diff --git a/src/libs/E2E/client.ts b/src/libs/E2E/client.ts index 5aa999267ead..7a0259de7eef 100644 --- a/src/libs/E2E/client.ts +++ b/src/libs/E2E/client.ts @@ -1,6 +1,7 @@ import Config from '../../../tests/e2e/config'; import Routes from '../../../tests/e2e/server/routes'; import type {NetworkCacheMap, TestConfig, TestResult} from './types'; +import {waitForActiveRequestsToBeEmpty} from './utils/NetworkInterceptor'; type NativeCommandPayload = { text: string; @@ -57,7 +58,7 @@ const submitTestResults = (testResult: TestResult): Promise => { }); }; -const submitTestDone = () => fetch(`${SERVER_ADDRESS}${Routes.testDone}`, defaultRequestInit); +const submitTestDone = () => waitForActiveRequestsToBeEmpty().then(() => fetch(`${SERVER_ADDRESS}${Routes.testDone}`, defaultRequestInit)); let currentActiveTestConfig: TestConfig | null = null; diff --git a/src/libs/E2E/utils/NetworkInterceptor.ts b/src/libs/E2E/utils/NetworkInterceptor.ts index 3a4a48f7db53..ad23afeb0c3b 100644 --- a/src/libs/E2E/utils/NetworkInterceptor.ts +++ b/src/libs/E2E/utils/NetworkInterceptor.ts @@ -1,4 +1,5 @@ /* eslint-disable @lwc/lwc/no-async-await */ +import {DeviceEventEmitter} from 'react-native'; import type {NetworkCacheEntry, NetworkCacheMap} from '@libs/E2E/types'; const LOG_TAG = `[E2E][NetworkInterceptor]`; @@ -93,6 +94,33 @@ function hashFetchArgs(args: Parameters) { return `${url}${JSON.stringify(headers)}`; } +let activeRequestsCount = 0; + +const ACTIVE_REQUESTS_QUEUE_IS_EMPTY_EVENT = 'activeRequestsQueueIsEmpty'; + +/** + * Assures that ongoing network requests are empty. **Highly desirable** to call this function before closing the app. + * Otherwise if some requests are persisted - they will be executed on the next app start. And it can lead to a situation + * 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) + * and such big amount of requests can lead to a situation, where first app run (in test suite to cache network requests) + * may be blocked by spinners and lead to unbelievable big time execution, which eventually will be bigger than timeout and + * will lead to a test failure. + */ +function waitForActiveRequestsToBeEmpty(): Promise { + console.debug('Waiting for requests queue to be empty...', activeRequestsCount); + + if (activeRequestsCount === 0) { + return Promise.resolve(); + } + + return new Promise((resolve) => { + const subscription = DeviceEventEmitter.addListener(ACTIVE_REQUESTS_QUEUE_IS_EMPTY_EVENT, () => { + subscription.remove(); + resolve(); + }); + }); +} + /** * Install a network interceptor by overwriting the global fetch function: * - Overwrites fetch globally with a custom implementation @@ -145,6 +173,8 @@ export default function installNetworkInterceptor( console.debug('!!! Missed cache hit for url:', url); } + activeRequestsCount++; + return originalFetch(...args) .then(async (res) => { if (networkCache != null) { @@ -166,6 +196,16 @@ export default function installNetworkInterceptor( .then((res) => { console.debug(LOG_TAG, 'Network cache updated!'); return res; + }) + .finally(() => { + console.debug('Active requests count:', activeRequestsCount); + + activeRequestsCount--; + + if (activeRequestsCount === 0) { + DeviceEventEmitter.emit(ACTIVE_REQUESTS_QUEUE_IS_EMPTY_EVENT); + } }); }; } +export {waitForActiveRequestsToBeEmpty}; diff --git a/tests/e2e/config.ts b/tests/e2e/config.ts index c7cb9d0ed3c7..790836e54a08 100644 --- a/tests/e2e/config.ts +++ b/tests/e2e/config.ts @@ -68,7 +68,6 @@ export default { TESTS_CONFIG: { [TEST_NAMES.AppStartTime]: { name: TEST_NAMES.AppStartTime, - warmupRuns: 1, // ... any additional config you might need }, [TEST_NAMES.OpenChatFinderPage]: { diff --git a/tests/e2e/testRunner.ts b/tests/e2e/testRunner.ts index f2f4d6290e31..a8295f6ddf5c 100644 --- a/tests/e2e/testRunner.ts +++ b/tests/e2e/testRunner.ts @@ -185,7 +185,7 @@ const runTests = async (): Promise => { // by default we do 2 warmups: // - first warmup to pass a login flow // - second warmup to pass an actual flow and cache network requests - const iterations = test.warmupRuns ?? 2; + const iterations = 2; for (let i = 0; i < iterations; i++) { // Warmup the main app: await runTestIteration(config.MAIN_APP_PACKAGE, `[MAIN] ${warmupText}. Iteration ${i + 1}/${iterations}`);