mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-04 13:51:28 +08:00
260 lines
8.8 KiB
TypeScript
260 lines
8.8 KiB
TypeScript
import { Component, EventEmitter, Input, NgModule, Output, Type } from '@angular/core';
|
|
|
|
import { TestBed } from '@angular/core/testing';
|
|
import { BrowserModule } from '@angular/platform-browser';
|
|
import { BehaviorSubject } from 'rxjs';
|
|
import { ICollection } from '../types';
|
|
import { getStorybookModuleMetadata } from './StorybookModule';
|
|
|
|
describe('StorybookModule', () => {
|
|
describe('getStorybookModuleMetadata', () => {
|
|
describe('with simple component', () => {
|
|
@Component({
|
|
selector: 'foo',
|
|
template: `
|
|
<p id="input">{{ input }}</p>
|
|
<p id="inputBindingPropertyName">{{ localPropertyName }}</p>
|
|
<p id="localProperty">{{ localProperty }}</p>
|
|
<p id="localFunction">{{ localFunction() }}</p>
|
|
<p id="output" (click)="output.emit('outputEmitted')"></p>
|
|
<p id="outputBindingPropertyName" (click)="localOutput.emit('outputEmitted')"></p>
|
|
`,
|
|
})
|
|
class FooComponent {
|
|
@Input()
|
|
public input: string;
|
|
|
|
@Input('inputBindingPropertyName')
|
|
public localPropertyName: string;
|
|
|
|
@Output()
|
|
public output = new EventEmitter<string>();
|
|
|
|
@Output('outputBindingPropertyName')
|
|
public localOutput = new EventEmitter<string>();
|
|
|
|
public localProperty: string;
|
|
|
|
public localFunction = () => '';
|
|
}
|
|
|
|
it('should initialize inputs', async () => {
|
|
const props = {
|
|
input: 'input',
|
|
inputBindingPropertyName: 'inputBindingPropertyName',
|
|
localProperty: 'localProperty',
|
|
localFunction: () => 'localFunction',
|
|
};
|
|
|
|
const ngModule = getStorybookModuleMetadata(
|
|
{ storyFnAngular: { props }, parameters: { component: FooComponent } },
|
|
new BehaviorSubject(props)
|
|
);
|
|
|
|
const { fixture } = await configureTestingModule(ngModule);
|
|
fixture.detectChanges();
|
|
|
|
expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(props.input);
|
|
expect(fixture.nativeElement.querySelector('p#inputBindingPropertyName').innerHTML).toEqual(
|
|
props.inputBindingPropertyName
|
|
);
|
|
expect(fixture.nativeElement.querySelector('p#localProperty').innerHTML).toEqual(
|
|
props.localProperty
|
|
);
|
|
expect(fixture.nativeElement.querySelector('p#localFunction').innerHTML).toEqual(
|
|
props.localFunction()
|
|
);
|
|
});
|
|
|
|
it('should initialize outputs', async () => {
|
|
let expectedOutputValue: string;
|
|
let expectedOutputBindingValue: string;
|
|
const props = {
|
|
output: (value: string) => {
|
|
expectedOutputValue = value;
|
|
},
|
|
outputBindingPropertyName: (value: string) => {
|
|
expectedOutputBindingValue = value;
|
|
},
|
|
};
|
|
|
|
const ngModule = getStorybookModuleMetadata(
|
|
{ storyFnAngular: { props }, parameters: { component: FooComponent } },
|
|
new BehaviorSubject(props)
|
|
);
|
|
|
|
const { fixture } = await configureTestingModule(ngModule);
|
|
fixture.detectChanges();
|
|
|
|
fixture.nativeElement.querySelector('p#output').click();
|
|
fixture.nativeElement.querySelector('p#outputBindingPropertyName').click();
|
|
|
|
expect(expectedOutputValue).toEqual('outputEmitted');
|
|
expect(expectedOutputBindingValue).toEqual('outputEmitted');
|
|
});
|
|
|
|
it('should change inputs if storyProps$ Subject emit', async () => {
|
|
const initialProps = {
|
|
input: 'input',
|
|
};
|
|
const storyProps$ = new BehaviorSubject(initialProps);
|
|
|
|
const ngModule = getStorybookModuleMetadata(
|
|
{ storyFnAngular: { props: initialProps }, parameters: { component: FooComponent } },
|
|
storyProps$
|
|
);
|
|
const { fixture } = await configureTestingModule(ngModule);
|
|
fixture.detectChanges();
|
|
|
|
expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(
|
|
initialProps.input
|
|
);
|
|
expect(fixture.nativeElement.querySelector('p#inputBindingPropertyName').innerHTML).toEqual(
|
|
''
|
|
);
|
|
|
|
const newProps = {
|
|
input: 'new input',
|
|
inputBindingPropertyName: 'new inputBindingPropertyName',
|
|
localProperty: 'new localProperty',
|
|
localFunction: () => 'new localFunction',
|
|
};
|
|
storyProps$.next(newProps);
|
|
fixture.detectChanges();
|
|
|
|
expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(newProps.input);
|
|
expect(fixture.nativeElement.querySelector('p#inputBindingPropertyName').innerHTML).toEqual(
|
|
newProps.inputBindingPropertyName
|
|
);
|
|
expect(fixture.nativeElement.querySelector('p#localProperty').innerHTML).toEqual(
|
|
newProps.localProperty
|
|
);
|
|
expect(fixture.nativeElement.querySelector('p#localFunction').innerHTML).toEqual(
|
|
newProps.localFunction()
|
|
);
|
|
});
|
|
|
|
it('should override outputs if storyProps$ Subject emit', async () => {
|
|
let expectedOutputValue;
|
|
let expectedOutputBindingValue;
|
|
const initialProps = {
|
|
output: (value: string) => {
|
|
expectedOutputValue = value;
|
|
},
|
|
outputBindingPropertyName: (value: string) => {
|
|
expectedOutputBindingValue = value;
|
|
},
|
|
};
|
|
const storyProps$ = new BehaviorSubject(initialProps);
|
|
|
|
const ngModule = getStorybookModuleMetadata(
|
|
{ storyFnAngular: { props: initialProps }, parameters: { component: FooComponent } },
|
|
storyProps$
|
|
);
|
|
const { fixture } = await configureTestingModule(ngModule);
|
|
fixture.detectChanges();
|
|
|
|
const newProps = {
|
|
input: 'new input',
|
|
output: () => {
|
|
expectedOutputValue = 'should be called';
|
|
},
|
|
outputBindingPropertyName: () => {
|
|
expectedOutputBindingValue = 'should be called';
|
|
},
|
|
};
|
|
storyProps$.next(newProps);
|
|
fixture.detectChanges();
|
|
|
|
fixture.nativeElement.querySelector('p#output').click();
|
|
fixture.nativeElement.querySelector('p#outputBindingPropertyName').click();
|
|
|
|
expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(newProps.input);
|
|
expect(expectedOutputValue).toEqual('should be called');
|
|
expect(expectedOutputBindingValue).toEqual('should be called');
|
|
});
|
|
|
|
it('should change template inputs if storyProps$ Subject emit', async () => {
|
|
const initialProps = {
|
|
color: 'red',
|
|
input: 'input',
|
|
};
|
|
const storyProps$ = new BehaviorSubject<ICollection>(initialProps);
|
|
|
|
const ngModule = getStorybookModuleMetadata(
|
|
{
|
|
storyFnAngular: {
|
|
props: initialProps,
|
|
template: '<p [style.color]="color"><foo [input]="input"></foo></p>',
|
|
},
|
|
parameters: { component: FooComponent },
|
|
},
|
|
storyProps$
|
|
);
|
|
const { fixture } = await configureTestingModule(ngModule);
|
|
fixture.detectChanges();
|
|
expect(fixture.nativeElement.querySelector('p').style.color).toEqual('red');
|
|
expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(
|
|
initialProps.input
|
|
);
|
|
|
|
const newProps = {
|
|
color: 'black',
|
|
input: 'new input',
|
|
};
|
|
storyProps$.next(newProps);
|
|
fixture.detectChanges();
|
|
|
|
expect(fixture.nativeElement.querySelector('p').style.color).toEqual('black');
|
|
expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(newProps.input);
|
|
});
|
|
});
|
|
|
|
describe('with component without selector', () => {
|
|
@Component({
|
|
template: `The content`,
|
|
})
|
|
class WithoutSelectorComponent {}
|
|
|
|
it('should display the component', async () => {
|
|
const props = {};
|
|
|
|
const ngModule = getStorybookModuleMetadata(
|
|
{
|
|
storyFnAngular: {
|
|
props,
|
|
moduleMetadata: { entryComponents: [WithoutSelectorComponent] },
|
|
},
|
|
parameters: { component: WithoutSelectorComponent },
|
|
},
|
|
new BehaviorSubject<ICollection>(props)
|
|
);
|
|
|
|
const { fixture } = await configureTestingModule(ngModule);
|
|
fixture.detectChanges();
|
|
|
|
expect(fixture.nativeElement.innerHTML).toContain('The content');
|
|
});
|
|
});
|
|
});
|
|
|
|
async function configureTestingModule(ngModule: NgModule) {
|
|
await TestBed.configureTestingModule({
|
|
declarations: ngModule.declarations,
|
|
providers: ngModule.providers,
|
|
})
|
|
.overrideModule(BrowserModule, {
|
|
set: {
|
|
entryComponents: [...ngModule.entryComponents],
|
|
},
|
|
})
|
|
.compileComponents();
|
|
|
|
const fixture = TestBed.createComponent(ngModule.bootstrap[0] as Type<unknown>);
|
|
|
|
return {
|
|
fixture,
|
|
};
|
|
}
|
|
});
|