From 0dac86f05374d42eaac7316b0c2123dcae8b0982 Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Mon, 18 Nov 2024 17:38:35 -0500 Subject: [PATCH 1/2] [playground] Fix incorrect ci path and change reporter --- .github/workflows/compiler_playground.yml | 8 +++++--- compiler/apps/playground/playwright.config.js | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/compiler_playground.yml b/.github/workflows/compiler_playground.yml index 9e7b5b438ad2b..81c6c3ee42a27 100644 --- a/.github/workflows/compiler_playground.yml +++ b/.github/workflows/compiler_playground.yml @@ -6,7 +6,7 @@ on: pull_request: paths: - compiler/** - - .github/workflows/compiler-playground.yml + - .github/workflows/compiler_playground.yml concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} @@ -44,10 +44,12 @@ jobs: - name: yarn install playground run: yarn install --frozen-lockfile - run: npx playwright install --with-deps chromium - - run: yarn test + - run: CI=true yarn test + - run: ls -R test-results + if: '!cancelled()' - name: Archive test results if: '!cancelled()' uses: actions/upload-artifact@v4 with: name: test-results - path: test-results + path: compiler/apps/playground/test-results diff --git a/compiler/apps/playground/playwright.config.js b/compiler/apps/playground/playwright.config.js index d620a377460dc..533ebd0b3dd0b 100644 --- a/compiler/apps/playground/playwright.config.js +++ b/compiler/apps/playground/playwright.config.js @@ -36,6 +36,10 @@ export default defineConfig({ reuseExistingServer: !process.env.CI, }, + // 'github' for GitHub Actions CI to generate annotations, plus a concise 'dot' + // default 'list' when running locally + reporter: process.env.CI ? 'github' : 'list', + use: { // Use baseURL so to make navigations relative. // More information: https://playwright.dev/docs/api/class-testoptions#test-options-base-url From de535b1a5caef7fa0a610b1fcf49706bc42e9a7d Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Mon, 18 Nov 2024 18:34:38 -0500 Subject: [PATCH 2/2] [playground] Fix broken tests Our e2e setup with monaco is kinda brittle since it relies on the dom. It seems like longish text gets truncated so let's just simpify all these test cases. --- .../page.spec.ts/01-user-output.txt | 26 +-- .../page.spec.ts/02-default-output.txt | 22 +- ...nction-scope-beats-module-scope-output.txt | 14 ++ ...ctive-arrow-function-expression-output.txt | 20 -- ...-memo-arrow-function-expression-output.txt | 32 --- ...e-use-memo-function-declaration-output.txt | 32 --- ...se-no-memo-function-declaration-output.txt | 32 --- ...use-no-memo-function-expression-output.txt | 18 -- .../module-scope-use-memo-output.txt | 26 +-- ...use-no-memo-function-expression-output.txt | 3 - .../module-scope-use-no-memo-output.txt | 10 +- .../page.spec.ts/use-memo-output.txt | 28 +++ .../page.spec.ts/use-no-memo-output.txt | 8 + .../playground/__tests__/e2e/page.spec.ts | 213 +++++------------- compiler/apps/playground/playwright.config.js | 2 + 15 files changed, 143 insertions(+), 343 deletions(-) create mode 100644 compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-beats-module-scope-output.txt delete mode 100644 compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-no-directive-arrow-function-expression-output.txt delete mode 100644 compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-memo-arrow-function-expression-output.txt delete mode 100644 compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-memo-function-declaration-output.txt delete mode 100644 compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-no-memo-function-declaration-output.txt delete mode 100644 compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-no-memo-function-expression-output.txt delete mode 100644 compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-no-memo-function-expression-output.txt create mode 100644 compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/use-memo-output.txt create mode 100644 compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/use-no-memo-output.txt diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/01-user-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/01-user-output.txt index f45eb2c625c40..ba680bbb57232 100644 --- a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/01-user-output.txt +++ b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/01-user-output.txt @@ -1,13 +1,13 @@ -function TestComponent(t0) { -  const $ = _c(2); -  const { x } = t0; -  let t1; -  if ($[0] !== x) { -    t1 = ; -    $[0] = x; -    $[1] = t1; -  } else { -    t1 = $[1]; -  } -  return t1; -} \ No newline at end of file +function TestComponent(t0) { + const $ = _c(2); + const { x } = t0; + let t1; + if ($[0] !== x) { + t1 = ; + $[0] = x; + $[1] = t1; + } else { + t1 = $[1]; + } + return t1; +} diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/02-default-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/02-default-output.txt index a26ec5baaf5ab..2cbd09bba6179 100644 --- a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/02-default-output.txt +++ b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/02-default-output.txt @@ -1,11 +1,11 @@ -function MyApp() { -  const $ = _c(1); -  let t0; -  if ($[0] === Symbol.for("react.memo_cache_sentinel")) { -    t0 = 
Hello World
; -    $[0] = t0; -  } else { -    t0 = $[0]; -  } -  return t0; -} \ No newline at end of file +function MyApp() { + const $ = _c(1); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 =
Hello World
; + $[0] = t0; + } else { + t0 = $[0]; + } + return t0; +} diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-beats-module-scope-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-beats-module-scope-output.txt new file mode 100644 index 0000000000000..5bcfcb75edd18 --- /dev/null +++ b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-beats-module-scope-output.txt @@ -0,0 +1,14 @@ +function TestComponent(t0) { + "use memo"; + const $ = _c(2); + const { x } = t0; + let t1; + if ($[0] !== x) { + t1 = ; + $[0] = x; + $[1] = t1; + } else { + t1 = $[1]; + } + return t1; +} diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-no-directive-arrow-function-expression-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-no-directive-arrow-function-expression-output.txt deleted file mode 100644 index db441a034c50a..0000000000000 --- a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-no-directive-arrow-function-expression-output.txt +++ /dev/null @@ -1,20 +0,0 @@ -function anonymous_1() { -  "use no memo"; -  const Avatar = () => { -    return 
Avatar Content
; -  }; -  const MemoizedAvatar = React.memo(Avatar); -  const Bio = () => { -    const handleBioUpdate = () => { -      console.log("Bio updated"); -    }; -    return Bio Content; -  }; -  const MemoizedBio = React.memo(Bio); -  return ( -    
-       -       -    
-  ); -} \ No newline at end of file diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-memo-arrow-function-expression-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-memo-arrow-function-expression-output.txt deleted file mode 100644 index 974ceeb8b7af8..0000000000000 --- a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-memo-arrow-function-expression-output.txt +++ /dev/null @@ -1,32 +0,0 @@ -function anonymous_1() { -  "use memo"; -  const $ = _c(3); -  const Chart = _temp2; -  let t0; -  if ($[0] === Symbol.for("react.memo_cache_sentinel")) { -    t0 = React.memo(Chart); -    $[0] = t0; -  } else { -    t0 = $[0]; -  } -  const MemoizedChart = t0; -  const Graph = _temp3; -  let t1; -  if ($[1] === Symbol.for("react.memo_cache_sentinel")) { -    t1 = React.memo(Graph); -    $[1] = t1; -  } else { -    t1 = $[1]; -  } -  const MemoizedGraph = t1; -  let t2; -  if ($[2] === Symbol.for("react.memo_cache_sentinel")) { -    t2 = ( -      
-         -         -      
-    ); -    $[2] = t2; -  } else { -    t2 = $[2]; \ No newline at end of file diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-memo-function-declaration-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-memo-function-declaration-output.txt deleted file mode 100644 index 3caacf369cebf..0000000000000 --- a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-memo-function-declaration-output.txt +++ /dev/null @@ -1,32 +0,0 @@ -function App() { -  "use memo"; -  const $ = _c(3); -  let t0; -  if ($[0] === Symbol.for("react.memo_cache_sentinel")) { -    const Sidebar = function Sidebar() { -      const handleToggle = _temp; -      return Sidebar Content; -    }; -    t0 = React.memo(Sidebar); -    $[0] = t0; -  } else { -    t0 = $[0]; -  } -  const MemoizedSidebar = t0; -  let t1; -  if ($[1] === Symbol.for("react.memo_cache_sentinel")) { -    const Content = function Content() { -      return 
Main Content
; -    }; -    t1 = React.memo(Content); -    $[1] = t1; -  } else { -    t1 = $[1]; -  } -  const MemoizedContent = t1; -  let t2; -  if ($[2] === Symbol.for("react.memo_cache_sentinel")) { -    t2 = ( -      
-         \ No newline at end of file diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-no-memo-function-declaration-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-no-memo-function-declaration-output.txt deleted file mode 100644 index 51fb860de27eb..0000000000000 --- a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-no-memo-function-declaration-output.txt +++ /dev/null @@ -1,32 +0,0 @@ -function Settings() { -  "use memo"; -  const $ = _c(3); -  let t0; -  if ($[0] === Symbol.for("react.memo_cache_sentinel")) { -    t0 = function Preferences() { -      const handleSave = _temp; -      return Preferences Content; -    }; -    $[0] = t0; -  } else { -    t0 = $[0]; -  } -  const Preferences = t0; -  let t1; -  if ($[1] === Symbol.for("react.memo_cache_sentinel")) { -    t1 = function Notifications() { -      return 
Notifications Settings
; -    }; -    $[1] = t1; -  } else { -    t1 = $[1]; -  } -  const Notifications = t1; -  let t2; -  if ($[2] === Symbol.for("react.memo_cache_sentinel")) { -    t2 = ( -      
-         -         -      
\ No newline at end of file diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-no-memo-function-expression-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-no-memo-function-expression-output.txt deleted file mode 100644 index 2c31ad8e50662..0000000000000 --- a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-no-memo-function-expression-output.txt +++ /dev/null @@ -1,18 +0,0 @@ -function anonymous_1() { -  "use no memo"; -  const Widget = function () { -    const handleExpand = () => { -      console.log("Widget expanded"); -    }; -    return Widget Content
; -  }; -  const Panel = function () { -    return 
Panel Information
; -  }; -  return ( -    
-       -       -    
-  ); -} \ No newline at end of file diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-memo-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-memo-output.txt index 3b26c022db289..ba680bbb57232 100644 --- a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-memo-output.txt +++ b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-memo-output.txt @@ -1,15 +1,13 @@ -function anonymous_1() { -  const $ = _c(1); -  const handleClick = _temp; -  let t0; -  if ($[0] === Symbol.for("react.memo_cache_sentinel")) { -    t0 = Welcome to the App!; -    $[0] = t0; -  } else { -    t0 = $[0]; -  } -  return t0; +function TestComponent(t0) { + const $ = _c(2); + const { x } = t0; + let t1; + if ($[0] !== x) { + t1 = ; + $[0] = x; + $[1] = t1; + } else { + t1 = $[1]; + } + return t1; } -function _temp() { -  console.log("Header clicked"); -} \ No newline at end of file diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-no-memo-function-expression-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-no-memo-function-expression-output.txt deleted file mode 100644 index 7af2442b5c8dc..0000000000000 --- a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-no-memo-function-expression-output.txt +++ /dev/null @@ -1,3 +0,0 @@ -function anonymous_1() { -  return ; -} \ No newline at end of file diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-no-memo-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-no-memo-output.txt index 3433dfeaae094..2c69ddc1d65b8 100644 --- a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-no-memo-output.txt +++ b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-no-memo-output.txt @@ -1,7 +1,3 @@ -function anonymous_1() { -  const handleMouseOver = () => { -    console.log("Footer hovered"); -  }; -  return Footer  -      Information; -} \ No newline at end of file +function TestComponent({ x }) { + return ; +} diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/use-memo-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/use-memo-output.txt new file mode 100644 index 0000000000000..804bacab97e05 --- /dev/null +++ b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/use-memo-output.txt @@ -0,0 +1,28 @@ +function TestComponent(t0) { + "use memo"; + const $ = _c(2); + const { x } = t0; + let t1; + if ($[0] !== x) { + t1 = ; + $[0] = x; + $[1] = t1; + } else { + t1 = $[1]; + } + return t1; +} +function anonymous_1(t0) { + "use memo"; + const $ = _c(2); + const { x } = t0; + let t1; + if ($[0] !== x) { + t1 = ; + $[0] = x; + $[1] = t1; + } else { + t1 = $[1]; + } + return t1; +} diff --git a/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/use-no-memo-output.txt b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/use-no-memo-output.txt new file mode 100644 index 0000000000000..5fb66309fc70c --- /dev/null +++ b/compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/use-no-memo-output.txt @@ -0,0 +1,8 @@ +function anonymous_1() { + "use no memo"; + return ; +} +function anonymous_3({ x }) { + "use no memo"; + return ; +} diff --git a/compiler/apps/playground/__tests__/e2e/page.spec.ts b/compiler/apps/playground/__tests__/e2e/page.spec.ts index 1c2b2317d512d..846e6227bd1a1 100644 --- a/compiler/apps/playground/__tests__/e2e/page.spec.ts +++ b/compiler/apps/playground/__tests__/e2e/page.spec.ts @@ -7,185 +7,64 @@ import {expect, test} from '@playwright/test'; import {encodeStore, type Store} from '../../lib/stores'; +import {format} from 'prettier'; -test.describe.configure({mode: 'parallel'}); - -function concat(data: Array): string { - return data.join(''); +function print(data: Array): Promise { + return format(data.join(''), {parser: 'babel'}); } + const DIRECTIVE_TEST_CASES = [ { name: 'module-scope-use-memo', - input: `'use memo'; - -const Header = () => { - const handleClick = () => { - console.log('Header clicked'); - }; - - return

Welcome to the App!

; -};`, + input: ` +'use memo'; +export default function TestComponent({ x }) { + return ; +}`, }, { name: 'module-scope-use-no-memo', - input: `'use no memo'; - -const Footer = () => { - const handleMouseOver = () => { - console.log('Footer hovered'); - }; - - return
Footer Information
; -}; -`, - }, - { - name: 'function-scope-use-memo-function-declaration', - input: `function App() { - 'use memo'; - - function Sidebar() { - const handleToggle = () => { - console.log('Sidebar toggled'); - }; - - return ; - } - - const MemoizedSidebar = React.memo(Sidebar); - - function Content() { - return
Main Content
; - } - - const MemoizedContent = React.memo(Content); - - return ( -
- - -
- ); + input: ` +'use no memo'; +export default function TestComponent({ x }) { + return ; }`, }, { - name: 'function-scope-use-no-memo-function-expression', - input: `const Dashboard = function() { - 'use no memo'; - const Widget = function() { - const handleExpand = () => { - console.log('Widget expanded'); - }; - - return
Widget Content
; - }; - - const Panel = function() { - return
Panel Information
; - }; - - return ( -
- - -
- ); -};`, - }, - { - name: 'function-scope-use-memo-arrow-function-expression', - input: `const Analytics = () => { + name: 'use-memo', + input: ` +function TestComponent({ x }) { 'use memo'; - - const Chart = () => { - const handleRefresh = () => { - console.log('Chart refreshed'); - }; - - return
Chart Content
; - }; - - const MemoizedChart = React.memo(Chart); - - const Graph = () => { - return
Graph Content
; - }; - - const MemoizedGraph = React.memo(Graph); - - return ( -
- - -
- ); + return ; +} +const TestComponent2 = ({ x }) => { + 'use memo'; + return ; };`, }, { - name: 'module-scope-use-no-memo-function-expression', - input: `'use no memo'; - -const Sidebar = function() { - return ; + name: 'use-no-memo', + input: ` +const TestComponent = function() { + 'use no memo'; + return ; +}; +const TestComponent2 = ({ x }) => { + 'use no memo'; + return ; };`, }, { - name: 'function-scope-no-directive-arrow-function-expression', + name: 'function-scope-beats-module-scope', input: ` -const Profile = () => { 'use no memo'; - const Avatar = () => { - return
Avatar Content
; - }; - - const MemoizedAvatar = React.memo(Avatar); - - const Bio = () => { - const handleBioUpdate = () => { - console.log('Bio updated'); - }; - - return
Bio Content
; - }; - - const MemoizedBio = React.memo(Bio); - - return ( -
- - -
- ); -};`, - }, - { - name: 'function-scope-use-no-memo-function-declaration', - input: `'use no memo'; - -function Settings() { +function TestComponent({ x }) { 'use memo'; - - function Preferences() { - const handleSave = () => { - console.log('Preferences saved'); - }; - - return
Preferences Content
; - } - - function Notifications() { - return
Notifications Settings
; - } - - return ( -
- - -
- ); + return ; }`, }, ]; + test('editor should open successfully', async ({page}) => { await page.goto(`/`, {waitUntil: 'networkidle'}); await page.screenshot({ @@ -193,6 +72,7 @@ test('editor should open successfully', async ({page}) => { path: 'test-results/00-fresh-page.png', }); }); + test('editor should compile from hash successfully', async ({page}) => { const store: Store = { source: `export default function TestComponent({ x }) { @@ -208,10 +88,14 @@ test('editor should compile from hash successfully', async ({page}) => { fullPage: true, path: 'test-results/01-compiles-from-hash.png', }); - const userInput = + const text = (await page.locator('.monaco-editor').nth(1).allInnerTexts()) ?? []; - expect(concat(userInput)).toMatchSnapshot('01-user-output.txt'); + const output = await print(text); + + expect(output).not.toEqual(''); + expect(output).toMatchSnapshot('01-user-output.txt'); }); + test('reset button works', async ({page}) => { const store: Store = { source: `export default function TestComponent({ x }) { @@ -229,10 +113,14 @@ test('reset button works', async ({page}) => { fullPage: true, path: 'test-results/02-reset-button-works.png', }); - const defaultInput = + const text = (await page.locator('.monaco-editor').nth(1).allInnerTexts()) ?? []; - expect(concat(defaultInput)).toMatchSnapshot('02-default-output.txt'); + const output = await print(text); + + expect(output).not.toEqual(''); + expect(output).toMatchSnapshot('02-default-output.txt'); }); + DIRECTIVE_TEST_CASES.forEach((t, idx) => test(`directives work: ${t.name}`, async ({page}) => { const store: Store = { @@ -245,8 +133,11 @@ DIRECTIVE_TEST_CASES.forEach((t, idx) => path: `test-results/03-0${idx}-${t.name}.png`, }); - const useMemoOutput = + const text = (await page.locator('.monaco-editor').nth(1).allInnerTexts()) ?? []; - expect(concat(useMemoOutput)).toMatchSnapshot(`${t.name}-output.txt`); + const output = await print(text); + + expect(output).not.toEqual(''); + expect(output).toMatchSnapshot(`${t.name}-output.txt`); }), ); diff --git a/compiler/apps/playground/playwright.config.js b/compiler/apps/playground/playwright.config.js index 533ebd0b3dd0b..ca243742f5636 100644 --- a/compiler/apps/playground/playwright.config.js +++ b/compiler/apps/playground/playwright.config.js @@ -18,6 +18,8 @@ const baseURL = `http://localhost:${PORT}`; export default defineConfig({ // Timeout per test timeout: 30 * 1000, + // Run all tests in parallel. + fullyParallel: true, // Test directory testDir: path.join(__dirname, '__tests__/e2e'), // If a test fails, retry it additional 2 times