Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP to make it compatible with ts-jest 23.10 and remove regexp replacers #201

Closed
wants to merge 1 commit into from

Conversation

huafu
Copy link

@huafu huafu commented Oct 17, 2018

DO NOT MERGE, this is a WIP which I do not have time to continue just right now

see #195

@thymikee
Copy link
Owner

Awesome, waiting for your availability then :)

@wtho
Copy link
Collaborator

wtho commented Nov 25, 2018

So to push this PR a bit

(and maybe start helping out)

As I see what is still missing, it is just a single transformer has to look for the @Component-Decorator and checks if there are

  • styles
  • styleUrls
  • template
  • templateUrl

Then the transformer has to

  • Replace the styles with an empty string
  • Replace styleUrls with an empty array
  • Add the inline template somehow (did this work in the old processor?)
  • Add the HTML file as require statement to the node

I wonder if adding the HTML as require is sufficient to make ts-jest load the html, or if it has to be added to the context in some other way, any ideas?

@ahnpnl
Copy link
Collaborator

ahnpnl commented Nov 25, 2018

inline template works in the current preprocessor. Regarding to adding the HTML file I have no idea because the current preprocessor doesn't do that as far as I'm concerned.

@wtho
Copy link
Collaborator

wtho commented Nov 25, 2018

Ok, as @huafu stated in the comments of the PR's preprocessor.js, the inline html part is handled by ts-jest.

As far as I understand it, the current preprocessor checks for templateUrl and replaces it with an inlined template: require(...)-statement:

const TEMPLATE_URL_REGEX = /templateUrl\s*:\s*('|"|`)(\.\/){0,}(.*)('|"|`)/g;

.replace(TEMPLATE_URL_REGEX, 'template: require($1./$3$4)')

I will have a try to implement it as an AST transformer.

@wtho
Copy link
Collaborator

wtho commented Nov 27, 2018

I am done with the transformer, but need some instructions:

  • Should I open a new PR, or do you, @huafu, want to include my commit in yours? Probably depends on how much time you currently have. I forked from your branch and added one commit so far.
  • These changes will be a breaking change (transitive of ts-jest's breaking change, suppose users of this library modified the ts-jest config) as ts-jest changed. I think v7 should be published with this change, what do you suggest? Note: I have not updated the Angular packages in the example app to v7, I feel like this should be done in a different PR.
  • I wrote the transformer in TS, which was easier for me. I added a build step to compile the TypeScript, and called in the prepare-hook. I hope this is ok.
  • I cannot make the example app pass the tests, as it is inside the preset repo, and as it references the preset using .., the module loader cannot find the angular/zone.js packages referenced inside jest-preset-angular/index.js, as they are not dependencies of jest-preset-angular, but outside the example app's folder. The only way I see to make this work is to map all these packages in tsconfig.json explicitly to the subproject's dependencies, but this will result in something other users cannot simply copy & paste (and I am not sure if i works, have not tried it).
    In my eyes the real issue here is that the inner app references the published version in example/package.json (and its dependencies) on npm instead of the version in the repo, but we have a breaking change in the dependency ts-jest now and it cannot work with the old dependency that way.
    It works using "jest-preset-angular": "github:wtho/jest-preset-angular#ts-jest-23-10", (and building it, which will happen for us on publish via prepare), so once this will be merged and published, it will work with referencing the latest version of the package.

Implementation Details:

  • The transformer looks for any Class Decorator (not just the ones named Component), as some folks might do import { Component as CustomDecorator } from '@core/angular'
  • It checks inside all Class Decorators for assignments to
    • templateUrl with a string literal as value, and changes it to template: require(<same string literal>)
    • styleUrls and sets the initializer to an emtpy array
    • styles and sets the initializer to an emtpy array
  • If there would be another Decorator with one of these properties, they would also be transformed (have not heard why this should be the case)
  • If the argument is constructed outside the Decorator, it will not be transformed, example:
    const componentArg = { templateUrl: './some-angular.component.ts' };
    
    @Component(componentArg)
    class SomeAngularClass { }

@ahnpnl
Copy link
Collaborator

ahnpnl commented Nov 27, 2018

hi @wtho, thank you very much for your effort. In my opinion, I think:

  • Fork the current work of @huafu and create a new PR and refer this PR from it seems to be a good way to do.
  • Indeed the changes will be breaking because of ts-jest. Since Angular already released v7, we can release your changes in v7 of this preset as well. Would you please add this change to CHANGELOG ?
  • I think it's ok to leave a .ts file and compile it into .js.
  • Indeed the example app refers to npm package. I think the ideal situation we can have is running pre-build script before running the all the tests inside this repo. But I think it should be in another PR. We can run some tests against your branch to make sure the changes are fine before merging into master.

@thymikee thymikee closed this in #204 Dec 4, 2018
thymikee pushed a commit that referenced this pull request Dec 4, 2018
#204)

Closes #195 and closes #201

### Breaking Change
This is a breaking change as Configuration Interface changes ([see ts-jest v23.10 docs](https://kulshekhar.github.io/ts-jest/user/config/#ts-jest-options))

This PR is built upon @huafu's #201, kudos to him for setting up everything and pointing out what was still to be done. Transformer and test are also heavily inspired by his examples in ts-jest. Also see the PR for more information.

### Implementation Details
Like the Regex, all the transformer does is transform
* `templateUrl: <PATH>` to `template: require(<PATH>)`
* `styles: <ANYTHING>` to `styles: []` 
* `styleUrls <ANYTHING>` to `styleUrls: []`

For more information see the comments in the [transformer file](https://github.com/wtho/jest-preset-angular/blob/55bcfdb993d1dc511611553995ff566d64ea6944/src/InlineHtmlStripStylesTransformer.ts) or #201.

### Edge Cases
I had to make some decisions on how strict the astTransformer is, I decided for this, but I am open to discussion:
**Works**
```ts
import { Component as Cmp } from '@angular/core';
@cmp({
  templateUrl: './some-path.html'
})
class AngularComp { }
```
Caveat - this also gets transformed
```ts
@SomeOtherDecorator({
  templateUrl: './some-path.html'
})
class SomeClass { }
```

**Does not work**
```ts
const componentArgs = {
  templateUrl: './some-path.html'
}
@component(componentArgs)
class AngularComp { }
```

### Additional Notes
* Run unit tests for the transformer with `npm test`
* The transformer was written in TypeScript. A `prepare`-script for was added, which compiles it to JS before publishing and after `npm install`.
* `preprocessor.js` and its unit tests were removed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants