Skip to content

Commit 9323e9a

Browse files
authored
Reduce FM Integration Test Impact & Run Time (#4676)
* Initial Commit * Let get_delete_token run first
1 parent 72b1096 commit 9323e9a

8 files changed

+267
-142
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/**
2+
* @license
3+
* Copyright 2017 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
const testServer = require('./utils/test-server');
19+
const sendMessage = require('./utils/sendMessage');
20+
const retrieveToken = require('./utils/retrieveToken');
21+
const seleniumAssistant = require('selenium-assistant');
22+
const getReceivedBackgroundMessages = require('./utils/getReceivedBackgroundMessages');
23+
const createPermittedWebDriver = require('./utils/createPermittedWebDriver');
24+
const checkSendResponse = require('./utils/checkSendResponse');
25+
const checkMessageReceived = require('./utils/checkMessageReceived');
26+
const openNewTab = require('./utils/openNewTab');
27+
28+
const TEST_DOMAINS = ['valid-vapid-key-modern-sw'];
29+
30+
// 4 minutes. The fact that the flow includes making a request to the Send Service,
31+
// storing/retrieving form indexedDb asynchronously makes these test units to have a execution time
32+
// variance. Therefore, allowing these units to have a longer time to work is crucial.
33+
const TIMEOUT_BACKGROUND_MESSAGE_TEST_UNIT_MILLISECONDS = 240000;
34+
35+
// 1 minute. Wait for object store to be created and received message to be stored in idb. This
36+
// waiting time MUST be longer than the wait time for adding to db in the sw.
37+
const WAIT_TIME_BEFORE_RETRIEVING_BACKGROUND_MESSAGES_MILLISECONDS = 60000;
38+
39+
const wait = ms => new Promise(res => setTimeout(res, ms));
40+
41+
// 50% of integration test run time is spent in testing receiving in background. Running these
42+
// slower tests last so other tests can fail quickly if they do fail.
43+
require('./test-token-delete');
44+
require('./test-token-update');
45+
require('./test-useValidManifest');
46+
require('./test-useDefaultServiceWorker');
47+
require('./test-receive-foreground');
48+
49+
describe('Firebase Messaging Integration Tests > Test Background Receive', function () {
50+
this.retries(2);
51+
let globalWebDriver;
52+
53+
before(async function () {
54+
await testServer.start();
55+
});
56+
57+
after(async function () {
58+
await testServer.stop();
59+
});
60+
61+
// TODO: enable testing for firefox
62+
seleniumAssistant.getLocalBrowsers().forEach(assistantBrowser => {
63+
if (assistantBrowser.getId() !== 'chrome') {
64+
return;
65+
}
66+
67+
TEST_DOMAINS.forEach(domain => {
68+
describe(`Testing browser: ${assistantBrowser.getPrettyName()} : ${domain}`, function () {
69+
before(async function () {
70+
globalWebDriver = createPermittedWebDriver(
71+
/* browser= */ assistantBrowser.getId()
72+
);
73+
});
74+
75+
it('Background app can receive a {} empty message from sw', async function () {
76+
this.timeout(TIMEOUT_BACKGROUND_MESSAGE_TEST_UNIT_MILLISECONDS);
77+
78+
// Clearing the cache and db data by killing the previously instantiated driver. Note that
79+
// ideally this call is placed inside the after/before hooks. However, Mocha forbids
80+
// operations longer than 2s in hooks. Hence, this clearing call needs to be inside the
81+
// test unit.
82+
await seleniumAssistant.killWebDriver(globalWebDriver);
83+
84+
globalWebDriver = createPermittedWebDriver(
85+
/* browser= */ assistantBrowser.getId()
86+
);
87+
88+
prepareBackgroundApp(globalWebDriver, domain);
89+
90+
checkSendResponse(
91+
await sendMessage({
92+
to: await retrieveToken(globalWebDriver)
93+
})
94+
);
95+
96+
await wait(
97+
WAIT_TIME_BEFORE_RETRIEVING_BACKGROUND_MESSAGES_MILLISECONDS
98+
);
99+
100+
checkMessageReceived(
101+
await getReceivedBackgroundMessages(globalWebDriver),
102+
/* expectedNotificationPayload= */ null,
103+
/* expectedDataPayload= */ null,
104+
/* isLegacyPayload= */ false
105+
);
106+
});
107+
108+
it('Background app can receive a {"data"} message frow sw', async function () {
109+
this.timeout(TIMEOUT_BACKGROUND_MESSAGE_TEST_UNIT_MILLISECONDS);
110+
111+
await seleniumAssistant.killWebDriver(globalWebDriver);
112+
113+
globalWebDriver = createPermittedWebDriver(
114+
/* browser= */ assistantBrowser.getId()
115+
);
116+
117+
prepareBackgroundApp(globalWebDriver, domain);
118+
119+
checkSendResponse(
120+
await sendMessage({
121+
to: await retrieveToken(globalWebDriver),
122+
data: getTestDataPayload()
123+
})
124+
);
125+
126+
await wait(
127+
WAIT_TIME_BEFORE_RETRIEVING_BACKGROUND_MESSAGES_MILLISECONDS
128+
);
129+
130+
checkMessageReceived(
131+
await getReceivedBackgroundMessages(globalWebDriver),
132+
/* expectedNotificationPayload= */ null,
133+
/* expectedDataPayload= */ getTestDataPayload()
134+
);
135+
});
136+
});
137+
});
138+
});
139+
});
140+
141+
async function prepareBackgroundApp(globalWebDriver, domain) {
142+
await globalWebDriver.get(`${testServer.serverAddress}/${domain}/`);
143+
// TODO: remove the try/catch block once the underlying bug has been resolved. Shift window focus
144+
// away from app window so that background messages can be received/processed
145+
try {
146+
await openNewTab(globalWebDriver);
147+
} catch (err) {
148+
// ChromeDriver seems to have an open bug which throws "JavascriptError: javascript error:
149+
// circular reference". Nevertheless, a new tab can still be opened. Hence, just catch and
150+
// continue here.
151+
console.log('FCM (ignored on purpose): ' + err);
152+
}
153+
}
154+
155+
function getTestDataPayload() {
156+
return { hello: 'world' };
157+
}

