1 | "use strict";
|
2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
6 | return c > 3 && r && Object.defineProperty(target, key, r), r;
|
7 | };
|
8 | var __metadata = (this && this.__metadata) || function (k, v) {
|
9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
10 | };
|
11 | Object.defineProperty(exports, "__esModule", { value: true });
|
12 | const core_1 = require("@angular/core");
|
13 | const testing_1 = require("@angular/core/testing");
|
14 | const rxjs_1 = require("rxjs");
|
15 | const StorybookModule_1 = require("./StorybookModule");
|
16 | const StorybookProvider_1 = require("./StorybookProvider");
|
17 | const PropertyExtractor_1 = require("./utils/PropertyExtractor");
|
18 | describe('StorybookModule', () => {
|
19 | describe('getStorybookModuleMetadata', () => {
|
20 | describe('with simple component', () => {
|
21 | let FooComponent = class FooComponent {
|
22 | constructor() {
|
23 | this.output = new core_1.EventEmitter();
|
24 | this.localOutput = new core_1.EventEmitter();
|
25 | this.localFunction = () => '';
|
26 | this.setterCallNb = 0;
|
27 | }
|
28 | set setter(value) {
|
29 | this.setterCallNb += 1;
|
30 | }
|
31 | };
|
32 | __decorate([
|
33 | (0, core_1.Input)(),
|
34 | __metadata("design:type", String)
|
35 | ], FooComponent.prototype, "input", void 0);
|
36 | __decorate([
|
37 | (0, core_1.Input)('inputBindingPropertyName'),
|
38 | __metadata("design:type", String)
|
39 | ], FooComponent.prototype, "localPropertyName", void 0);
|
40 | __decorate([
|
41 | (0, core_1.Input)(),
|
42 | __metadata("design:type", String),
|
43 | __metadata("design:paramtypes", [String])
|
44 | ], FooComponent.prototype, "setter", null);
|
45 | __decorate([
|
46 | (0, core_1.Output)(),
|
47 | __metadata("design:type", Object)
|
48 | ], FooComponent.prototype, "output", void 0);
|
49 | __decorate([
|
50 | (0, core_1.Output)('outputBindingPropertyName'),
|
51 | __metadata("design:type", Object)
|
52 | ], FooComponent.prototype, "localOutput", void 0);
|
53 | FooComponent = __decorate([
|
54 | (0, core_1.Component)({
|
55 | selector: 'foo',
|
56 | template: `
|
57 | <p id="input">{{ input }}</p>
|
58 | <p id="inputBindingPropertyName">{{ localPropertyName }}</p>
|
59 | <p id="setterCallNb">{{ setterCallNb }}</p>
|
60 | <p id="localProperty">{{ localProperty }}</p>
|
61 | <p id="localFunction">{{ localFunction() }}</p>
|
62 | <p id="output" (click)="output.emit('outputEmitted')"></p>
|
63 | <p id="outputBindingPropertyName" (click)="localOutput.emit('outputEmitted')"></p>
|
64 | `,
|
65 | })
|
66 | ], FooComponent);
|
67 | it('should initialize inputs', async () => {
|
68 | const props = {
|
69 | input: 'input',
|
70 | inputBindingPropertyName: 'inputBindingPropertyName',
|
71 | localProperty: 'localProperty',
|
72 | localFunction: () => 'localFunction',
|
73 | };
|
74 | const analyzedMetadata = new PropertyExtractor_1.PropertyExtractor({}, FooComponent);
|
75 | const application = (0, StorybookModule_1.getApplication)({
|
76 | storyFnAngular: { props },
|
77 | component: FooComponent,
|
78 | targetSelector: 'my-selector',
|
79 | analyzedMetadata,
|
80 | });
|
81 | const { fixture } = await configureTestingModule({
|
82 | imports: [application],
|
83 | providers: [(0, StorybookProvider_1.storyPropsProvider)(new rxjs_1.BehaviorSubject(props))],
|
84 | });
|
85 | fixture.detectChanges();
|
86 | expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(props.input);
|
87 | expect(fixture.nativeElement.querySelector('p#inputBindingPropertyName').innerHTML).toEqual(props.inputBindingPropertyName);
|
88 | expect(fixture.nativeElement.querySelector('p#localProperty').innerHTML).toEqual(props.localProperty);
|
89 | expect(fixture.nativeElement.querySelector('p#localFunction').innerHTML).toEqual(props.localFunction());
|
90 | });
|
91 | it('should initialize outputs', async () => {
|
92 | let expectedOutputValue;
|
93 | let expectedOutputBindingValue;
|
94 | const props = {
|
95 | output: (value) => {
|
96 | expectedOutputValue = value;
|
97 | },
|
98 | outputBindingPropertyName: (value) => {
|
99 | expectedOutputBindingValue = value;
|
100 | },
|
101 | };
|
102 | const analyzedMetadata = new PropertyExtractor_1.PropertyExtractor({}, FooComponent);
|
103 | const application = (0, StorybookModule_1.getApplication)({
|
104 | storyFnAngular: { props },
|
105 | component: FooComponent,
|
106 | targetSelector: 'my-selector',
|
107 | analyzedMetadata,
|
108 | });
|
109 | const { fixture } = await configureTestingModule({
|
110 | imports: [application],
|
111 | providers: [(0, StorybookProvider_1.storyPropsProvider)(new rxjs_1.BehaviorSubject(props))],
|
112 | });
|
113 | fixture.detectChanges();
|
114 | fixture.nativeElement.querySelector('p#output').click();
|
115 | fixture.nativeElement.querySelector('p#outputBindingPropertyName').click();
|
116 | expect(expectedOutputValue).toEqual('outputEmitted');
|
117 | expect(expectedOutputBindingValue).toEqual('outputEmitted');
|
118 | });
|
119 | it('should change inputs if storyProps$ Subject emit', async () => {
|
120 | const initialProps = {
|
121 | input: 'input',
|
122 | inputBindingPropertyName: '',
|
123 | };
|
124 | const storyProps$ = new rxjs_1.BehaviorSubject(initialProps);
|
125 | const analyzedMetadata = new PropertyExtractor_1.PropertyExtractor({}, FooComponent);
|
126 | const application = (0, StorybookModule_1.getApplication)({
|
127 | storyFnAngular: { props: initialProps },
|
128 | component: FooComponent,
|
129 | targetSelector: 'my-selector',
|
130 | analyzedMetadata,
|
131 | });
|
132 | const { fixture } = await configureTestingModule({
|
133 | imports: [application],
|
134 | providers: [(0, StorybookProvider_1.storyPropsProvider)(storyProps$)],
|
135 | });
|
136 | fixture.detectChanges();
|
137 | expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(initialProps.input);
|
138 | expect(fixture.nativeElement.querySelector('p#inputBindingPropertyName').innerHTML).toEqual('');
|
139 | const newProps = {
|
140 | input: 'new input',
|
141 | inputBindingPropertyName: 'new inputBindingPropertyName',
|
142 | localProperty: 'new localProperty',
|
143 | localFunction: () => 'new localFunction',
|
144 | };
|
145 | storyProps$.next(newProps);
|
146 | fixture.detectChanges();
|
147 | expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(newProps.input);
|
148 | expect(fixture.nativeElement.querySelector('p#inputBindingPropertyName').innerHTML).toEqual(newProps.inputBindingPropertyName);
|
149 | expect(fixture.nativeElement.querySelector('p#localProperty').innerHTML).toEqual(newProps.localProperty);
|
150 | expect(fixture.nativeElement.querySelector('p#localFunction').innerHTML).toEqual(newProps.localFunction());
|
151 | });
|
152 | it('should override outputs if storyProps$ Subject emit', async () => {
|
153 | let expectedOutputValue;
|
154 | let expectedOutputBindingValue;
|
155 | const initialProps = {
|
156 | input: '',
|
157 | output: (value) => {
|
158 | expectedOutputValue = value;
|
159 | },
|
160 | outputBindingPropertyName: (value) => {
|
161 | expectedOutputBindingValue = value;
|
162 | },
|
163 | };
|
164 | const storyProps$ = new rxjs_1.BehaviorSubject(initialProps);
|
165 | const analyzedMetadata = new PropertyExtractor_1.PropertyExtractor({}, FooComponent);
|
166 | const application = (0, StorybookModule_1.getApplication)({
|
167 | storyFnAngular: { props: initialProps },
|
168 | component: FooComponent,
|
169 | targetSelector: 'my-selector',
|
170 | analyzedMetadata,
|
171 | });
|
172 | const { fixture } = await configureTestingModule({
|
173 | imports: [application],
|
174 | providers: [(0, StorybookProvider_1.storyPropsProvider)(storyProps$)],
|
175 | });
|
176 | fixture.detectChanges();
|
177 | const newProps = {
|
178 | input: 'new input',
|
179 | output: () => {
|
180 | expectedOutputValue = 'should be called';
|
181 | },
|
182 | outputBindingPropertyName: () => {
|
183 | expectedOutputBindingValue = 'should be called';
|
184 | },
|
185 | };
|
186 | storyProps$.next(newProps);
|
187 | fixture.detectChanges();
|
188 | fixture.nativeElement.querySelector('p#output').click();
|
189 | fixture.nativeElement.querySelector('p#outputBindingPropertyName').click();
|
190 | expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(newProps.input);
|
191 | expect(expectedOutputValue).toEqual('should be called');
|
192 | expect(expectedOutputBindingValue).toEqual('should be called');
|
193 | });
|
194 | it('should change template inputs if storyProps$ Subject emit', async () => {
|
195 | const initialProps = {
|
196 | color: 'red',
|
197 | input: 'input',
|
198 | };
|
199 | const storyProps$ = new rxjs_1.BehaviorSubject(initialProps);
|
200 | const analyzedMetadata = new PropertyExtractor_1.PropertyExtractor({}, FooComponent);
|
201 | const application = (0, StorybookModule_1.getApplication)({
|
202 | storyFnAngular: {
|
203 | props: initialProps,
|
204 | template: '<p [style.color]="color"><foo [input]="input"></foo></p>',
|
205 | },
|
206 | component: FooComponent,
|
207 | targetSelector: 'my-selector',
|
208 | analyzedMetadata,
|
209 | });
|
210 | const { fixture } = await configureTestingModule({
|
211 | imports: [application],
|
212 | providers: [(0, StorybookProvider_1.storyPropsProvider)(storyProps$)],
|
213 | });
|
214 | fixture.detectChanges();
|
215 | expect(fixture.nativeElement.querySelector('p').style.color).toEqual('red');
|
216 | expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(initialProps.input);
|
217 | const newProps = {
|
218 | color: 'black',
|
219 | input: 'new input',
|
220 | };
|
221 | storyProps$.next(newProps);
|
222 | fixture.detectChanges();
|
223 | expect(fixture.nativeElement.querySelector('p').style.color).toEqual('black');
|
224 | expect(fixture.nativeElement.querySelector('p#input').innerHTML).toEqual(newProps.input);
|
225 | });
|
226 | it('should call the Input() setter the right number of times', async () => {
|
227 | const initialProps = {
|
228 | setter: 'init',
|
229 | };
|
230 | const storyProps$ = new rxjs_1.BehaviorSubject(initialProps);
|
231 | const analyzedMetadata = new PropertyExtractor_1.PropertyExtractor({}, FooComponent);
|
232 | const application = (0, StorybookModule_1.getApplication)({
|
233 | storyFnAngular: { props: initialProps },
|
234 | component: FooComponent,
|
235 | targetSelector: 'my-selector',
|
236 | analyzedMetadata,
|
237 | });
|
238 | const { fixture } = await configureTestingModule({
|
239 | imports: [application],
|
240 | providers: [(0, StorybookProvider_1.storyPropsProvider)(storyProps$)],
|
241 | });
|
242 | fixture.detectChanges();
|
243 | expect(fixture.nativeElement.querySelector('p#setterCallNb').innerHTML).toEqual('1');
|
244 | const newProps = {
|
245 | setter: 'new setter value',
|
246 | };
|
247 | storyProps$.next(newProps);
|
248 | fixture.detectChanges();
|
249 | expect(fixture.nativeElement.querySelector('p#setterCallNb').innerHTML).toEqual('2');
|
250 | });
|
251 | });
|
252 | describe('with component without selector', () => {
|
253 | let WithoutSelectorComponent = class WithoutSelectorComponent {
|
254 | };
|
255 | WithoutSelectorComponent = __decorate([
|
256 | (0, core_1.Component)({
|
257 | template: `The content`,
|
258 | })
|
259 | ], WithoutSelectorComponent);
|
260 | it('should display the component', async () => {
|
261 | const props = {};
|
262 | const analyzedMetadata = new PropertyExtractor_1.PropertyExtractor({ entryComponents: [WithoutSelectorComponent] }, WithoutSelectorComponent);
|
263 | const application = (0, StorybookModule_1.getApplication)({
|
264 | storyFnAngular: {
|
265 | props,
|
266 | moduleMetadata: { entryComponents: [WithoutSelectorComponent] },
|
267 | },
|
268 | component: WithoutSelectorComponent,
|
269 | targetSelector: 'my-selector',
|
270 | analyzedMetadata,
|
271 | });
|
272 | const { fixture } = await configureTestingModule({
|
273 | imports: [application],
|
274 | providers: [(0, StorybookProvider_1.storyPropsProvider)(new rxjs_1.BehaviorSubject(props))],
|
275 | });
|
276 | fixture.detectChanges();
|
277 | expect(fixture.nativeElement.innerHTML).toContain('The content');
|
278 | });
|
279 | });
|
280 | it('should keep template with an empty value', async () => {
|
281 | let FooComponent = class FooComponent {
|
282 | };
|
283 | FooComponent = __decorate([
|
284 | (0, core_1.Component)({
|
285 | selector: 'foo',
|
286 | template: `Should not be displayed`,
|
287 | })
|
288 | ], FooComponent);
|
289 | const analyzedMetadata = new PropertyExtractor_1.PropertyExtractor({}, FooComponent);
|
290 | const application = (0, StorybookModule_1.getApplication)({
|
291 | storyFnAngular: { template: '' },
|
292 | component: FooComponent,
|
293 | targetSelector: 'my-selector',
|
294 | analyzedMetadata,
|
295 | });
|
296 | const { fixture } = await configureTestingModule({
|
297 | imports: [application],
|
298 | providers: [(0, StorybookProvider_1.storyPropsProvider)(new rxjs_1.BehaviorSubject({}))],
|
299 | });
|
300 | fixture.detectChanges();
|
301 | expect(fixture.nativeElement.innerHTML).toEqual('');
|
302 | });
|
303 | });
|
304 | async function configureTestingModule(ngModule) {
|
305 | await testing_1.TestBed.configureTestingModule(ngModule).compileComponents();
|
306 | const fixture = testing_1.TestBed.createComponent(ngModule.imports[0]);
|
307 | return {
|
308 | fixture,
|
309 | };
|
310 | }
|
311 | });
|