I have an Angular component that has a component level provider.
@Component({
selector: 'storybook-di-component',
templateUrl: './di.component.html',
providers: [{ provide: TEST_TOKEN, useValue: 123 }],
})
export class DiComponent {
@Input()
title: string;
constructor(
protected injector: Injector,
protected elRef: ElementRef,
@Inject(TEST_TOKEN) protected testToken: number
) {}
In such cases, how do I get storybook to inject a different provider so that I can provide an alternate/mock service? For example, in the DiComponent above, what if I wanted to inject { provide: TEST_TOKEN, useValue: 456 }
instead?
The real world use case is that I'm using ngrx/component-store and need to provide a dummy, prepopulated store for the component.
(Additional info:) Injecting it at module level (like below) doesn't work as the component still goes and creates it's own instance of the provider:
moduleMetadata: {
providers: [
{ provide: StateStore, useValue: stateStore }
],
imports: [...],
},
I ended up solving this problem using a low tech approach.
.stories.ts
filesuper(...)
with the injected services + the mocked service.Given that my actual need was to inject a mock of the ngrx/component-store
my stories.ts
has something like the following now:
const stateStore = new RecordSuggestionsPageStore(mockSuggestionsService);
stateStore.setState(() => ({
selectableRecords: [
{ name: "John Legend", recordType: "employee" },
{ name: "Allan Davies", recordType: "employee" },
]
}));
@Component({
selector: "myapp-suggested-records-page",
templateUrl: "./suggested-records-page.component.html",
styleUrls: ["./suggested-records-page.component.scss"]
})
class SuggestedRecordsPageComponentStubbed extends SuggestedRecordsPageComponent {
constructor(router: Router) {
super(stateStore, router);
}
}