@samitouri / QOS-React-2 / commits / c866d75060

[playground] Fix broken tests (#31573)

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. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/31573). * __->__ #31573 * #31572

lauren committed Nov 18, 2024 at 19:18 UTC c866d7506086140aaa79a015f4a7b2cf20c51905
15 files changed +143 -343
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/01-user-output.txt
+13 -13
@@ -1,13 +1,13 @@
1 -function TestComponent(t0) {
2 -  const $ = _c(2);
3 -  const { x } = t0;
4 -  let t1;
5 -  if ($[0] !== x) {
6 -    t1 = <Button>{x}</Button>;
7 -    $[0] = x;
8 -    $[1] = t1;
9 -  } else {
10 -    t1 = $[1];
11 -  }
12 -  return t1;
13 -}
\ No newline at end of file
1 +function TestComponent(t0) {
2 + const $ = _c(2);
3 + const { x } = t0;
4 + let t1;
5 + if ($[0] !== x) {
6 + t1 = <Button>{x}</Button>;
7 + $[0] = x;
8 + $[1] = t1;
9 + } else {
10 + t1 = $[1];
11 + }
12 + return t1;
13 +}
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/02-default-output.txt
+11 -11
@@ -1,11 +1,11 @@
1 -function MyApp() {
2 -  const $ = _c(1);
3 -  let t0;
4 -  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
5 -    t0 = <div>Hello World</div>;
6 -    $[0] = t0;
7 -  } else {
8 -    t0 = $[0];
9 -  }
10 -  return t0;
11 -}
\ No newline at end of file
1 +function MyApp() {
2 + const $ = _c(1);
3 + let t0;
4 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
5 + t0 = <div>Hello World</div>;
6 + $[0] = t0;
7 + } else {
8 + t0 = $[0];
9 + }
10 + return t0;
11 +}
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-beats-module-scope-output.txt new
+14
@@ -0,0 +1,14 @@
1 +function TestComponent(t0) {
2 + "use memo";
3 + const $ = _c(2);
4 + const { x } = t0;
5 + let t1;
6 + if ($[0] !== x) {
7 + t1 = <Button>{x}</Button>;
8 + $[0] = x;
9 + $[1] = t1;
10 + } else {
11 + t1 = $[1];
12 + }
13 + return t1;
14 +}
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-no-directive-arrow-function-expression-output.txt deleted
-20
@@ -1,20 +0,0 @@
1 -function anonymous_1() {
2 -  "use no memo";
3 -  const Avatar = () => {
4 -    return <div>Avatar Content</div>;
5 -  };
6 -  const MemoizedAvatar = React.memo(Avatar);
7 -  const Bio = () => {
8 -    const handleBioUpdate = () => {
9 -      console.log("Bio updated");
10 -    };
11 -    return <div onClick={handleBioUpdate}>Bio Content</div>;
12 -  };
13 -  const MemoizedBio = React.memo(Bio);
14 -  return (
15 -    <div>
16 -      <MemoizedAvatar />
17 -      <MemoizedBio />
18 -    </div>
19 -  );
20 -}
\ No newline at end of file
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-memo-arrow-function-expression-output.txt deleted
-32
@@ -1,32 +0,0 @@
1 -function anonymous_1() {
2 -  "use memo";
3 -  const $ = _c(3);
4 -  const Chart = _temp2;
5 -  let t0;
6 -  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
7 -    t0 = React.memo(Chart);
8 -    $[0] = t0;
9 -  } else {
10 -    t0 = $[0];
11 -  }
12 -  const MemoizedChart = t0;
13 -  const Graph = _temp3;
14 -  let t1;
15 -  if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
16 -    t1 = React.memo(Graph);
17 -    $[1] = t1;
18 -  } else {
19 -    t1 = $[1];
20 -  }
21 -  const MemoizedGraph = t1;
22 -  let t2;
23 -  if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
24 -    t2 = (
25 -      <div>
26 -        <MemoizedChart />
27 -        <MemoizedGraph />
28 -      </div>
29 -    );
30 -    $[2] = t2;
31 -  } else {
32 -    t2 = $[2];
\ No newline at end of file
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-memo-function-declaration-output.txt deleted
-32
@@ -1,32 +0,0 @@
1 -function App() {
2 -  "use memo";
3 -  const $ = _c(3);
4 -  let t0;
5 -  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
6 -    const Sidebar = function Sidebar() {
7 -      const handleToggle = _temp;
8 -      return <aside onClick={handleToggle}>Sidebar Content</
9 -          aside>;
10 -    };
11 -    t0 = React.memo(Sidebar);
12 -    $[0] = t0;
13 -  } else {
14 -    t0 = $[0];
15 -  }
16 -  const MemoizedSidebar = t0;
17 -  let t1;
18 -  if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
19 -    const Content = function Content() {
20 -      return <main>Main Content</main>;
21 -    };
22 -    t1 = React.memo(Content);
23 -    $[1] = t1;
24 -  } else {
25 -    t1 = $[1];
26 -  }
27 -  const MemoizedContent = t1;
28 -  let t2;
29 -  if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
30 -    t2 = (
31 -      <div>
32 -        <MemoizedSidebar />
\ No newline at end of file
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-no-memo-function-declaration-output.txt deleted
-32
@@ -1,32 +0,0 @@
1 -function Settings() {
2 -  "use memo";
3 -  const $ = _c(3);
4 -  let t0;
5 -  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
6 -    t0 = function Preferences() {
7 -      const handleSave = _temp;
8 -      return <div onClick={handleSave}>Preferences Content</
9 -          div>;
10 -    };
11 -    $[0] = t0;
12 -  } else {
13 -    t0 = $[0];
14 -  }
15 -  const Preferences = t0;
16 -  let t1;
17 -  if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
18 -    t1 = function Notifications() {
19 -      return <div>Notifications Settings</div>;
20 -    };
21 -    $[1] = t1;
22 -  } else {
23 -    t1 = $[1];
24 -  }
25 -  const Notifications = t1;
26 -  let t2;
27 -  if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
28 -    t2 = (
29 -      <div>
30 -        <Preferences />
31 -        <Notifications />
32 -      </div>
\ No newline at end of file
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/function-scope-use-no-memo-function-expression-output.txt deleted
-18
@@ -1,18 +0,0 @@
1 -function anonymous_1() {
2 -  "use no memo";
3 -  const Widget = function () {
4 -    const handleExpand = () => {
5 -      console.log("Widget expanded");
6 -    };
7 -    return <div onClick={handleExpand}>Widget Content</div>;
8 -  };
9 -  const Panel = function () {
10 -    return <section>Panel Information</section>;
11 -  };
12 -  return (
13 -    <div>
14 -      <Widget />
15 -      <Panel />
16 -    </div>
17 -  );
18 -}
\ No newline at end of file
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-memo-output.txt
+12 -14
@@ -1,15 +1,13 @@
1 -function anonymous_1() {
2 -  const $ = _c(1);
3 -  const handleClick = _temp;
4 -  let t0;
5 -  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
6 -    t0 = <h1 onClick={handleClick}>Welcome to the App!</h1>;
7 -    $[0] = t0;
8 -  } else {
9 -    t0 = $[0];
10 -  }
11 -  return t0;
1 +function TestComponent(t0) {
2 + const $ = _c(2);
3 + const { x } = t0;
4 + let t1;
5 + if ($[0] !== x) {
6 + t1 = <Button>{x}</Button>;
7 + $[0] = x;
8 + $[1] = t1;
9 + } else {
10 + t1 = $[1];
11 + }
12 + return t1;
13 }
13 -function _temp() {
14 -  console.log("Header clicked");
15 -}
\ No newline at end of file
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-no-memo-function-expression-output.txt deleted
-3
@@ -1,3 +0,0 @@
1 -function anonymous_1() {
2 -  return <aside>Sidebar Information</aside>;
3 -}
\ No newline at end of file
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/module-scope-use-no-memo-output.txt
+3 -7
@@ -1,7 +1,3 @@
1 -function anonymous_1() {
2 -  const handleMouseOver = () => {
3 -    console.log("Footer hovered");
4 -  };
5 -  return <footer onMouseOver={handleMouseOver}>Footer 
6 -      Information</footer>;
7 -}
\ No newline at end of file
1 +function TestComponent({ x }) {
2 + return <Button>{x}</Button>;
3 +}
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/use-memo-output.txt new
+28
@@ -0,0 +1,28 @@
1 +function TestComponent(t0) {
2 + "use memo";
3 + const $ = _c(2);
4 + const { x } = t0;
5 + let t1;
6 + if ($[0] !== x) {
7 + t1 = <Button>{x}</Button>;
8 + $[0] = x;
9 + $[1] = t1;
10 + } else {
11 + t1 = $[1];
12 + }
13 + return t1;
14 +}
15 +function anonymous_1(t0) {
16 + "use memo";
17 + const $ = _c(2);
18 + const { x } = t0;
19 + let t1;
20 + if ($[0] !== x) {
21 + t1 = <Button>{x}</Button>;
22 + $[0] = x;
23 + $[1] = t1;
24 + } else {
25 + t1 = $[1];
26 + }
27 + return t1;
28 +}
compiler/apps/playground/__tests__/e2e/__snapshots__/page.spec.ts/use-no-memo-output.txt new
+8
@@ -0,0 +1,8 @@
1 +function anonymous_1() {
2 + "use no memo";
3 + return <Button>{x}</Button>;
4 +}
5 +function anonymous_3({ x }) {
6 + "use no memo";
7 + return <Button>{x}</Button>;
8 +}
compiler/apps/playground/__tests__/e2e/page.spec.ts
+52 -161
@@ -7,185 +7,64 @@
7
8 import {expect, test} from '@playwright/test';
9 import {encodeStore, type Store} from '../../lib/stores';
10 +import {format} from 'prettier';
11
11 -test.describe.configure({mode: 'parallel'});
12 -
13 -function concat(data: Array<string>): string {
14 - return data.join('');
12 +function print(data: Array<string>): Promise<string> {
13 + return format(data.join(''), {parser: 'babel'});
14 }
15 +
16 const DIRECTIVE_TEST_CASES = [
17 {
18 name: 'module-scope-use-memo',
19 - input: `'use memo';
20 -
21 -const Header = () => {
22 - const handleClick = () => {
23 - console.log('Header clicked');
24 - };
25 -
26 - return <h1 onClick={handleClick}>Welcome to the App!</h1>;
27 -};`,
19 + input: `
20 +'use memo';
21 +export default function TestComponent({ x }) {
22 + return <Button>{x}</Button>;
23 +}`,
24 },
25 {
26 name: 'module-scope-use-no-memo',
31 - input: `'use no memo';
32 -
33 -const Footer = () => {
34 - const handleMouseOver = () => {
35 - console.log('Footer hovered');
36 - };
37 -
38 - return <footer onMouseOver={handleMouseOver}>Footer Information</footer>;
39 -};
40 -`,
41 - },
42 - {
43 - name: 'function-scope-use-memo-function-declaration',
44 - input: `function App() {
45 - 'use memo';
46 -
47 - function Sidebar() {
48 - const handleToggle = () => {
49 - console.log('Sidebar toggled');
50 - };
51 -
52 - return <aside onClick={handleToggle}>Sidebar Content</aside>;
53 - }
54 -
55 - const MemoizedSidebar = React.memo(Sidebar);
56 -
57 - function Content() {
58 - return <main>Main Content</main>;
59 - }
60 -
61 - const MemoizedContent = React.memo(Content);
62 -
63 - return (
64 - <div>
65 - <MemoizedSidebar />
66 - <MemoizedContent />
67 - </div>
68 - );
27 + input: `
28 +'use no memo';
29 +export default function TestComponent({ x }) {
30 + return <Button>{x}</Button>;
31 }`,
32 },
33 {
72 - name: 'function-scope-use-no-memo-function-expression',
73 - input: `const Dashboard = function() {
74 - 'use no memo';
75 - const Widget = function() {
76 - const handleExpand = () => {
77 - console.log('Widget expanded');
78 - };
79 -
80 - return <div onClick={handleExpand}>Widget Content</div>;
81 - };
82 -
83 - const Panel = function() {
84 - return <section>Panel Information</section>;
85 - };
86 -
87 - return (
88 - <div>
89 - <Widget />
90 - <Panel />
91 - </div>
92 - );
93 -};`,
94 - },
95 - {
96 - name: 'function-scope-use-memo-arrow-function-expression',
97 - input: `const Analytics = () => {
34 + name: 'use-memo',
35 + input: `
36 +function TestComponent({ x }) {
37 'use memo';
99 -
100 - const Chart = () => {
101 - const handleRefresh = () => {
102 - console.log('Chart refreshed');
103 - };
104 -
105 - return <div onClick={handleRefresh}>Chart Content</div>;
106 - };
107 -
108 - const MemoizedChart = React.memo(Chart);
109 -
110 - const Graph = () => {
111 - return <div>Graph Content</div>;
112 - };
113 -
114 - const MemoizedGraph = React.memo(Graph);
115 -
116 - return (
117 - <div>
118 - <MemoizedChart />
119 - <MemoizedGraph />
120 - </div>
121 - );
38 + return <Button>{x}</Button>;
39 +}
40 +const TestComponent2 = ({ x }) => {
41 + 'use memo';
42 + return <Button>{x}</Button>;
43 };`,
44 },
45 {
125 - name: 'module-scope-use-no-memo-function-expression',
126 - input: `'use no memo';
127 -
128 -const Sidebar = function() {
129 - return <aside>Sidebar Information</aside>;
46 + name: 'use-no-memo',
47 + input: `
48 +const TestComponent = function() {
49 + 'use no memo';
50 + return <Button>{x}</Button>;
51 +};
52 +const TestComponent2 = ({ x }) => {
53 + 'use no memo';
54 + return <Button>{x}</Button>;
55 };`,
56 },
57 {
133 - name: 'function-scope-no-directive-arrow-function-expression',
58 + name: 'function-scope-beats-module-scope',
59 input: `
135 -const Profile = () => {
60 'use no memo';
137 - const Avatar = () => {
138 - return <div>Avatar Content</div>;
139 - };
140 -
141 - const MemoizedAvatar = React.memo(Avatar);
142 -
143 - const Bio = () => {
144 - const handleBioUpdate = () => {
145 - console.log('Bio updated');
146 - };
147 -
148 - return <div onClick={handleBioUpdate}>Bio Content</div>;
149 - };
150 -
151 - const MemoizedBio = React.memo(Bio);
152 -
153 - return (
154 - <div>
155 - <MemoizedAvatar />
156 - <MemoizedBio />
157 - </div>
158 - );
159 -};`,
160 - },
161 - {
162 - name: 'function-scope-use-no-memo-function-declaration',
163 - input: `'use no memo';
164 -
165 -function Settings() {
61 +function TestComponent({ x }) {
62 'use memo';
167 -
168 - function Preferences() {
169 - const handleSave = () => {
170 - console.log('Preferences saved');
171 - };
172 -
173 - return <div onClick={handleSave}>Preferences Content</div>;
174 - }
175 -
176 - function Notifications() {
177 - return <div>Notifications Settings</div>;
178 - }
179 -
180 - return (
181 - <div>
182 - <Preferences />
183 - <Notifications />
184 - </div>
185 - );
63 + return <Button>{x}</Button>;
64 }`,
65 },
66 ];
67 +
68 test('editor should open successfully', async ({page}) => {
69 await page.goto(`/`, {waitUntil: 'networkidle'});
70 await page.screenshot({
@@ -193,6 +72,7 @@ test('editor should open successfully', async ({page}) => {
72 path: 'test-results/00-fresh-page.png',
73 });
74 });
75 +
76 test('editor should compile from hash successfully', async ({page}) => {
77 const store: Store = {
78 source: `export default function TestComponent({ x }) {
@@ -208,10 +88,14 @@ test('editor should compile from hash successfully', async ({page}) => {
88 fullPage: true,
89 path: 'test-results/01-compiles-from-hash.png',
90 });
211 - const userInput =
91 + const text =
92 (await page.locator('.monaco-editor').nth(1).allInnerTexts()) ?? [];
213 - expect(concat(userInput)).toMatchSnapshot('01-user-output.txt');
93 + const output = await print(text);
94 +
95 + expect(output).not.toEqual('');
96 + expect(output).toMatchSnapshot('01-user-output.txt');
97 });
98 +
99 test('reset button works', async ({page}) => {
100 const store: Store = {
101 source: `export default function TestComponent({ x }) {
@@ -229,10 +113,14 @@ test('reset button works', async ({page}) => {
113 fullPage: true,
114 path: 'test-results/02-reset-button-works.png',
115 });
232 - const defaultInput =
116 + const text =
117 (await page.locator('.monaco-editor').nth(1).allInnerTexts()) ?? [];
234 - expect(concat(defaultInput)).toMatchSnapshot('02-default-output.txt');
118 + const output = await print(text);
119 +
120 + expect(output).not.toEqual('');
121 + expect(output).toMatchSnapshot('02-default-output.txt');
122 });
123 +
124 DIRECTIVE_TEST_CASES.forEach((t, idx) =>
125 test(`directives work: ${t.name}`, async ({page}) => {
126 const store: Store = {
@@ -245,8 +133,11 @@ DIRECTIVE_TEST_CASES.forEach((t, idx) =>
133 path: `test-results/03-0${idx}-${t.name}.png`,
134 });
135
248 - const useMemoOutput =
136 + const text =
137 (await page.locator('.monaco-editor').nth(1).allInnerTexts()) ?? [];
250 - expect(concat(useMemoOutput)).toMatchSnapshot(`${t.name}-output.txt`);
138 + const output = await print(text);
139 +
140 + expect(output).not.toEqual('');
141 + expect(output).toMatchSnapshot(`${t.name}-output.txt`);
142 }),
143 );
compiler/apps/playground/playwright.config.js
+2
@@ -18,6 +18,8 @@ const baseURL = `http://localhost:${PORT}`;
18 export default defineConfig({
19 // Timeout per test
20 timeout: 30 * 1000,
21 + // Run all tests in parallel.
22 + fullyParallel: true,
23 // Test directory
24 testDir: path.join(__dirname, '__tests__/e2e'),
25 // If a test fails, retry it additional 2 times