integration/messaging/test/test-send.js renamed to integration/messaging/test/test-receive-foreground.js

Lines changed: 10 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -15,41 +15,24 @@
1515
* limitations under the License.
1616
*/
1717

18-
const expect = require('chai').expect;
1918
const testServer = require('./utils/test-server');
2019
const sendMessage = require('./utils/sendMessage');
2120
const retrieveToken = require('./utils/retrieveToken');
2221
const seleniumAssistant = require('selenium-assistant');
23-
const getReceivedBackgroundMessages = require('./utils/getReceivedBackgroundMessages');
22+
const checkSendResponse = require('./utils/checkSendResponse');
2423
const getReceivedForegroundMessages = require('./utils/getReceivedForegroundMessages');
25-
const openNewTab = require('./utils/openNewTab');
24+
const checkMessageReceived = require('./utils/checkMessageReceived');
2625
const createPermittedWebDriver = require('./utils/createPermittedWebDriver');
2726

28-
const TEST_DOMAINS = ['valid-vapid-key', 'valid-vapid-key-modern-sw'];
29-
const TEST_PROJECT_SENDER_ID = '750970317741';
30-
const DEFAULT_COLLAPSE_KEY_VALUE = 'do_not_collapse';
31-
const FIELD_FROM = 'from';
32-
const FIELD_COLLAPSE_KEY_LEGACY = 'collapse_key';
33-
const FIELD_COLLAPSE_KEY = 'collapseKey';
34-
35-
const FIELD_DATA = 'data';
36-
const FIELD_NOTIFICATION = 'notification';
37-
38-
// 4 minutes. The fact that the flow includes making a request to the Send Service,
39-
// storing/retrieving form indexedDb asynchronously makes these test units to have a execution time
40-
// variance. Therefore, allowing these units to have a longer time to work is crucial.
41-
const TIMEOUT_BACKGROUND_MESSAGE_TEST_UNIT_MILLISECONDS = 240000;
42-
27+
// Only testing 'valid-vapid-key' because 'valid-vapid-key-modern-sw' has the same behavior
28+
const TEST_DOMAINS = ['valid-vapid-key'];
4329
const TIMEOUT_FOREGROUND_MESSAGE_TEST_UNIT_MILLISECONDS = 120000;
4430

