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

Feature Request: Allow ng-mocks to work with standalone components #2687

Closed
DmitryEfimenko opened this issue Jun 3, 2022 · 14 comments · Fixed by #2751
Closed

Feature Request: Allow ng-mocks to work with standalone components #2687

DmitryEfimenko opened this issue Jun 3, 2022 · 14 comments · Fixed by #2751
Assignees
Labels

Comments

@DmitryEfimenko
Copy link

Describe the feature or problem you'd like to solve

Angular v14 is released and the standalone components are now available.
We need support for mocking of standalone component dependencies (anything that's inside of the imports property of the @Component decorator).

Proposed solution

It appears we should consider the standalone components affect existing APIs in the ng-mocks:

  1. MockComponent
  2. MockBuilder

The following discussion will use MyStandaloneComponent as defined below:

@Component({
  standalone: true,
  imports: [CoolModule, FooComponent, BarDirective, BazPipe],
  template: `I'm a standalone component!`
})
export class MyStandaloneComponent {}

1. MockComponent

I think MockComponent(MyStandaloneComponent) should behave exactly like it used to - the component should be mocked. However, in addition, all the members of the imports property should also be mocked

2. MockBuilder

MockBuilder(MyStandaloneComponent) should keep the implementation of the MyStandaloneComponent itself. However, all the dependencies specified in the imports property should be mocked.
This would go well with the best practices of "shallow" component testing. If there's a need to "keep" one of the dependency of the MyStandaloneComponent, the developer can leverage the existing .keep(BarDirective) functionality.

Additional context

@DmitryEfimenko DmitryEfimenko added the enhancement New feature or request label Jun 3, 2022
@DmitryEfimenko
Copy link
Author

FYI, before working on this issue we might want to see how this open issue in Angular will unwrap.

@satanTime
Copy link
Member

Agree, makes sense.

Is it a syntax sugar for a module with single export?

@NgModule({
  imports: [CoolModule, FooComponent, BarDirective, BazPipe],
  declarations: [MyStandaloneComponent],
  exports: [MyStandaloneComponent]
})
class StandaloneComponentModule {}

Sorry, I haven't code with angular for a year already and missed this feature :)

I'm asking, because it looks simpler to convert it like that in MockBuilder.
In MockComponent, I can simply remove all imports, just need to check if they are available in nested components.

@DmitryEfimenko
Copy link
Author

yeah, I think that's pretty much it. I believe it's not quite 1:1 comparison. There are some nuances, but for the purposes of unit testing I don't think these nuances are important.

@Dominik-Kriese
Copy link

Hi,

just to push this topic a little:

I use ng-mocks a lot in conjunction with jests snapshot testing feature to reduce the bloat of rendered Angular Material Components as well as predictable false negatives in my test suite. Would love to use standalone components there, but i don't as the drawbacks in testing are to high for me at the moment.

PS: tanks for this awesome lib, it helps a lot and speeds up things by quite a margin :)

@satanTime
Copy link
Member

After some research:

Anything imported in a standalone declaration cannot be used anywhere else. The exception is services. They are available in parent declarations.

So if we mock a standalone declaration, it should simply provide provides from all imported modules.

@satanTime
Copy link
Member

satanTime commented Jun 16, 2022

Hi @DmitryEfimenko, could I ask you test current implementation?

ng-mocks.zip

Now it keeps the component and mocks its imports if the component is standalone. You can keep, exclude etc:

// It does mock imports
MockBuilder(StandaloneComponent).keep(ImportedPipe);

if you want to keep its imports too, then you need to add its config separately or use chain methods:

// It doesn't mock imports
MockBuilder(StandaloneComponent).keep(StandaloneComponent, {shallow: false});

// It doesn't mock imports
MockBuilder().keep(StandaloneComponent);

satanTime added a commit to satanTime/ng-mocks that referenced this issue Jun 16, 2022
satanTime added a commit to satanTime/ng-mocks that referenced this issue Jun 16, 2022
satanTime added a commit to satanTime/ng-mocks that referenced this issue Jun 16, 2022
satanTime added a commit to satanTime/ng-mocks that referenced this issue Jun 16, 2022
satanTime added a commit to satanTime/ng-mocks that referenced this issue Jun 16, 2022
@DmitryEfimenko
Copy link
Author

I don't quite have a playground for standalone components set up yet, but I'll get it going and give it a spin. Thanks!

@satanTime
Copy link
Member

satanTime commented Jun 17, 2022

Ah, oki then. It should do the job :) I'm waiting for the update of primeng to support A14 and will release the next major version of ng-mocks.

@satanTime
Copy link
Member

Ah, also forgot.

@Dominik-Kriese, if you have standalone things in your project, could you give a try to the latest updates: ng-mocks.zip?

Thank you in advance!

satanTime added a commit to satanTime/ng-mocks that referenced this issue Jun 17, 2022
@Dominik-Kriese
Copy link

@satanTime I only had very small and dumb components as standalone components due to the risks of low test coverage, but those seem to work fine with the new updates provided by you :)

@satanTime
Copy link
Member

Great. Thanks.

Let's hope primeng will be released soon.

@DmitryEfimenko
Copy link
Author

you've mentioned primeng a couple times. I'm curious, why ng-mocks release is waiting for the release of primeng? What's the relationship?

@satanTime
Copy link
Member

satanTime commented Jun 17, 2022

It's a historical thing from the times when CI ran only 4 parallel jobs. To reduce the time for ensuring that e2e tests with 3rd-party libs work correctly, node_modules for the lib and e2e is shared and therefore depends on all 3rd-party libraries.

Now, it's possible to add one more CI step to install node_modules separately for e2e tests.
However, I hope primeng will be faster than my patience and I won't need to do anything, only wait :)

satanTime added a commit to satanTime/ng-mocks that referenced this issue Jun 18, 2022
satanTime added a commit to satanTime/ng-mocks that referenced this issue Jun 18, 2022
satanTime added a commit to satanTime/ng-mocks that referenced this issue Jun 18, 2022
satanTime added a commit to satanTime/ng-mocks that referenced this issue Jun 18, 2022
satanTime added a commit that referenced this issue Jun 18, 2022
feat(core): Support of standalone declarations #2687
@satanTime
Copy link
Member

v14.0.0 has been released and contains a fix for the issue. Feel free to reopen the issue or to submit a new one if you meet any problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants