2023-01-13 00:02:54 +03:00
|
|
|
/**
|
|
|
|
* Copyright (c) Microsoft Corporation.
|
|
|
|
*
|
|
|
|
* 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 path from 'path';
|
|
|
|
import { test, expect } from './playwright-test-fixtures';
|
|
|
|
|
2023-01-18 23:56:03 +03:00
|
|
|
test.fixme(true, 'Restore this');
|
|
|
|
|
2023-01-13 00:02:54 +03:00
|
|
|
type Timeline = { titlePath: string[], event: 'begin' | 'end' }[];
|
|
|
|
|
|
|
|
function formatTimeline(timeline: Timeline) {
|
|
|
|
return timeline.map(e => `${e.titlePath.slice(1).join(' > ')} [${e.event}]`).join('\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
function formatFileNames(timeline: Timeline) {
|
|
|
|
return timeline.map(e => e.titlePath[2]).join('\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
function fileNames(timeline: Timeline) {
|
|
|
|
const fileNames = Array.from(new Set(timeline.map(({ titlePath }) => {
|
|
|
|
const name = titlePath[2];
|
|
|
|
const index = name.lastIndexOf(path.sep);
|
|
|
|
if (index === -1)
|
|
|
|
return name;
|
|
|
|
return name.slice(index + 1);
|
|
|
|
})).keys());
|
|
|
|
fileNames.sort();
|
|
|
|
return fileNames;
|
|
|
|
}
|
|
|
|
|
|
|
|
function expectFilesRunBefore(timeline: Timeline, before: string[], after: string[]) {
|
|
|
|
const fileBegin = name => {
|
|
|
|
const index = timeline.findIndex(({ titlePath }) => titlePath[2] === name);
|
|
|
|
expect(index, `cannot find ${name} in\n${formatFileNames(timeline)}`).not.toBe(-1);
|
|
|
|
return index;
|
|
|
|
};
|
|
|
|
const fileEnd = name => {
|
|
|
|
// There is no Array.findLastIndex in Node < 18.
|
|
|
|
let index = -1;
|
|
|
|
for (index = timeline.length - 1; index >= 0; index--) {
|
|
|
|
if (timeline[index].titlePath[2] === name)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
expect(index, `cannot find ${name} in\n${formatFileNames(timeline)}`).not.toBe(-1);
|
|
|
|
return index;
|
|
|
|
};
|
|
|
|
|
|
|
|
for (const b of before) {
|
|
|
|
const bEnd = fileEnd(b);
|
|
|
|
for (const a of after) {
|
|
|
|
const aBegin = fileBegin(a);
|
|
|
|
expect(bEnd < aBegin, `'${b}' expected to finish before ${a}, actual order:\n${formatTimeline(timeline)}`).toBeTruthy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
test('should work for one project', async ({ runGroups }, testInfo) => {
|
|
|
|
const files = {
|
|
|
|
'playwright.config.ts': `
|
|
|
|
module.exports = {
|
|
|
|
globalScripts: /.*global.ts/,
|
|
|
|
projects: [
|
|
|
|
{
|
|
|
|
name: 'p1',
|
|
|
|
testMatch: /.*.test.ts/,
|
|
|
|
},
|
|
|
|
]
|
|
|
|
};`,
|
|
|
|
'a.test.ts': `
|
|
|
|
const { test } = pwt;
|
|
|
|
test('test1', async () => { });
|
|
|
|
test('test2', async () => { });
|
|
|
|
`,
|
|
|
|
'global.ts': `
|
|
|
|
const { test } = pwt;
|
|
|
|
test('setup1', async () => { });
|
|
|
|
test('setup2', async () => { });
|
|
|
|
`,
|
|
|
|
};
|
|
|
|
const { exitCode, passed, timeline } = await runGroups(files);
|
|
|
|
expect(exitCode).toBe(0);
|
|
|
|
expect(passed).toBe(4);
|
|
|
|
expect(formatTimeline(timeline)).toEqual(`Global Scripts > global.ts > setup1 [begin]
|
|
|
|
Global Scripts > global.ts > setup1 [end]
|
|
|
|
Global Scripts > global.ts > setup2 [begin]
|
|
|
|
Global Scripts > global.ts > setup2 [end]
|
|
|
|
p1 > a.test.ts > test1 [begin]
|
|
|
|
p1 > a.test.ts > test1 [end]
|
|
|
|
p1 > a.test.ts > test2 [begin]
|
|
|
|
p1 > a.test.ts > test2 [end]`);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should work for several projects', async ({ runGroups }, testInfo) => {
|
|
|
|
const files = {
|
|
|
|
'playwright.config.ts': `
|
|
|
|
module.exports = {
|
|
|
|
globalScripts: /.*global.ts/,
|
|
|
|
projects: [
|
|
|
|
{
|
|
|
|
name: 'p1',
|
|
|
|
testMatch: /.*a.test.ts/,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'p2',
|
|
|
|
testMatch: /.*b.test.ts/,
|
|
|
|
},
|
|
|
|
]
|
|
|
|
};`,
|
|
|
|
'a.test.ts': `
|
|
|
|
const { test } = pwt;
|
|
|
|
test('test1', async () => { });
|
|
|
|
test('test2', async () => { });
|
|
|
|
`,
|
|
|
|
'b.test.ts': `
|
|
|
|
const { test } = pwt;
|
|
|
|
test('test1', async () => { });
|
|
|
|
test('test2', async () => { });
|
|
|
|
`,
|
|
|
|
'global.ts': `
|
|
|
|
const { test } = pwt;
|
|
|
|
test('setup1', async () => { });
|
|
|
|
test('setup2', async () => { });
|
|
|
|
`,
|
|
|
|
};
|
|
|
|
const { exitCode, passed, timeline } = await runGroups(files);
|
|
|
|
expect(exitCode).toBe(0);
|
|
|
|
expect(passed).toBe(6);
|
|
|
|
expectFilesRunBefore(timeline, [`global.ts`], [`a.test.ts`, `b.test.ts`]);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should skip tests if global setup fails', async ({ runGroups }, testInfo) => {
|
|
|
|
const files = {
|
|
|
|
'playwright.config.ts': `
|
|
|
|
module.exports = {
|
|
|
|
globalScripts: /.*global.ts/,
|
|
|
|
projects: [
|
|
|
|
{
|
|
|
|
name: 'p1',
|
|
|
|
testMatch: /.*a.test.ts/,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'p2',
|
|
|
|
testMatch: /.*b.test.ts/,
|
|
|
|
},
|
|
|
|
]
|
|
|
|
};`,
|
|
|
|
'a.test.ts': `
|
|
|
|
const { test } = pwt;
|
|
|
|
test('test1', async () => { });
|
|
|
|
test('test2', async () => { });
|
|
|
|
`,
|
|
|
|
'b.test.ts': `
|
|
|
|
const { test } = pwt;
|
|
|
|
test('test1', async () => { });
|
|
|
|
`,
|
|
|
|
'global.ts': `
|
|
|
|
const { test, expect } = pwt;
|
|
|
|
test('setup1', async () => { });
|
|
|
|
test('setup2', async () => { expect(1).toBe(2) });
|
|
|
|
`,
|
|
|
|
};
|
|
|
|
const { exitCode, passed, skipped } = await runGroups(files);
|
|
|
|
expect(exitCode).toBe(1);
|
|
|
|
expect(passed).toBe(1);
|
|
|
|
expect(skipped).toBe(3);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should run setup in each project shard', async ({ runGroups }, testInfo) => {
|
|
|
|
const files = {
|
|
|
|
'playwright.config.ts': `
|
|
|
|
module.exports = {
|
|
|
|
globalScripts: /.*global.ts/,
|
|
|
|
projects: [
|
|
|
|
{
|
|
|
|
name: 'p1',
|
|
|
|
},
|
|
|
|
]
|
|
|
|
};`,
|
|
|
|
'a.test.ts': `
|
|
|
|
const { test } = pwt;
|
|
|
|
test('test1', async () => { });
|
|
|
|
test('test2', async () => { });
|
|
|
|
test('test3', async () => { });
|
|
|
|
test('test4', async () => { });
|
|
|
|
`,
|
|
|
|
'b.test.ts': `
|
|
|
|
const { test } = pwt;
|
|
|
|
test('test1', async () => { });
|
|
|
|
test('test2', async () => { });
|
|
|
|
`,
|
|
|
|
'global.ts': `
|
|
|
|
const { test, expect } = pwt;
|
|
|
|
test('setup1', async () => { });
|
|
|
|
test('setup2', async () => { });
|
|
|
|
`,
|
|
|
|
};
|
|
|
|
|
|
|
|
{ // Shard 1/2
|
|
|
|
const { exitCode, passed, timeline, output } = await runGroups(files, { shard: '1/2' });
|
|
|
|
expect(output).toContain('Running 6 tests using 1 worker, shard 1 of 2');
|
|
|
|
expect(fileNames(timeline)).toEqual(['a.test.ts', 'global.ts']);
|
|
|
|
expectFilesRunBefore(timeline, [`global.ts`], [`a.test.ts`]);
|
|
|
|
expect(exitCode).toBe(0);
|
|
|
|
expect(passed).toBe(6);
|
|
|
|
}
|
|
|
|
{ // Shard 2/2
|
|
|
|
const { exitCode, passed, timeline, output } = await runGroups(files, { shard: '2/2' });
|
|
|
|
expect(output).toContain('Running 4 tests using 1 worker, shard 2 of 2');
|
|
|
|
expect(fileNames(timeline)).toEqual(['b.test.ts', 'global.ts']);
|
|
|
|
expectFilesRunBefore(timeline, [`global.ts`], [`b.test.ts`]);
|
|
|
|
expect(exitCode).toBe(0);
|
|
|
|
expect(passed).toBe(4);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|