Skip to content

No automatic override for imports on standalone components #306

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

Closed
jadengis opened this issue Jul 4, 2022 · 4 comments · Fixed by #307
Closed

No automatic override for imports on standalone components #306

jadengis opened this issue Jul 4, 2022 · 4 comments · Fixed by #307
Labels

Comments

@jadengis
Copy link
Contributor

jadengis commented Jul 4, 2022

Problem

For standalone components, we define compiler scope like

@Component({
  selector: 'app-foo',
  template: `...`,
  standalone: true,
  imports: [SomeComponent, SomeModule]
})
export class FooComponent {}

When using angular testing library, define component compilation scope using the declarations and imports property on the render function.

describe('test', async () => {
  await render(FooComponent, { declarations: [MockSomeComponent], imports: [...]})
})

However, this does not overwrite the imports property of standalone components.

Workaround

It is possible to manually override the imports property on a standalone component using TestBed.

beforeEach(() => {
  TestBed.configureTestingModule({
    imports: [FooComponent]
  })
  TestBed.overrideComponent(FooComponent, {set: {imports: mockImports}})
})

describe('another test', async () => {
  await render(FooComponent, {excludeComponentDeclaration: true})
})

Proposed Solution

Perhaps we can use TestBed.overrideComponent to swap the imports already on a standalone component for the imports array passed into render. Perhaps this can be guarded be a configuration flag like overrideComponentImports.

I might whip up a PR with this idea but just wanted to briefly discuss if this makes sense before putting in the work. Thanks!

@timdeschryver
Copy link
Member

I'm in favor of adding a componentImports property.

But I think this could get complicated if a child component also has its own imports that need to be mocked. We should keep that in mind, and try to find a solution for that as well.
To be honest, I'm not sure how to tackle that 😅

@jadengis
Copy link
Contributor Author

jadengis commented Jul 6, 2022

I've taken a first stab at this in #307 and got it working. Would love some feedback on the API. 🙏

But I think this could get complicated if a child component also has its own imports that need to be mocked
I don't think this is a concern because you should be able to simple replace the child component with a mock version and skip all its dependencies.

For something more complicated like rendering with a template where you aren't passing in a specific component to override imports on, it might be possible to iterate through the list of specified imports and override a specific import on each standalone component. Something like:

imports.forEach(token => {
  if(isStandalone(token)) {
    TestBed.overrideComponent(token, {add: {imports: [MockImportComponent]}, remove: {imports: [RealImportComponent})
  }
})

Where you could pass in as an option some bindings of which classes to replace with with mocks.

I honestly don't know how much of a value add that is.

@timdeschryver
Copy link
Member

We can tackle it when it becomes a problem 😅.
Iterating over the imports to replace all components might not work though, I was thinking more about an API where you could provide the componentImport for each component individually.

@github-actions
Copy link

github-actions bot commented Jul 6, 2022

🎉 This issue has been resolved in version 12.1.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

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.

2 participants