Skip to content

Commit 2ac6dd6

Browse files
authored
Merge pull request #43038 from margelo/e2e/terminate-app-only-when-no-active-requests
[NoQA] e2e: terminate app only when all network requests were finished
2 parents 67ec334 + fae2bf2 commit 2ac6dd6

File tree

4 files changed

+43
-3
lines changed

4 files changed

+43
-3
lines changed

src/libs/E2E/client.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Config from '../../../tests/e2e/config';
22
import Routes from '../../../tests/e2e/server/routes';
33
import type {NetworkCacheMap, TestConfig, TestResult} from './types';
4+
import {waitForActiveRequestsToBeEmpty} from './utils/NetworkInterceptor';
45

56
type NativeCommandPayload = {
67
text: string;
@@ -57,7 +58,7 @@ const submitTestResults = (testResult: TestResult): Promise<void> => {
5758
});
5859
};
5960

60-
const submitTestDone = () => fetch(`${SERVER_ADDRESS}${Routes.testDone}`, defaultRequestInit);
61+
const submitTestDone = () => waitForActiveRequestsToBeEmpty().then(() => fetch(`${SERVER_ADDRESS}${Routes.testDone}`, defaultRequestInit));
6162

6263
let currentActiveTestConfig: TestConfig | null = null;
6364

src/libs/E2E/utils/NetworkInterceptor.ts

+40
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* eslint-disable @lwc/lwc/no-async-await */
2+
import {DeviceEventEmitter} from 'react-native';
23
import type {NetworkCacheEntry, NetworkCacheMap} from '@libs/E2E/types';
34

45
const LOG_TAG = `[E2E][NetworkInterceptor]`;
@@ -93,6 +94,33 @@ function hashFetchArgs(args: Parameters<typeof fetch>) {
9394
return `${url}${JSON.stringify(headers)}`;
9495
}
9596

97+
let activeRequestsCount = 0;
98+
99+
const ACTIVE_REQUESTS_QUEUE_IS_EMPTY_EVENT = 'activeRequestsQueueIsEmpty';
100+
101+
/**
102+
* Assures that ongoing network requests are empty. **Highly desirable** to call this function before closing the app.
103+
* Otherwise if some requests are persisted - they will be executed on the next app start. And it can lead to a situation
104+
* where we can have `N * M` requests (where `N` is the number of app run per test and `M` is the number of test suites)
105+
* and such big amount of requests can lead to a situation, where first app run (in test suite to cache network requests)
106+
* may be blocked by spinners and lead to unbelievable big time execution, which eventually will be bigger than timeout and
107+
* will lead to a test failure.
108+
*/
109+
function waitForActiveRequestsToBeEmpty(): Promise<void> {
110+
console.debug('Waiting for requests queue to be empty...', activeRequestsCount);
111+
112+
if (activeRequestsCount === 0) {
113+
return Promise.resolve();
114+
}
115+
116+
return new Promise((resolve) => {
117+
const subscription = DeviceEventEmitter.addListener(ACTIVE_REQUESTS_QUEUE_IS_EMPTY_EVENT, () => {
118+
subscription.remove();
119+
resolve();
120+
});
121+
});
122+
}
123+
96124
/**
97125
* Install a network interceptor by overwriting the global fetch function:
98126
* - Overwrites fetch globally with a custom implementation
@@ -145,6 +173,8 @@ export default function installNetworkInterceptor(
145173
console.debug('!!! Missed cache hit for url:', url);
146174
}
147175

176+
activeRequestsCount++;
177+
148178
return originalFetch(...args)
149179
.then(async (res) => {
150180
if (networkCache != null) {
@@ -166,6 +196,16 @@ export default function installNetworkInterceptor(
166196
.then((res) => {
167197
console.debug(LOG_TAG, 'Network cache updated!');
168198
return res;
199+
})
200+
.finally(() => {
201+
console.debug('Active requests count:', activeRequestsCount);
202+
203+
activeRequestsCount--;
204+
205+
if (activeRequestsCount === 0) {
206+
DeviceEventEmitter.emit(ACTIVE_REQUESTS_QUEUE_IS_EMPTY_EVENT);
207+
}
169208
});
170209
};
171210
}
211+
export {waitForActiveRequestsToBeEmpty};

tests/e2e/config.ts

-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ export default {
6868
TESTS_CONFIG: {
6969
[TEST_NAMES.AppStartTime]: {
7070
name: TEST_NAMES.AppStartTime,
71-
warmupRuns: 1,
7271
// ... any additional config you might need
7372
},
7473
[TEST_NAMES.OpenChatFinderPage]: {

tests/e2e/testRunner.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ const runTests = async (): Promise<void> => {
185185
// by default we do 2 warmups:
186186
// - first warmup to pass a login flow
187187
// - second warmup to pass an actual flow and cache network requests
188-
const iterations = test.warmupRuns ?? 2;
188+
const iterations = 2;
189189
for (let i = 0; i < iterations; i++) {
190190
// Warmup the main app:
191191
await runTestIteration(config.MAIN_APP_PACKAGE, `[MAIN] ${warmupText}. Iteration ${i + 1}/${iterations}`);

0 commit comments

Comments
 (0)