Skip to content

Commit 05f83e8

Browse files
committed
test(functions): mitigate slow functions emulator e2e flakes
1 parent 48616ae commit 05f83e8

8 files changed

Lines changed: 217 additions & 61 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/** Server timeout for e2e callables that are not probing client deadline behavior. */
2+
export const E2E_TEST_FUNCTION_TIMEOUT_SECONDS = 120;

.github/workflows/scripts/functions/src/fetchAppCheckToken.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@
99

1010
import { getAppCheck } from 'firebase-admin/app-check';
1111
import { CallableRequest, onCall } from 'firebase-functions/v2/https';
12+
import { E2E_TEST_FUNCTION_TIMEOUT_SECONDS } from './e2eCallOptions';
1213
import { getAdminApp } from '.';
1314

1415
// Note: this will only work in a live environment, not locally via the Firebase emulator.
15-
export const fetchAppCheckTokenV2 = onCall(async (req: CallableRequest<{ appId: string }>) => {
16-
const { appId } = req.data;
17-
const expireTimeMillis = Math.floor(Date.now() / 1000) + 60 * 60;
18-
getAdminApp();
19-
const result = await getAppCheck().createToken(appId);
20-
return { ...result, expireTimeMillis };
21-
});
16+
export const fetchAppCheckTokenV2 = onCall(
17+
{ timeoutSeconds: E2E_TEST_FUNCTION_TIMEOUT_SECONDS },
18+
async (req: CallableRequest<{ appId: string }>) => {
19+
const { appId } = req.data;
20+
const expireTimeMillis = Math.floor(Date.now() / 1000) + 60 * 60;
21+
getAdminApp();
22+
const result = await getAppCheck().createToken(appId);
23+
return { ...result, expireTimeMillis };
24+
},
25+
);

.github/workflows/scripts/functions/src/sendFCM.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import { logger } from 'firebase-functions/v2';
1111
import { CallableRequest, onCall } from 'firebase-functions/v2/https';
1212
import { getMessaging, TokenMessage } from 'firebase-admin/messaging';
13+
import { E2E_TEST_FUNCTION_TIMEOUT_SECONDS } from './e2eCallOptions';
1314
import { getAdminApp } from '.';
1415

