diff --git a/code/e2e-tests/addon-docs.spec.ts b/code/e2e-tests/addon-docs.spec.ts index 0f318f9f657d..ba04d5c99632 100644 --- a/code/e2e-tests/addon-docs.spec.ts +++ b/code/e2e-tests/addon-docs.spec.ts @@ -85,7 +85,7 @@ test.describe('addon-docs', () => { test('should provide source snippet', async ({ page }) => { // templateName is e.g. 'Vue-CLI (Default JS)' test.skip( - /^(vue3|vue-cli|preact)/i.test(`${templateName}`), + /^(vue-cli|preact)/i.test(`${templateName}`), `Skipping ${templateName}, which does not support dynamic source snippets` ); @@ -111,7 +111,6 @@ test.describe('addon-docs', () => { test('source snippet should not change in stories block', async ({ page }) => { const skipped = [ - 'vue3', 'vue-cli', 'preact', // SSv6 does not render stories in the correct order in our sandboxes @@ -157,6 +156,42 @@ test.describe('addon-docs', () => { await expect(storiesCode).toContainText('Basic'); }); + test('source snippet should change back to previous value in stories block', async ({ page }) => { + test.skip( + /^(lit|vue-cli|preact|angular|internal\/ssv6|ca)/i.test(`${templateName}`), + `Skipping ${templateName}, which does not support dynamic source snippets` + ); + + const sbPage = new SbPage(page); + await sbPage.navigateToStory('addons/docs/docspage/basic', 'docs'); + const root = sbPage.previewRoot(); + const toggles = root.locator('.docblock-code-toggle'); + + const toggle = await toggles.nth(0); + await toggle.click({ force: true }); + + const codes = root.locator('pre.prismjs'); + + const code = await codes.nth(0); + const text = await code.innerText(); + + await expect(text).toContain('Basic'); + + const labelControl = root.locator('textarea[name=label]'); + labelControl.fill('Changed'); + labelControl.blur(); + + // Check the Primary one has changed + await expect(code).toContainText('Changed'); + + // Change the value back + labelControl.fill('Basic'); + labelControl.blur(); + + // Check the Primary one has changed back + await expect(code).toContainText('Basic'); + }); + test('should not run autoplay stories without parameter', async ({ page }) => { const sbPage = new SbPage(page); await sbPage.navigateToStory('addons/docs/docspage/autoplay', 'docs'); diff --git a/code/ui/blocks/src/blocks/SourceContainer.tsx b/code/ui/blocks/src/blocks/SourceContainer.tsx index a2359ea103a2..c24b320c4330 100644 --- a/code/ui/blocks/src/blocks/SourceContainer.tsx +++ b/code/ui/blocks/src/blocks/SourceContainer.tsx @@ -1,7 +1,6 @@ import type { FC, Context, PropsWithChildren } from 'react'; import React, { createContext, useEffect, useState } from 'react'; -import { dequal as deepEqual } from 'dequal'; import type { Channel } from '@storybook/channels'; import { SNIPPET_RENDERED } from '@storybook/docs-tools'; @@ -64,11 +63,14 @@ export const SourceContainer: FC> = ({ : idOrEvent; const hash = args ? argsHash(args) : UNKNOWN_ARGS_HASH; - - // optimization: if the source is the same, ignore the incoming event - if (sources[id] && sources[id][hash] && sources[id][hash].code === source) { - return; - } + // FIXME: In SB8.0 when we remove the Source block deprecations, + // we should restore this optimizationand make the Source block + // smarter about understanding when its args change. + // + // See https://github.com/storybookjs/storybook/pull/22807 + // + // optimization: don't update if the source is the same + // if (deepEqual(currentSource, { code: source, format })) return; setSources((current) => { const newSources = { @@ -79,10 +81,7 @@ export const SourceContainer: FC> = ({ }, }; - if (!deepEqual(current, newSources)) { - return newSources; - } - return current; + return newSources; }); };