<commit_before>/**
 * Copyright Microsoft Corporation. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { test, expect } from './playwright-test-fixtures';

for (const mode of ['legacy', 'default']) {
  test.describe(`${mode} mode`, () => {
    const env = { PW_TEST_LEGACY_GLOBAL_SETUP_MODE: mode === 'legacy' ? '1' : undefined };

    test('globalSetup and globalTeardown should work', async ({ runInlineTest }) => {
      const { results, output } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: './globalSetup',
            globalTeardown: path.join(__dirname, 'globalTeardown.ts'),
          };
        `,
        'globalSetup.ts': `
          module.exports = async () => {
            await new Promise(f => setTimeout(f, 100));
            global.value = 42;
            process.env.FOO = String(global.value);
          };
        `,
        'globalTeardown.ts': `
          module.exports = async () => {
            console.log('teardown=' + global.value);
          };
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should work', async ({}, testInfo) => {
            expect(process.env.FOO).toBe('42');
          });
        `,
      }, undefined, env);
      expect(results[0].status).toBe('passed');
      expect(output).toContain('teardown=42');
    });

    test('globalTeardown runs after failures', async ({ runInlineTest }) => {
      const { results, output } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: 'globalSetup.ts',
            globalTeardown: './globalTeardown.ts',
          };
        `,
        'globalSetup.ts': `
          module.exports = async () => {
            await new Promise(f => setTimeout(f, 100));
            global.value = 42;
            process.env.FOO = String(global.value);
          };
        `,
        'globalTeardown.ts': `
          module.exports = async () => {
            console.log('teardown=' + global.value);
          };
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should work', async ({}, testInfo) => {
            expect(process.env.FOO).toBe('43');
          });
        `,
      }, undefined, env);
      expect(results[0].status).toBe('failed');
      expect(output).toContain('teardown=42');
    });

    test('globalTeardown does not run when globalSetup times out', async ({ runInlineTest }) => {
      test.skip(!!env.PW_TEST_LEGACY_GLOBAL_SETUP_MODE);
      const result = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: './globalSetup.ts',
            globalTeardown: 'globalTeardown.ts',
            globalTimeout: 1000,
          };
        `,
        'globalSetup.ts': `
          module.exports = async () => {
            await new Promise(f => setTimeout(f, 10000));
          };
        `,
        'globalTeardown.ts': `
          module.exports = async () => {
            console.log('teardown=');
          };
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should not run', async ({}, testInfo) => {
          });
        `,
      }, undefined, env);
      // We did not run tests, so we should only have 1 skipped test.
      expect(result.skipped).toBe(1);
      expect(result.passed).toBe(0);
      expect(result.failed).toBe(0);
      expect(result.exitCode).toBe(1);
      expect(result.output).not.toContain('teardown=');
    });

    test('globalSetup should work with sync function', async ({ runInlineTest }) => {
      const { passed } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: './globalSetup.ts',
          };
        `,
        'globalSetup.ts': `
          module.exports = () => {
            process.env.FOO = JSON.stringify({ foo: 'bar' });
          };
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should work', async ({}) => {
            const value = JSON.parse(process.env.FOO);
            expect(value).toEqual({ foo: 'bar' });
          });
        `,
      }, undefined, env);
      expect(passed).toBe(1);
    });

    test('globalSetup should throw when passed non-function', async ({ runInlineTest }) => {
      const { output } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: './globalSetup.ts',
          };
        `,
        'globalSetup.ts': `
          module.exports = 42;
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should work', async ({}) => {
          });
        `,
      }, undefined, env);
      expect(output).toContain(`globalSetup.ts: globalSetup file must export a single function.`);
    });

    test('globalSetup should work with default export and run the returned fn', async ({ runInlineTest }) => {
      const { output, exitCode, passed } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: './globalSetup.ts',
          };
        `,
        'globalSetup.ts': `
          function setup() {
            let x = 42;
            console.log('\\n%%setup: ' + x);
            return async () => {
              await x;
              console.log('\\n%%teardown: ' + x);
            };
          }
          export default setup;
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should work', async ({}) => {
          });
        `,
      }, undefined, env);
      expect(passed).toBe(1);
      expect(exitCode).toBe(0);
      expect(output).toContain(`%%setup: 42`);
      expect(output).toContain(`%%teardown: 42`);
    });

    test('globalSetup should allow requiring a package from node_modules', async ({ runInlineTest }) => {
      const { results } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: 'my-global-setup'
          };
        `,
        'node_modules/my-global-setup/index.js': `
          module.exports = async () => {
            await new Promise(f => setTimeout(f, 100));
            global.value = 42;
            process.env.FOO = String(global.value);
          };
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should work', async ({}, testInfo) => {
            expect(process.env.FOO).toBe('42');
          });
        `,
      }, undefined, env);
      expect(results[0].status).toBe('passed');
    });

    const authFiles = {
      'playwright.config.ts': `
        const config: pwt.PlaywrightTestConfig = {
          globalSetup: require.resolve('./auth'),
          use: {
            baseURL: 'https://www.example.com',
            storageState: 'state.json',
          },
        };
        export default config;
      `,
      'auth.ts': `
        async function globalSetup(config: pwt.FullConfig) {
          const { baseURL, storageState } = config.projects[0].use;
          const browser = await pwt.chromium.launch();
          const page = await browser.newPage();
          await page.route('**/*', route => {
            route.fulfill({ body: '<html></html>' }).catch(() => {});
          });
          await page.goto(baseURL!);
          await page.evaluate(() => {
            localStorage['name'] = 'value';
          });
          await page.context().storageState({ path: storageState as string });
          await browser.close();
        };
        export default globalSetup;
      `,
      'a.test.ts': `
        const { test } = pwt;
        test('should have storage state', async ({ page }) => {
          await page.route('**/*', route => {
            route.fulfill({ body: '<html></html>' }).catch(() => {});
          });
          await page.goto('/');
          const value = await page.evaluate(() => localStorage['name']);
          expect(value).toBe('value');
        });
      `,
    };

    test('globalSetup should work for auth', async ({ runInlineTest }) => {
      const result = await runInlineTest(authFiles, undefined, env);
      expect(result.exitCode).toBe(0);
      expect(result.passed).toBe(1);
    });

    test('globalSetup auth should compile', async ({ runTSC }) => {
      const result = await runTSC(authFiles);
      expect(result.exitCode).toBe(0);
    });
  });
}
<commit_msg>test: ensure tests do not run after globalSetup fail (#13255)<commit_after>/**
 * Copyright Microsoft Corporation. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { test, expect, stripAnsi } from './playwright-test-fixtures';

for (const mode of ['legacy', 'default']) {
  test.describe(`${mode} mode`, () => {
    const env = { PW_TEST_LEGACY_GLOBAL_SETUP_MODE: mode === 'legacy' ? '1' : undefined };

    test('globalSetup and globalTeardown should work', async ({ runInlineTest }) => {
      const { results, output } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: './globalSetup',
            globalTeardown: path.join(__dirname, 'globalTeardown.ts'),
          };
        `,
        'globalSetup.ts': `
          module.exports = async () => {
            await new Promise(f => setTimeout(f, 100));
            global.value = 42;
            process.env.FOO = String(global.value);
          };
        `,
        'globalTeardown.ts': `
          module.exports = async () => {
            console.log('teardown=' + global.value);
          };
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should work', async ({}, testInfo) => {
            expect(process.env.FOO).toBe('42');
          });
        `,
      }, undefined, env);
      expect(results[0].status).toBe('passed');
      expect(output).toContain('teardown=42');
    });

    test('globalTeardown runs after failures', async ({ runInlineTest }) => {
      const { results, output } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: 'globalSetup.ts',
            globalTeardown: './globalTeardown.ts',
          };
        `,
        'globalSetup.ts': `
          module.exports = async () => {
            await new Promise(f => setTimeout(f, 100));
            global.value = 42;
            process.env.FOO = String(global.value);
          };
        `,
        'globalTeardown.ts': `
          module.exports = async () => {
            console.log('teardown=' + global.value);
          };
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should work', async ({}, testInfo) => {
            expect(process.env.FOO).toBe('43');
          });
        `,
      }, undefined, env);
      expect(results[0].status).toBe('failed');
      expect(output).toContain('teardown=42');
    });

    test('globalTeardown does not run when globalSetup times out', async ({ runInlineTest }) => {
      test.skip(!!env.PW_TEST_LEGACY_GLOBAL_SETUP_MODE);
      const result = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: './globalSetup.ts',
            globalTeardown: 'globalTeardown.ts',
            globalTimeout: 1000,
          };
        `,
        'globalSetup.ts': `
          module.exports = async () => {
            await new Promise(f => setTimeout(f, 10000));
          };
        `,
        'globalTeardown.ts': `
          module.exports = async () => {
            console.log('teardown=');
          };
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should not run', async ({}, testInfo) => {
          });
        `,
      }, undefined, env);
      // We did not run tests, so we should only have 1 skipped test.
      expect(result.skipped).toBe(1);
      expect(result.passed).toBe(0);
      expect(result.failed).toBe(0);
      expect(result.exitCode).toBe(1);
      expect(result.output).not.toContain('teardown=');
    });

    test('globalSetup should work with sync function', async ({ runInlineTest }) => {
      const { passed } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: './globalSetup.ts',
          };
        `,
        'globalSetup.ts': `
          module.exports = () => {
            process.env.FOO = JSON.stringify({ foo: 'bar' });
          };
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should work', async ({}) => {
            const value = JSON.parse(process.env.FOO);
            expect(value).toEqual({ foo: 'bar' });
          });
        `,
      }, undefined, env);
      expect(passed).toBe(1);
    });

    test('globalSetup error should prevent tests from executing', async ({ runInlineTest }) => {
      const { passed, output } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: './globalSetup.ts',
          };
        `,
        'globalSetup.ts': `
          module.exports = () => {
            throw new Error('failure in global setup!');
          };
        `,
        'a.test.js': `
          const { test } = pwt;
          test('a', async ({}) => {
            console.log('this test ran');
          });

          test('b', async ({}) => {
            console.log('this test ran');
          });
        `,
      }, { reporter: 'line' }, env);

      expect(stripAnsi(output)).not.toContain('this test ran');
      expect(passed).toBe(0);
    });

    test('globalSetup should throw when passed non-function', async ({ runInlineTest }) => {
      const { output } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: './globalSetup.ts',
          };
        `,
        'globalSetup.ts': `
          module.exports = 42;
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should work', async ({}) => {
          });
        `,
      }, undefined, env);
      expect(output).toContain(`globalSetup.ts: globalSetup file must export a single function.`);
    });

    test('globalSetup should work with default export and run the returned fn', async ({ runInlineTest }) => {
      const { output, exitCode, passed } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: './globalSetup.ts',
          };
        `,
        'globalSetup.ts': `
          function setup() {
            let x = 42;
            console.log('\\n%%setup: ' + x);
            return async () => {
              await x;
              console.log('\\n%%teardown: ' + x);
            };
          }
          export default setup;
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should work', async ({}) => {
          });
        `,
      }, undefined, env);
      expect(passed).toBe(1);
      expect(exitCode).toBe(0);
      expect(output).toContain(`%%setup: 42`);
      expect(output).toContain(`%%teardown: 42`);
    });

    test('globalSetup should allow requiring a package from node_modules', async ({ runInlineTest }) => {
      const { results } = await runInlineTest({
        'playwright.config.ts': `
          import * as path from 'path';
          module.exports = {
            globalSetup: 'my-global-setup'
          };
        `,
        'node_modules/my-global-setup/index.js': `
          module.exports = async () => {
            await new Promise(f => setTimeout(f, 100));
            global.value = 42;
            process.env.FOO = String(global.value);
          };
        `,
        'a.test.js': `
          const { test } = pwt;
          test('should work', async ({}, testInfo) => {
            expect(process.env.FOO).toBe('42');
          });
        `,
      }, undefined, env);
      expect(results[0].status).toBe('passed');
    });

    const authFiles = {
      'playwright.config.ts': `
        const config: pwt.PlaywrightTestConfig = {
          globalSetup: require.resolve('./auth'),
          use: {
            baseURL: 'https://www.example.com',
            storageState: 'state.json',
          },
        };
        export default config;
      `,
      'auth.ts': `
        async function globalSetup(config: pwt.FullConfig) {
          const { baseURL, storageState } = config.projects[0].use;
          const browser = await pwt.chromium.launch();
          const page = await browser.newPage();
          await page.route('**/*', route => {
            route.fulfill({ body: '<html></html>' }).catch(() => {});
          });
          await page.goto(baseURL!);
          await page.evaluate(() => {
            localStorage['name'] = 'value';
          });
          await page.context().storageState({ path: storageState as string });
          await browser.close();
        };
        export default globalSetup;
      `,
      'a.test.ts': `
        const { test } = pwt;
        test('should have storage state', async ({ page }) => {
          await page.route('**/*', route => {
            route.fulfill({ body: '<html></html>' }).catch(() => {});
          });
          await page.goto('/');
          const value = await page.evaluate(() => localStorage['name']);
          expect(value).toBe('value');
        });
      `,
    };

    test('globalSetup should work for auth', async ({ runInlineTest }) => {
      const result = await runInlineTest(authFiles, undefined, env);
      expect(result.exitCode).toBe(0);
      expect(result.passed).toBe(1);
    });

    test('globalSetup auth should compile', async ({ runTSC }) => {
      const result = await runTSC(authFiles);
      expect(result.exitCode).toBe(0);
    });
  });
}

{'fraction_non_alphanumeric': 0.15574235470063433, 'fraction_numerical': 0.006704141096384921, 'mean_word_length': 1.8186046511627907, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 89, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '121908', 'n_tokens_mistral': 5535, 'n_tokens_neox': 5415, 'n_words': 1220}