1516
// Note: this will only work in a live environment, not locally via the Firebase emulator.
1617
export const sendFCM = onCall(
18+
{ timeoutSeconds: E2E_TEST_FUNCTION_TIMEOUT_SECONDS },
1719
async (req: CallableRequest<{ message: TokenMessage; delay?: number }>) => {
1820
const { message, delay } = req.data;
1921
return await new Promise(() => {

.github/workflows/scripts/functions/src/testFunctionCustomRegion.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
*/
99

1010
import { onCall } from 'firebase-functions/v2/https';
11+
import { E2E_TEST_FUNCTION_TIMEOUT_SECONDS } from './e2eCallOptions';
1112

1213
export const testFunctionCustomRegion = onCall(
1314
{
1415
region: 'europe-west1',
16+
timeoutSeconds: E2E_TEST_FUNCTION_TIMEOUT_SECONDS,
1517
},
1618
() => 'europe-west1',
1719
);

.github/workflows/scripts/functions/src/testFunctionDefaultRegion.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
import { deepEqual } from 'assert';
1111
import { FirebaseError } from 'firebase-admin';
1212
import { CallableRequest, onCall, HttpsError } from 'firebase-functions/v2/https';
13+
import { E2E_TEST_FUNCTION_TIMEOUT_SECONDS } from './e2eCallOptions';
1314
import SAMPLE_DATA from './sample-data';
1415

1516
export const testFunctionDefaultRegionV2 = onCall(
17+
{ timeoutSeconds: E2E_TEST_FUNCTION_TIMEOUT_SECONDS },
1618
(req: CallableRequest<{ type: string; asError: boolean; inputData: any }>) => {
1719
console.log(Date.now(), req.data);
1820

.github/workflows/scripts/functions/src/testFunctionRemoteConfigUpdate.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010
import { getRemoteConfig } from 'firebase-admin/remote-config';
1111
import { logger } from 'firebase-functions/v2';
1212
import { CallableRequest, onCall } from 'firebase-functions/v2/https';
13+
import { E2E_TEST_FUNCTION_TIMEOUT_SECONDS } from './e2eCallOptions';
1314
import { getAdminApp } from '.';
1415

1516
export const testFunctionRemoteConfigUpdateV2 = onCall(
1617
{
1718
maxInstances: 1,
1819
concurrency: 1,
20+
timeoutSeconds: E2E_TEST_FUNCTION_TIMEOUT_SECONDS,
1921
},
2022
async (
2123
req: CallableRequest<{

.github/workflows/scripts/functions/src/testStreamingCallable.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import { onCall, CallableRequest, CallableResponse, HttpsError } from 'firebase-functions/v2/https';
22
import { logger } from 'firebase-functions/v2';
3+
import { E2E_TEST_FUNCTION_TIMEOUT_SECONDS } from './e2eCallOptions';
34
import SAMPLE_DATA from './sample-data';
45

6+
const e2eOnCall = (
7+
handler: (req: CallableRequest<any>, response?: CallableResponse<any>) => unknown,
8+
) => onCall({ timeoutSeconds: E2E_TEST_FUNCTION_TIMEOUT_SECONDS }, handler);
9+
510
/**
611
* Test streaming callable function that sends multiple chunks of data
712
* This function demonstrates Server-Sent Events (SSE) streaming
813
*/
9-
export const testStreamingCallable = onCall(
14+
export const testStreamingCallable = e2eOnCall(
1015
async (
1116
req: CallableRequest<{ count?: number; delay?: number }>,
1217
response?: CallableResponse<any>,
@@ -43,7 +48,7 @@ export const testStreamingCallable = onCall(
4348
/**
4449
* Test streaming callable that sends progressive updates
4550
*/
46-
export const testProgressStream = onCall(
51+
export const testProgressStream = e2eOnCall(
4752
async (req: CallableRequest<{ task?: string }>, response?: CallableResponse<any>) => {
4853
const task = req.data.task || 'Processing';
4954

@@ -71,7 +76,7 @@ export const testProgressStream = onCall(
7176
/**
7277
* Test streaming with complex data types
7378
*/
74-
export const testComplexDataStream = onCall(
79+
export const testComplexDataStream = e2eOnCall(
7580
async (req: CallableRequest, response?: CallableResponse<any>) => {
7681
logger.info('testComplexDataStream called');
7782

@@ -126,7 +131,7 @@ export const testComplexDataStream = onCall(
126131
/**
127132
* Test streaming with error handling
128133
*/
129-
export const testStreamWithError = onCall(
134+
export const testStreamWithError = e2eOnCall(
130135
async (
131136
req: CallableRequest<{ shouldError?: boolean; errorAfter?: number }>,
132137
response?: CallableResponse<any>,
@@ -161,7 +166,7 @@ export const testStreamWithError = onCall(
161166
* Test streaming callable that returns the type of data sent
162167
* Similar to Dart's testStreamResponse - sends back the type of input data
163168
*/
164-
export const testStreamResponse = onCall(
169+
export const testStreamResponse = e2eOnCall(
165170
async (req: CallableRequest<any>, response?: CallableResponse<any>) => {
166171
logger.info('testStreamResponse called', { data: req.data });
167172

@@ -207,7 +212,7 @@ export const testStreamResponse = onCall(
207212
* Test streaming callable that handles null data
208213
* This function specifically accepts null and returns success: true
209214
*/
210-
export const testStreamingCallableWithNull = onCall(
215+
export const testStreamingCallableWithNull = e2eOnCall(
211216
async (req: CallableRequest<any>, response?: CallableResponse<any>) => {
212217
logger.info('testStreamingCallableWithNull called', { data: req.data });
213218

@@ -228,7 +233,7 @@ export const testStreamingCallableWithNull = onCall(
228233
* Streaming callable that throws HttpsError (for testing stream-by-name).
229234
* Only throws: invalid-argument (bad/missing type), or cancelled with details (when asError).
230235
*/
231-
export const testStreamWithHttpsError = onCall(
236+
export const testStreamWithHttpsError = e2eOnCall(
232237
async (
233238
req: CallableRequest<{ type?: string; asError?: boolean; inputData?: any }>,
234239
response?: CallableResponse<any>,
@@ -263,7 +268,7 @@ export const testStreamWithHttpsError = onCall(
263268
* Streaming callable that throws HttpsError (for testing stream-from-URL).
264269
* Same behaviour as testStreamWithHttpsError; separate export for httpsCallableFromUrl.stream() e2e.
265270
*/
266-
export const testStreamWithHttpsErrorFromUrl = onCall(
271+
export const testStreamWithHttpsErrorFromUrl = e2eOnCall(
267272
async (
268273
req: CallableRequest<{ type?: string; asError?: boolean; inputData?: any }>,
269274
response?: CallableResponse<any>,

0 commit comments

Comments
 (0)