diff --git a/app/angular/package.json b/app/angular/package.json index 33a4041bfdad..253fdf76dfeb 100644 --- a/app/angular/package.json +++ b/app/angular/package.json @@ -65,6 +65,7 @@ "regenerator-runtime": "^0.13.7", "sass-loader": "^10.1.0", "strip-json-comments": "3.1.1", + "telejson": "^5.3.2", "ts-dedent": "^2.0.0", "ts-loader": "^8.0.14", "tsconfig-paths-webpack-plugin": "^3.3.0", diff --git a/app/angular/src/client/preview/angular-beta/AbstractRenderer.ts b/app/angular/src/client/preview/angular-beta/AbstractRenderer.ts index 8260f8856244..8dbaaf5b1c41 100644 --- a/app/angular/src/client/preview/angular-beta/AbstractRenderer.ts +++ b/app/angular/src/client/preview/angular-beta/AbstractRenderer.ts @@ -3,6 +3,7 @@ import { enableProdMode, NgModule, PlatformRef } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BehaviorSubject, Subject } from 'rxjs'; +import { stringify } from 'telejson'; import { ICollection, StoryFnAngularReturnType } from '../types'; import { Parameters } from '../types-6-0'; import { createStorybookModule, getStorybookModuleMetadata } from './StorybookModule'; @@ -160,7 +161,7 @@ export abstract class AbstractRenderer { const currentStoryRender = { storyFnAngular, - moduleMetadataSnapshot: JSON.stringify(moduleMetadata), + moduleMetadataSnapshot: stringify(moduleMetadata), }; this.previousStoryRenderInfo = currentStoryRender; diff --git a/app/angular/src/client/preview/angular-beta/RendererService.test.ts b/app/angular/src/client/preview/angular-beta/RendererService.test.ts index 802ac6039382..920eb8f4d001 100644 --- a/app/angular/src/client/preview/angular-beta/RendererService.test.ts +++ b/app/angular/src/client/preview/angular-beta/RendererService.test.ts @@ -57,6 +57,29 @@ describe('RendererService', () => { ); }); + it('should handle circular reference in moduleMetadata', async () => { + class Thing { + token: Thing; + + constructor() { + this.token = this; + } + } + const token = new Thing(); + + await rendererService.render({ + storyFnAngular: { + template: '🦊', + props: {}, + moduleMetadata: { providers: [{ provide: 'foo', useValue: token }] }, + }, + forced: false, + parameters: {} as any, + }); + + expect(document.body.getElementsByTagName('storybook-wrapper')[0].innerHTML).toBe('🦊'); + }); + describe('when forced=true', () => { beforeEach(async () => { // Init first render diff --git a/app/angular/src/client/preview/angular-beta/RendererService.ts b/app/angular/src/client/preview/angular-beta/RendererService.ts index 58144ac66a26..9909cf0f24ae 100644 --- a/app/angular/src/client/preview/angular-beta/RendererService.ts +++ b/app/angular/src/client/preview/angular-beta/RendererService.ts @@ -3,6 +3,7 @@ import { enableProdMode, NgModule, PlatformRef } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BehaviorSubject, Subject } from 'rxjs'; +import { stringify } from 'telejson'; import { ICollection, StoryFnAngularReturnType } from '../types'; import { Parameters } from '../types-6-0'; import { createStorybookModule, getStorybookModuleMetadata } from './StorybookModule'; @@ -154,7 +155,7 @@ export class RendererService { this.currentStoryRender = { storyFnAngular, - moduleMetadataSnapshot: JSON.stringify(moduleMetadata), + moduleMetadataSnapshot: stringify(moduleMetadata), }; if ( diff --git a/yarn.lock b/yarn.lock index 7a461d218ee8..2e7f9da32db0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6170,6 +6170,7 @@ __metadata: regenerator-runtime: ^0.13.7 sass-loader: ^10.1.0 strip-json-comments: 3.1.1 + telejson: ^5.3.2 ts-dedent: ^2.0.0 ts-jest: ^26.4.4 ts-loader: ^8.0.14