Let's say I have an Angular component with a getDataFromBackend method.
In my storybook I want getDataFromBackend to always return a mock.
Is there a way to override this method?
Mh I don't think overriding is possible. What you are trying to achieve is kind of the same as trying to mock things for unit tests. Without seeing your code I'd try something like this
@Injectable()
export class DataBackendService {
getDataFromBackend() {
// do the network request here
}
}
@Component({
...
})
export class SmartComponent {
constructor(private dataBackendService: DataBackendService) {}
getData() {
return this.dataBackendService.getDataFromBackend();
}
}
In your story you can now do this
class StubService {
getDataFromBackend() {
return { /* static test data here */ }
}
}
storiesOf('YourStory', module).addDecorator(
moduleMetadata({
provides: [
{ provide: DataBackendService, useClass: StubService }
]
declarations: [WithStoreComponent],
})
What happens here? Well Angular magic! You can replace a service with another implementation
See https://angular.io/guide/dependency-injection-providers
Here's a stackblitz example https://stackblitz.com/edit/angular-6xhma8ng-dep-providers?file=src/app/app.component.ts
Unfortunately the service is not injected in in this case. I have no control of the component.
Right now I am using a proxy approach similar to this: https://github.com/storybookjs/storybook/issues/208#issuecomment-472359026
But even with the proxy approach, it would be better to be able to do proxy per story instead of per the whole project.
In Jasmine, we can use spyOn to override specific methods when testing. It would be nice to have similar mechanism in storybook.
Storybook just wraps an Angular host and puts a story inside this wrapper. You are of course free to instantiate your component using the angular ComponentFactory or wrap it inside a demo component. Jasmine tests also instantiate the component in order to give you an instance that you can spyOn
Maybe this helps?
@Component({
template: `<your-actual-component></your-actual-component>`
})
class DemoWrapperComponent {
@ViewChild(YourActualComponent, { static: false }) componentRef: YourActualComponent
ngOnInit() {
componentRef['methodYouWantToOverride'] = () => { return "do crazy stuff" };
}
}
Haven't tested it, not sure if it works!
@kroeder That works! Thanks so much for your help!!