Skip to content

Commit 29f1c5d

Browse files
committed
PRO-16178 fix: use lexical steps stack via AsyncLocalStorage
1 parent 001c5ce commit 29f1c5d

16 files changed

Lines changed: 115 additions & 131 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ If the mapping returns `undefined`, the log entry is not skipped, but is printed
333333
For example, if it is equal to three, the test will be run no more than three times.
334334

335335
`navigationTimeout: number`: default timeout for navigation to url
336-
(`navigateToPage`, `navigateToUrl` actions) in milliseconds.
336+
(`navigateToUrl`, `setHeadersAndNavigateToUrl` actions) in milliseconds.
337337

338338
`overriddenConfigFields: PlaywrightTestConfig | null`: if not `null`, then this value will override
339339
fields of internal `Playwright` config.

autotests/pageObjects/pages/E2edReportExample/E2edReportExample.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ type CustomPageParams =
2121
* The e2ed report example page.
2222
*/
2323
export class E2edReportExample extends Page<CustomPageParams> {
24+
/**
25+
* Page navigation timeout.
26+
*/
27+
static override readonly navigationTimeout = 5_000;
28+
2429
/**
2530
* Page header.
2631
*/
@@ -47,11 +52,6 @@ export class E2edReportExample extends Page<CustomPageParams> {
4752
readonly navigationRetriesButtonSelected: Selector =
4853
this.navigationRetriesButton.filterByLocatorParameter('selected', 'true');
4954

50-
/**
51-
* Page navigation timeout.
52-
*/
53-
override readonly navigationTimeout = 5_000;
54-
5555
/**
5656
* Cookies that we set (additionally) on a page before navigating to it.
5757
*/

autotests/pageObjects/pages/Main.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ type CustomPageParams = Partial<RouteParams> | undefined;
1515
* The Main (index) page.
1616
*/
1717
export class Main extends Page<CustomPageParams> {
18+
/**
19+
* Page navigation timeout.
20+
*/
21+
static override readonly navigationTimeout = 12_000;
22+
1823
/**
1924
* Body selector.
2025
*/

src/Page.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ import type {
2424
* Abstract page with base methods.
2525
*/
2626
export abstract class Page<PageParams = undefined> {
27+
/**
28+
* Default timeout for navigation to url (`navigateToPage`, `navigateToUrl` actions) in milliseconds.
29+
*/
30+
static readonly navigationTimeout: number = 8_000;
31+
2732
/**
2833
* Type of page parameters.
2934
*/
@@ -40,12 +45,6 @@ export abstract class Page<PageParams = undefined> {
4045
*/
4146
readonly maxIntervalBetweenRequestsInMs: number;
4247

43-
/**
44-
* Default timeout for navigation to url (`navigateToPage`, `navigateToUrl` actions) in milliseconds.
45-
* The default value is taken from the corresponding field of the pack config.
46-
*/
47-
readonly navigationTimeout: number;
48-
4948
/**
5049
* Immutable page parameters.
5150
*/
@@ -67,12 +66,10 @@ export abstract class Page<PageParams = undefined> {
6766
this.pageParams = pageParams as PageParams;
6867

6968
const {
70-
navigationTimeout,
7169
waitForAllRequestsComplete: {maxIntervalBetweenRequestsInMs},
7270
} = getFullPackConfig();
7371

7472
this.maxIntervalBetweenRequestsInMs = maxIntervalBetweenRequestsInMs;
75-
this.navigationTimeout = navigationTimeout;
7673
}
7774

7875
/**
@@ -132,7 +129,7 @@ export abstract class Page<PageParams = undefined> {
132129
): Promise<NavigationReturn> {
133130
const navigationReturn = await navigateToUrl(url, {
134131
skipLogs: true,
135-
timeout: this.navigationTimeout,
132+
timeout: (this.constructor as typeof Page).navigationTimeout,
136133
...options,
137134
});
138135
const {statusCode} = navigationReturn;

src/README.md

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,39 +17,41 @@ Modules in the dependency graph should only import the modules above them:
1717
10. `utils/headers`
1818
11. `utils/viewport`
1919
12. `utils/parse`
20-
13. `utils/distanceBetweenSelectors`
21-
14. `utils/getDurationWithUnits`
22-
15. `utils/valueToString`
23-
16. `utils/error`
24-
17. `utils/asserts`
25-
18. `utils/object`
26-
19. `utils/uiMode`
27-
20. `utils/runLabel`
28-
21. `utils/clone`
29-
22. `utils/notIncludedInPackTests`
30-
23. `utils/userland`
31-
24. `utils/fn`
32-
25. `utils/environment`
33-
26. `utils/packCompiler`
34-
27. `config`
35-
28. `utils/config`
36-
29. `utils/generalLog`
37-
30. `utils/testFilePaths`
38-
31. `utils/exit`
39-
32. `utils/promise`
40-
33. `utils/resourceUsage`
41-
34. `utils/fs`
42-
35. `utils/getGlobalErrorHandler`
43-
36. `utils/tests`
44-
37. `utils/end`
45-
38. `utils/pack`
46-
39. `useContext`
47-
40. `context`
48-
41. `utils/apiStatistics`
49-
42. `utils/selectors`
50-
43. `selectors`
51-
44. `utils/log`
52-
45. `utils/waitForEvents`
53-
46. `utils/expect`
54-
47. `expect`
55-
48. ...
20+
13. `utils/step`
21+
14. `utils/distanceBetweenSelectors`
22+
15. `utils/getDurationWithUnits`
23+
16. `utils/valueToString`
24+
17. `utils/error`
25+
18. `utils/asserts`
26+
19. `utils/object`
27+
20. `utils/uiMode`
28+
21. `utils/runLabel`
29+
22. `utils/clone`
30+
23. `utils/notIncludedInPackTests`
31+
24. `utils/userland`
32+
25. `utils/fn`
33+
26. `utils/environment`
34+
27. `utils/packCompiler`
35+
28. `config`
36+
29. `utils/config`
37+
30. `utils/generalLog`
38+
31. `utils/testFilePaths`
39+
32. `utils/exit`
40+
33. `utils/promise`
41+
34. `utils/resourceUsage`
42+
35. `utils/fs`
43+
36. `utils/getGlobalErrorHandler`
44+
37. `utils/tests`
45+
38. `utils/end`
46+
39. `utils/pack`
47+
40. `useContext`
48+
41. `context`
49+
42. `utils/apiStatistics`
50+
43. `utils/selectors`
51+
44. `selectors`
52+
45. `utils/log`
53+
46. `step`
54+
47. `utils/waitForEvents`
55+
48. `utils/expect`
56+
49. `expect`
57+
50. ...

src/actions/pages/assertPage.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {LogEventStatus, LogEventType} from '../../constants/internal';
1+
import {ADDITIONAL_STEP_TIMEOUT, LogEventStatus, LogEventType} from '../../constants/internal';
22
import {step} from '../../step';
33
import {assertValueIsDefined} from '../../utils/asserts';
44
import {getDocumentUrl} from '../../utils/document';
@@ -38,7 +38,11 @@ export const assertPage = async <SomePageClass extends AnyPageClassType>(
3838

3939
return {documentUrl, isMatch, logEventStatus, routeParams};
4040
},
41-
{payload: {pageParams}, type: LogEventType.InternalAction},
41+
{
42+
payload: {pageParams},
43+
timeout: PageClass.navigationTimeout + ADDITIONAL_STEP_TIMEOUT,
44+
type: LogEventType.InternalAction,
45+
},
4246
);
4347

4448
assertValueIsDefined(page, 'page is defined', {name: PageClass.name, pageParams});

src/actions/pages/navigateToPage.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {LogEventType} from '../../constants/internal';
1+
import {ADDITIONAL_STEP_TIMEOUT, LogEventType} from '../../constants/internal';
22
import {step} from '../../step';
33
import {addPageToApiStatistics} from '../../utils/apiStatistics';
44
import {assertValueIsDefined} from '../../utils/asserts';
@@ -56,7 +56,11 @@ export const navigateToPage = async <SomePageClass extends AnyPageClassType>(
5656

5757
return {documentUrl, isMatch, pageInstanceCreatedInMs, routeParams, url};
5858
},
59-
{payload: {pageParams}, type: LogEventType.InternalAction},
59+
{
60+
payload: {pageParams},
61+
timeout: PageClass.navigationTimeout + ADDITIONAL_STEP_TIMEOUT,
62+
type: LogEventType.InternalAction,
63+
},
6064
);
6165

6266
assertValueIsDefined(page, 'page is defined', {name: PageClass.name, pageParams});

src/context/stepsStack.ts

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/step.ts

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
/* eslint-disable max-lines */
2-
31
import {LogEventStatus, LogEventType} from './constants/internal';
4-
import {getStepsStack} from './context/stepsStack';
52
import {getTestIdleTimeout} from './context/testIdleTimeout';
63
import {E2edError} from './utils/error';
74
import {setCustomInspectOnFunction} from './utils/fn';
@@ -10,15 +7,9 @@ import {getDurationWithUnits} from './utils/getDurationWithUnits';
107
import {logAndGetLogEvent} from './utils/log';
118
import {setReadonlyProperty} from './utils/object';
129
import {addTimeoutToPromise} from './utils/promise';
10+
import {stepsStackStorage} from './utils/step';
1311

14-
import type {
15-
LogEvent,
16-
LogPayload,
17-
MaybePromise,
18-
Mutable,
19-
UtcTimeInMs,
20-
Void,
21-
} from './types/internal';
12+
import type {LogEvent, LogPayload, MaybePromise, UtcTimeInMs, Void} from './types/internal';
2213

2314
import {test as playwrightTest} from '@playwright/test';
2415

@@ -33,7 +24,7 @@ type Options = Readonly<{
3324
/**
3425
* Declares a test step (could calls Playwright's `test.step` function inside).
3526
*/
36-
// eslint-disable-next-line complexity, max-statements, max-lines-per-function
27+
// eslint-disable-next-line complexity, max-statements
3728
export const step = async (
3829
name: string,
3930
body?: () => MaybePromise<LogPayload | Void>,
@@ -44,7 +35,6 @@ export const step = async (
4435
}
4536

4637
let logEvent: LogEvent | undefined;
47-
const stepsStack = getStepsStack();
4838
const timeout: number = options?.timeout ?? getTestIdleTimeout();
4939

5040
if (options?.skipLogs !== true) {
@@ -55,10 +45,6 @@ export const step = async (
5545
);
5646
}
5747

58-
if (logEvent !== undefined) {
59-
(stepsStack as Mutable<typeof stepsStack>).push(logEvent);
60-
}
61-
6248
const errorProperties = {stepBody: body, stepName: name, stepOptions: options};
6349
let payload = undefined as LogPayload | Void;
6450
let stepError: unknown;
@@ -70,7 +56,11 @@ export const step = async (
7056
);
7157

7258
const runBody = async (): Promise<void> => {
73-
payload = await body?.();
59+
if (logEvent !== undefined && typeof body === 'function') {
60+
await stepsStackStorage.run(logEvent, body);
61+
} else {
62+
payload = await body?.();
63+
}
7464
};
7565

7666
let bodyError: unknown;
@@ -139,20 +129,6 @@ export const step = async (
139129
setReadonlyProperty(logEvent, 'payload', {...logEvent.payload, ...payload});
140130
}
141131

142-
const logEventIndex = stepsStack.findIndex((event) => event === logEvent);
143-
144-
if (logEventIndex === -1) {
145-
// eslint-disable-next-line no-unsafe-finally
146-
throw new E2edError('Cannot find running step in test steps stack', {
147-
runningStep: logEvent,
148-
stepBody: body,
149-
stepError,
150-
stepOptions: options,
151-
});
152-
}
153-
154-
(stepsStack as Mutable<typeof stepsStack>).splice(logEventIndex, 1);
155-
156132
generalLog(`Step "${name}" completed`, {
157133
body,
158134
step: {...logEvent, children: logEvent.children?.map(({message}) => message)},

src/types/config/ownE2edConfig.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ export type OwnE2edConfig<
172172
maxRetriesCountInDocker: number;
173173

174174
/**
175-
* Default timeout for navigation to url (`navigateToPage`, `navigateToUrl` actions) in milliseconds.
175+
* Default timeout for navigation to url (`navigateToUrl`, `setHeadersAndNavigateToUrl` actions) in milliseconds.
176176
*/
177177
navigationTimeout: number;
178178

0 commit comments

Comments
 (0)