Skip to content

Commit 4fcba65

Browse files
committed
PRO-14812 fix: really skip skipped tests in Playwright
1 parent ee8b0d9 commit 4fcba65

File tree

11 files changed

+75
-55
lines changed

11 files changed

+75
-55
lines changed

src/types/checks.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
/**
22
* This type checks that the type `true` is passed to it.
33
*/
4-
export type Expect<T extends true> = T;
4+
export type Expect<Type extends true> = Type;
55

66
/**
77
* Returns `true` if types are exactly equal and `false` otherwise.
88
* IsEqual<{foo: string}, {foo: string}> = true.
99
* IsEqual<{readonly foo: string}, {foo: string}> = false.
1010
*/
1111
export type IsEqual<X, Y> =
12-
(<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
12+
(<Type>() => Type extends X ? 1 : 2) extends <Type>() => Type extends Y ? 1 : 2 ? true : false;
1313

1414
/**
1515
* Returns `true` if key is readonly in object and `false` otherwise.

src/utils/expect/additionalMatchers.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {toMatchScreenshot} from './toMatchScreenshot';
55
import type {Expect} from './Expect';
66
import type {NonSelectorAdditionalMatchers, SelectorMatchers} from './types';
77

8-
import {expect} from '@playwright/test';
8+
import {expect as playwrightExpect} from '@playwright/test';
99

1010
/**
1111
* Addition matchers.
@@ -16,68 +16,68 @@ export const additionalMatchers: NonSelectorAdditionalMatchers<unknown> & Select
1616
const {actualValue, description} = this;
1717

1818
if (typeof actualValue === 'string' || Array.isArray(actualValue)) {
19-
return expect(actualValue, description).toContain(expected);
19+
return playwrightExpect(actualValue, description).toContain(expected);
2020
}
2121

22-
return expect(actualValue, description).toEqual(
23-
expect.objectContaining(expected as Record<string, unknown>),
22+
return playwrightExpect(actualValue, description).toEqual(
23+
playwrightExpect.objectContaining(expected as Record<string, unknown>),
2424
);
2525
},
2626
async eql(this: Expect, expected) {
2727
const {actualValue, description} = this;
2828

29-
return expect(actualValue, description).toEqual(expected);
29+
return playwrightExpect(actualValue, description).toEqual(expected);
3030
},
3131
async gt(this: Expect, expected) {
3232
const {actualValue, description} = this;
3333

34-
return expect(actualValue, description).toBeGreaterThan(expected);
34+
return playwrightExpect(actualValue, description).toBeGreaterThan(expected);
3535
},
3636
async gte(this: Expect, expected) {
3737
const {actualValue, description} = this;
3838

39-
return expect(actualValue, description).toBeGreaterThanOrEqual(expected);
39+
return playwrightExpect(actualValue, description).toBeGreaterThanOrEqual(expected);
4040
},
4141
async lt(this: Expect, expected) {
4242
const {actualValue, description} = this;
4343

44-
return expect(actualValue, description).toBeLessThan(expected);
44+
return playwrightExpect(actualValue, description).toBeLessThan(expected);
4545
},
4646
async lte(this: Expect, expected) {
4747
const {actualValue, description} = this;
4848

49-
return expect(actualValue, description).toBeLessThanOrEqual(expected);
49+
return playwrightExpect(actualValue, description).toBeLessThanOrEqual(expected);
5050
},
5151
async match(this: Expect, expected) {
5252
const {actualValue, description} = this;
5353

54-
return expect(actualValue, description).toMatch(expected);
54+
return playwrightExpect(actualValue, description).toMatch(expected);
5555
},
5656
async notContains(this: Expect, expected) {
5757
const {actualValue, description} = this;
5858

5959
if (typeof actualValue === 'string' || Array.isArray(actualValue)) {
60-
return expect(actualValue, description).not.toContain(expected);
60+
return playwrightExpect(actualValue, description).not.toContain(expected);
6161
}
6262

63-
return expect(actualValue, description).not.toEqual(
64-
expect.objectContaining(expected as Record<string, unknown>),
63+
return playwrightExpect(actualValue, description).not.toEqual(
64+
playwrightExpect.objectContaining(expected as Record<string, unknown>),
6565
);
6666
},
6767
async notEql(this: Expect, expected) {
6868
const {actualValue, description} = this;
6969

70-
return expect(actualValue, description).not.toEqual(expected);
70+
return playwrightExpect(actualValue, description).not.toEqual(expected);
7171
},
7272
async notOk(this: Expect) {
7373
const {actualValue, description} = this;
7474

75-
return expect(actualValue, description).not.toBeTruthy();
75+
return playwrightExpect(actualValue, description).not.toBeTruthy();
7676
},
7777
async ok(this: Expect) {
7878
const {actualValue, description} = this;
7979

80-
return expect(actualValue, description).toBeTruthy();
80+
return playwrightExpect(actualValue, description).toBeTruthy();
8181
},
8282

8383
toMatchScreenshot(this: Expect, expectedScreenshotId, options = {}) {

src/utils/expect/applyAdditionalMatcher.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type {Fn, Selector, SelectorPropertyRetryData} from '../../types/internal
44

55
import type {Expect} from './Expect';
66

7-
import {expect} from '@playwright/test';
7+
import {expect as playwrightExpect} from '@playwright/test';
88

99
/**
1010
* Apply additional matcher (with retrying, if needed).
@@ -25,7 +25,7 @@ export const applyAdditionalMatcher = (
2525

2626
let context: Expect;
2727

28-
return expect(() => {
28+
return playwrightExpect(() => {
2929
const {args: selectorArgs, property, selector} = selectorPropertyRetryData;
3030

3131
const actualValue =

src/utils/expect/createExpectMethod.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import type {Fn, SelectorPropertyRetryData} from '../../types/internal';
1818
import type {Expect} from './Expect';
1919
import type {AssertionFunction, ExpectMethod} from './types';
2020

21-
import {expect} from '@playwright/test';
21+
import {expect as playwrightExpect} from '@playwright/test';
2222

2323
const additionalAssertionTimeoutInMs = 1_000;
2424

@@ -66,7 +66,7 @@ export const createExpectMethod = (
6666
});
6767
}
6868

69-
const assertion = expect(value, ctx.description) as unknown as Record<
69+
const assertion = playwrightExpect(value, ctx.description) as unknown as Record<
7070
string,
7171
Fn<unknown[], Promise<unknown>>
7272
>;

src/utils/expect/toMatchScreenshot.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import type {FilePathFromRoot, Selector, ToMatchScreenshotOptions, Url} from '..
2020

2121
import type {Expect} from './Expect';
2222

23-
import {expect} from '@playwright/test';
23+
import {expect as playwrightExpect} from '@playwright/test';
2424

2525
type AdditionalLogFields = {
2626
actualScreenshotId: string | undefined;
@@ -99,7 +99,7 @@ export const toMatchScreenshot = async (
9999
try {
100100
const playwrightLocator = actualValue.getPlaywrightLocator();
101101

102-
await expect(playwrightLocator, description).toHaveScreenshot(screenshotFileName, {
102+
await playwrightExpect(playwrightLocator, description).toHaveScreenshot(screenshotFileName, {
103103
mask: mask.map((selector) => selector.getPlaywrightLocator()),
104104
...restOptions,
105105
});

src/utils/report/client/groupLogEvents.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {LogEventType} from '../../../constants/internal';
1+
import {LogEventStatus, LogEventType} from '../../../constants/internal';
22

33
import type {LogEvent, LogEventWithChildren} from '../../../types/internal';
44

@@ -16,14 +16,18 @@ export const groupLogEvents = (logEvents: readonly LogEvent[]): readonly LogEven
1616
LogEventType.InternalAssert,
1717
];
1818

19+
const isTopLevelEvent = (logEvent: LogEvent): boolean =>
20+
topLevelTypes.includes(logEvent.type) ||
21+
logEvent.payload?.logEventStatus === LogEventStatus.Failed;
22+
1923
const result: LogEventWithChildren[] = [];
2024

2125
for (const logEvent of logEvents) {
2226
const last = result.at(-1);
2327
const newEvent: LogEventWithChildren = {children: [], ...logEvent};
2428

25-
if (topLevelTypes.includes(logEvent.type)) {
26-
if (last && !topLevelTypes.includes(last.type)) {
29+
if (isTopLevelEvent(logEvent)) {
30+
if (last && !isTopLevelEvent(last)) {
2731
const firstTopLevel: LogEventWithChildren = {
2832
children: [...result],
2933
message: 'Initialization',
@@ -38,7 +42,7 @@ export const groupLogEvents = (logEvents: readonly LogEvent[]): readonly LogEven
3842
}
3943

4044
result.push(newEvent);
41-
} else if (last && topLevelTypes.includes(last.type)) {
45+
} else if (last && isTopLevelEvent(last)) {
4246
(last.children as LogEventWithChildren[]).push(newEvent);
4347
} else {
4448
result.push(newEvent);

src/utils/report/client/render/TestRunDescription.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export const TestRunDescription: JSX.Component<Props> = ({fullTestRun}) => {
3131
const valueWithLinks = parseMarkdownLinks`${value}`;
3232
const metaHtml = (
3333
<>
34-
<dt class="test-description__term">{key}</dt>
34+
<dt class="test-description__term">{key}</dt>{' '}
3535
<dd class="test-description__definition">{valueWithLinks}</dd>
3636
</>
3737
);
@@ -49,7 +49,7 @@ export const TestRunDescription: JSX.Component<Props> = ({fullTestRun}) => {
4949

5050
traceHtml = (
5151
<>
52-
<dt class="test-description__term">{traceLabel}</dt>
52+
<dt class="test-description__term">{traceLabel}</dt>{' '}
5353
<dd class="test-description__definition">
5454
<a href={traceUrl} download={traceName} aria-label={traceLabel}>
5555
{traceName}
@@ -63,11 +63,11 @@ export const TestRunDescription: JSX.Component<Props> = ({fullTestRun}) => {
6363
<dl class="test-description" aria-label="Test meta data">
6464
<List elements={metaHtmls} />
6565
{traceHtml}
66-
<dt class="test-description__term">Date</dt>
66+
<dt class="test-description__term">Date</dt>{' '}
6767
<dd class="test-description__definition">
6868
<DatesInterval endTimeInMs={endTimeInMs} startTimeInMs={startTimeInMs} />
6969
</dd>
70-
<dt class="test-description__term">Duration</dt>
70+
<dt class="test-description__term">Duration</dt>{' '}
7171
<dd class="test-description__definition">
7272
<Duration durationInMs={endTimeInMs - startTimeInMs} />
7373
</dd>

src/utils/test/beforeTest.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {getTestFnAndReject} from './getTestFnAndReject';
2121

2222
import type {TestRunEvent, TestUnit, UtcTimeInMs} from '../../types/internal';
2323

24-
import {test} from '@playwright/test';
24+
import {test as playwrightTest} from '@playwright/test';
2525

2626
const additionToPlaywrightTestTimeout = 500;
2727

@@ -59,7 +59,9 @@ export const beforeTest = ({
5959
const testTimeout =
6060
IS_DEBUG || isUiMode ? MAX_TIMEOUT_IN_MS : (options.testTimeout ?? testTimeoutFromConfig);
6161

62-
test.setTimeout(testTimeout + additionToPlaywrightTestTimeout + (Date.now() - startTimeInMs));
62+
playwrightTest.setTimeout(
63+
testTimeout + additionToPlaywrightTestTimeout + (Date.now() - startTimeInMs),
64+
);
6365

6466
setTestIdleTimeout(testIdleTimeout);
6567
setTestTimeout(testTimeout);
@@ -75,6 +77,7 @@ export const beforeTest = ({
7577
const {onlog, reject, testFnWithReject} = getTestFnAndReject({
7678
isSkipped,
7779
runId,
80+
skipReason,
7881
testFn,
7982
testIdleTimeout,
8083
testTimeout,

src/utils/test/getTestFnAndReject.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,19 @@ import {getPromiseWithResolveAndReject} from '../promise';
88

99
import type {Onlog, RejectTestRun, RunId, TestFn, Void} from '../../types/internal';
1010

11+
import {test as playwrightTest} from '@playwright/test';
12+
1113
type Options = Readonly<{
1214
isSkipped: boolean;
1315
runId: RunId;
16+
skipReason: string | undefined;
1417
testFn: TestFn;
1518
testIdleTimeout: number;
1619
testTimeout: number;
1720
}>;
1821

1922
type Return = Readonly<{onlog: Onlog; reject: RejectTestRun; testFnWithReject: TestFn}>;
2023

21-
const skippedTestFnAndReject: Return = {
22-
onlog: () => undefined,
23-
reject: () => undefined,
24-
testFnWithReject: () => RESOLVED_PROMISE,
25-
};
26-
2724
/**
2825
* Get test function with execution timeout, idle timeout, reject and onlog functions,
2926
* by isSkipped flag, test function, runId, test execution timeout and test idle timeouts.
@@ -32,12 +29,23 @@ const skippedTestFnAndReject: Return = {
3229
export const getTestFnAndReject = ({
3330
isSkipped,
3431
runId,
32+
skipReason,
3533
testFn,
3634
testIdleTimeout,
3735
testTimeout,
3836
}: Options): Return => {
3937
if (isSkipped) {
40-
return skippedTestFnAndReject;
38+
return {
39+
onlog: () => undefined,
40+
reject: () => undefined,
41+
testFnWithReject: () => {
42+
try {
43+
playwrightTest.skip(true, skipReason);
44+
} catch {}
45+
46+
return RESOLVED_PROMISE;
47+
},
48+
};
4149
}
4250

4351
const {

src/utils/test/waitBeforeRetry.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {getPreviousRunId} from './getPreviousRunId';
77

88
import type {FullTestRun, RunId, TestStaticOptions} from '../../types/internal';
99

10-
import {test} from '@playwright/test';
10+
import {test as playwrightTest} from '@playwright/test';
1111

1212
const additionToTimeout = 10_000;
1313

@@ -57,7 +57,7 @@ export const waitBeforeRetry = async (
5757
return;
5858
}
5959

60-
test.setTimeout(timeoutInMs + additionToTimeout);
60+
playwrightTest.setTimeout(timeoutInMs + additionToTimeout);
6161

6262
const timeoutObject = setInterval(() => {
6363
void writeLogEventTime();

0 commit comments

Comments
 (0)