45-
// 1 minute. Wait for object store to be created and received message to be stored in idb. This
46-
// waiting time MUST be longer than the wait time for adding to db in the sw.
47-
const WAIT_TIME_BEFORE_RETRIEVING_BACKGROUND_MESSAGES_MILLISECONDS = 60000;
31+
// Getting and deleting token is the entry step of using FM SDK. Let it run first and fail quickly.
32+
require('./test-token-delete');
4833

49-
const wait = ms => new Promise(res => setTimeout(res, ms));
50-
51-
describe('Starting Integration Test > Sending and Receiving ', function () {
52-
this.retries(3);
34+
describe('Firebase Messaging Integration Tests > Test Foreground Receive', function () {
35+
this.retries(2);
5336
let globalWebDriver;
5437

5538
before(async function () {
@@ -73,68 +56,6 @@ describe('Starting Integration Test > Sending and Receiving ', function () {
7356
/* browser= */ assistantBrowser.getId()
7457
);
7558
});
76-
77-
it('Background app can receive a {} empty message from sw', async function () {
78-
this.timeout(TIMEOUT_BACKGROUND_MESSAGE_TEST_UNIT_MILLISECONDS);
79-
80-
// Clearing the cache and db data by killing the previously instantiated driver. Note that
81-
// ideally this call is placed inside the after/before hooks. However, Mocha forbids
82-
// operations longer than 2s in hooks. Hence, this clearing call needs to be inside the
83-
// test unit.
84-
await seleniumAssistant.killWebDriver(globalWebDriver);
85-
86-
globalWebDriver = createPermittedWebDriver(
87-
/* browser= */ assistantBrowser.getId()
88-
);
89-
90-
prepareBackgroundApp(globalWebDriver, domain);
91-
92-
checkSendResponse(
93-
await sendMessage({
94-
to: await retrieveToken(globalWebDriver)
95-
})
96-
);
97-
98-
await wait(
99-
WAIT_TIME_BEFORE_RETRIEVING_BACKGROUND_MESSAGES_MILLISECONDS
100-
);
101-
102-
checkMessageReceived(
103-
await getReceivedBackgroundMessages(globalWebDriver),
104-
/* expectedNotificationPayload= */ null,
105-
/* expectedDataPayload= */ null,
106-
/* isLegacyPayload= */ false
107-
);
108-
});
109-
110-
it('Background app can receive a {"data"} message frow sw', async function () {
111-
this.timeout(TIMEOUT_BACKGROUND_MESSAGE_TEST_UNIT_MILLISECONDS);
112-
113-
await seleniumAssistant.killWebDriver(globalWebDriver);
114-
115-
globalWebDriver = createPermittedWebDriver(
116-
/* browser= */ assistantBrowser.getId()
117-
);
118-
119-
prepareBackgroundApp(globalWebDriver, domain);
120-
121-
checkSendResponse(
122-
await sendMessage({
123-
to: await retrieveToken(globalWebDriver),
124-
data: getTestDataPayload()
125-
})
126-
);
127-
128-
await wait(
129-
WAIT_TIME_BEFORE_RETRIEVING_BACKGROUND_MESSAGES_MILLISECONDS
130-
);
131-
132-
checkMessageReceived(
133-
await getReceivedBackgroundMessages(globalWebDriver),
134-
/* expectedNotificationPayload= */ null,
135-
/* expectedDataPayload= */ getTestDataPayload()
136-
);
137-
});
13859
});
13960

14061
it('Foreground app can receive a {} empty message in onMessage', async function () {
@@ -241,35 +162,8 @@ describe('Starting Integration Test > Sending and Receiving ', function () {
241162
});
242163
});
243164

244-
function checkMessageReceived(
245-
receivedMessages,
246-
expectedNotificationPayload,
247-
expectedDataPayload
248-
) {
249-
expect(receivedMessages).to.exist;
250-
251-
const message = receivedMessages[0];
252-
253-
expect(message[FIELD_FROM]).to.equal(TEST_PROJECT_SENDER_ID);
254-
const collapseKey = !!message[FIELD_COLLAPSE_KEY_LEGACY]
255-
? message[FIELD_COLLAPSE_KEY_LEGACY]
256-
: message[FIELD_COLLAPSE_KEY];
257-
expect(collapseKey).to.equal(DEFAULT_COLLAPSE_KEY_VALUE);
258-
259-
if (expectedNotificationPayload) {
260-
expect(message[FIELD_NOTIFICATION]).to.deep.equal(
261-
getTestNotificationPayload()
262-
);
263-
}
264-
265-
if (expectedDataPayload) {
266-
expect(message[FIELD_DATA]).to.deep.equal(getTestDataPayload());
267-
}
268-
}
269-
270-
function checkSendResponse(response) {
271-
expect(response).to.exist;
272-
expect(response.success).to.equal(1);
165+
function getTestDataPayload() {
166+
return { hello: 'world' };
273167
}
274168

275169
function getTestNotificationPayload() {
@@ -281,22 +175,3 @@ function getTestNotificationPayload() {
281175
tag: 'test-tag'
282176
};
283177
}
284-
285-
function getTestDataPayload() {
286-
return { hello: 'world' };
287-
}
288-
289-
async function prepareBackgroundApp(globalWebDriver, domain) {
290-
await globalWebDriver.get(`${testServer.serverAddress}/${domain}/`);
291-
292-
// TODO: remove the try/catch block once the underlying bug has been resolved. Shift window focus
293-
// away from app window so that background messages can be received/processed
294-
try {
295-
await openNewTab(globalWebDriver);
296-
} catch (err) {
297-
// ChromeDriver seems to have an open bug which throws "JavascriptError: javascript error:
298-
// circular reference". Nevertheless, a new tab can still be opened. Hence, just catch and
299-
// continue here.
300-
console.log('FCM (ignored on purpose): ' + err);
301-
}
302-
}

integration/messaging/test/test-deleteToken.js renamed to integration/messaging/test/test-token-delete.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ const retrieveToken = require('./utils/retrieveToken');
2323
const seleniumAssistant = require('selenium-assistant');
2424
const createPermittedWebDriver = require('./utils/createPermittedWebDriver');
2525

26-
const TEST_SUITE_TIMEOUT_MS = 100000;
26+
const TEST_SUITE_TIMEOUT_MS = 20000;
2727
const TEST_DOMAIN = 'valid-vapid-key';
2828

2929
describe('Firebase Messaging Integration Tests > get and delete token', function () {
3030
this.timeout(TEST_SUITE_TIMEOUT_MS);
31-
this.retries(3);
31+
this.retries(2);
3232
let globalWebDriver;
3333

3434
before(async function () {

integration/messaging/test/test-updateToken.js renamed to integration/messaging/test/test-token-update.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@ const getErrors = require('./utils/getErrors');
2828
const TEST_SUITE_TIMEOUT_MS = 70000;
2929
const TEST_DOMAIN = 'valid-vapid-key';
3030

31+
// Getting and deleting token is the entry step of using FM SDK. Let it run first and fail quickly.
32+
require('./test-token-delete');
33+
3134
describe('Firebase Messaging Integration Tests > update a token', function () {
3235
this.timeout(TEST_SUITE_TIMEOUT_MS);
33-
this.retries(3);
36+
this.retries(2);
3437

3538
let globalWebDriver;
3639

integration/messaging/test/test-useDefaultServiceWorker.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ const createPermittedWebDriver = require('./utils/createPermittedWebDriver');
2424
const TEST_DOMAIN = 'default-sw';
2525
const TEST_SUITE_TIMEOUT_MS = 70000;
2626

27+
// Getting and deleting token is the entry step of using FM SDK. Let it run first and fail quickly.
28+
require('./test-token-delete');
29+
2730
describe(`Firebase Messaging Integration Tests > Use 'firebase-messaging-sw.js' by default`, function () {
2831
this.timeout(TEST_SUITE_TIMEOUT_MS);
2932

30-
this.retries(3);
31-
3233
let globalWebDriver;
3334

3435
before(async function () {

integration/messaging/test/test-useValidManifest.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ const createPermittedWebDriver = require('./utils/createPermittedWebDriver');
2424
const TEST_DOMAIN = 'valid-manifest';
2525
const TEST_SUITE_TIMEOUT_MS = 70000;
2626

27+
// Getting and deleting token is the entry step of using FM SDK. Let it run first and fail quickly.
28+
require('./test-token-delete');
29+
2730
describe(`Firebase Messaging Integration Tests > Use 'use valid manifest`, function () {
2831
this.timeout(TEST_SUITE_TIMEOUT_MS);
2932

30-
this.retries(3);
31-
3233
let globalWebDriver;
3334

3435
before(async function () {

0 commit comments

Comments
 (0)