Skip to content

Commit 369f383

Browse files
#5972 Fix live test (#6127)
* fix: test * fix: test * fix: tests * fix: pacakge temp * fix: remove tap temp * fix: remove comment * fix: test * temp * fix: live test
1 parent 88c2449 commit 369f383

File tree

9 files changed

+52
-28
lines changed

9 files changed

+52
-28
lines changed

.semaphore/semaphore.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@ blocks:
3434
- npm -v
3535
- node -v
3636
- npm run-script test_ci_chrome_consumer
37-
- name: consumer mock - flaky test group
37+
- name: consumer mock - flaky test group 1
3838
commands:
39-
- npm run-script test_ci_chrome_consumer_flaky
39+
- npm run-script test_ci_chrome_consumer_flaky_1
40+
- name: consumer mock - flaky test group 2
41+
commands:
42+
- npm run-script test_ci_chrome_consumer_flaky_2
4043
- name: content script tests
4144
commands:
4245
- npm run-script test_ci_chrome_content_scripts

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@
8787
"test_ci_chrome_consumer_live_gmail": "npx ava --timeout=45m --verbose --tap --concurrency=1 build/test/test/source/test.js -- CONSUMER-LIVE-GMAIL STANDARD-GROUP | npx tap-xunit > report.xml",
8888
"test_ci_chrome_consumer": "npx ava --timeout=30m --verbose --concurrency=10 build/test/test/source/test.js -- CONSUMER-MOCK STANDARD-GROUP",
8989
"test_ci_chrome_enterprise": "npx ava --timeout=30m --verbose --tap --concurrency=10 build/test/test/source/test.js -- ENTERPRISE-MOCK STANDARD-GROUP | npx tap-xunit > report.xml",
90-
"test_ci_chrome_consumer_flaky": "npx ava --timeout=30m --verbose --tap --concurrency=10 build/test/test/source/test.js -- CONSUMER-MOCK FLAKY-GROUP | npx tap-xunit > report.xml",
90+
"test_ci_chrome_consumer_flaky": "npx ava --timeout=30m --verbose --tap --concurrency=1 build/test/test/source/test.js -- CONSUMER-MOCK FLAKY-GROUP | npx tap-xunit > report.xml",
91+
"test_ci_chrome_consumer_flaky_1": "npx ava --timeout=30m --verbose --tap --concurrency=1 build/test/test/source/test.js -- CONSUMER-MOCK FLAKY-GROUP-1 | npx tap-xunit > report.xml",
92+
"test_ci_chrome_consumer_flaky_2": "npx ava --timeout=30m --verbose --tap --concurrency=1 build/test/test/source/test.js -- CONSUMER-MOCK FLAKY-GROUP-2 | npx tap-xunit > report.xml",
9193
"test_ci_chrome_content_scripts": "npx ava --timeout=3m --verbose --tap build/test/test/source/test.js -- CONTENT-SCRIPT-TESTS > report.xml",
9294
"dev_start_gmail_mock_api": "./scripts/build.sh && cd ./conf && node ../build/tooling/tsc-compiler --project tsconfig.test.json && cd .. && node ./build/test/test/source/mock.js",
9395
"run_firefox": "npm run build-incremental && npx web-ext run --source-dir ./build/firefox-consumer/ --firefox-profile ~/.mozilla/firefox/flowcrypt-dev --keep-profile-changes",
@@ -118,4 +120,4 @@
118120
"prettier --write"
119121
]
120122
}
121-
}
123+
}

test/source/browser/browser-pool.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { TIMEOUT_DESTROY_UNEXPECTED_ALERT } from '.';
77
import { launch } from 'puppeteer';
88
import { addDebugHtml, AvaContext, newWithTimeoutsFunc } from '../tests/tooling';
99

10-
class TimeoutError extends Error {}
10+
class TimeoutError extends Error { }
1111

1212
export class BrowserPool {
1313
private semaphore: Semaphore;
@@ -41,6 +41,11 @@ export class BrowserPool {
4141
// Fix for CORS Private Network Access issues with Puppeteer 24.16.0+
4242
'--disable-web-security',
4343
];
44+
45+
if (process.env.CI || process.env.SEMAPHORE) {
46+
args.push('--disable-dev-shm-usage'); // Use /tmp instead of /dev/shm in CI
47+
args.push('--no-zygote'); // Helps prevent zombie processes
48+
}
4449
if (this.isMock) {
4550
args.push('--ignore-certificate-errors');
4651
args.push('--allow-insecure-localhost');
@@ -52,6 +57,7 @@ export class BrowserPool {
5257
headless: false,
5358
devtools: false,
5459
slowMo,
60+
timeout: 90000, // 90 seconds timeout for browser launch (CI can be slow)
5561
});
5662
const handle = new BrowserHandle(browser, this.semaphore, this.height, this.width);
5763
if (closeInitialPage) {

test/source/test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,10 @@ if (testGroup === 'UNIT-TESTS') {
238238
defineUnitBrowserTests(testVariant, testWithBrowser);
239239
} else if (testGroup === 'FLAKY-GROUP') {
240240
defineFlakyTests(testVariant, testWithBrowser);
241+
} else if (testGroup === 'FLAKY-GROUP-1') {
242+
defineFlakyTests(testVariant, testWithBrowser, 0, 2);
243+
} else if (testGroup === 'FLAKY-GROUP-2') {
244+
defineFlakyTests(testVariant, testWithBrowser, 1, 2);
241245
} else if (testGroup === 'CONTENT-SCRIPT-TESTS') {
242246
defineContentScriptTests(testWithBrowser);
243247
} else {

test/source/tests/flaky.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* ©️ 2016 - present FlowCrypt a.s. Limitations apply. Contact [email protected] */
22

3-
import test from 'ava';
3+
import avaTest, { Implementation } from 'ava';
44
import { expect } from 'chai';
55

66
import { Config, TestVariant, Util } from './../util';
@@ -29,7 +29,15 @@ import { minutes } from './tooling';
2929
// these tests are run serially, one after another, because they are somewhat more sensitive to parallel testing
3030
// eg if they are very cpu-sensitive (create key tests)
3131

32-
export const defineFlakyTests = (testVariant: TestVariant, testWithBrowser: TestWithBrowser) => {
32+
export const defineFlakyTests = (testVariant: TestVariant, testWithBrowser: TestWithBrowser, shardIndex = 0, totalShards = 1) => {
33+
let testCounter = 0;
34+
const test = (title: string, impl: Implementation<unknown[]>) => {
35+
if (testCounter++ % totalShards === shardIndex) {
36+
avaTest(title, impl);
37+
}
38+
};
39+
test.skip = avaTest.skip;
40+
3341
if (testVariant !== 'CONSUMER-LIVE-GMAIL') {
3442
test(
3543
'compose - own key expired - update and retry',
@@ -320,7 +328,7 @@ export const defineFlakyTests = (testVariant: TestVariant, testWithBrowser: Test
320328
'confirm',
321329
'cancel',
322330
'Messages to some recipients were sent successfully, while messages to [email protected], Mr Cc <[email protected]> ' +
323-
'encountered error(s) from Gmail. Please help us improve FlowCrypt by reporting the error to us.'
331+
'encountered error(s) from Gmail. Please help us improve FlowCrypt by reporting the error to us.'
324332
);
325333
await composePage.close();
326334
expect((await GoogleData.withInitializedData(acct)).searchMessagesBySubject(subject).length).to.equal(++expectedNumberOfPassedMessages);
@@ -345,7 +353,7 @@ export const defineFlakyTests = (testVariant: TestVariant, testWithBrowser: Test
345353
'error',
346354
'confirm',
347355
'Messages to some recipients were sent successfully, while messages to [email protected] ' +
348-
'encountered error(s) from Gmail: Invalid recipients\n\nPlease remove recipients, add them back and re-send the message.'
356+
'encountered error(s) from Gmail: Invalid recipients\n\nPlease remove recipients, add them back and re-send the message.'
349357
);
350358
await composePage.close();
351359
expect((await GoogleData.withInitializedData(acct)).searchMessagesBySubject(subject).length).to.equal(++expectedNumberOfPassedMessages);
@@ -370,7 +378,7 @@ export const defineFlakyTests = (testVariant: TestVariant, testWithBrowser: Test
370378
'error',
371379
'confirm',
372380
'Messages to some recipients were sent successfully, while messages to [email protected] ' +
373-
'encountered network errors. Please check your internet connection and try again.'
381+
'encountered network errors. Please check your internet connection and try again.'
374382
);
375383
await composePage.close();
376384
expect((await GoogleData.withInitializedData(acct)).searchMessagesBySubject(subject).length).to.equal(++expectedNumberOfPassedMessages);

test/source/tests/gmail.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,12 @@ export const defineGmailTests = (testVariant: TestVariant, testWithBrowser: Test
8383
};
8484

8585
const pageHasSecureDraft = async (gmailPage: ControllablePage, expectedContent?: string) => {
86-
const secureDraftFrame = await gmailPage.getFrame(['/chrome/elements/compose.htm', '&draftId=']);
86+
const secureDraftFrame = await gmailPage.getFrame(['/chrome/elements/compose.htm', '&draftId='], { sleep: 2 });
87+
await Util.sleep(3);
88+
// Wait for the iframe content to load - @input-body must exist first
89+
await secureDraftFrame.waitAll('@input-body');
8790
if (expectedContent) {
8891
await secureDraftFrame.waitForContent('@input-body', expectedContent);
89-
} else {
90-
await secureDraftFrame.waitAll('@input-body');
9192
}
9293
return secureDraftFrame;
9394
};
@@ -324,16 +325,13 @@ export const defineGmailTests = (testVariant: TestVariant, testWithBrowser: Test
324325
);
325326

326327
// convo-sensitive, draft-sensitive test
327-
// Couldn't figure out why pageHasSecureDraft can't find correct iframe
328-
// Need to fix later
329-
// https://flowcrypt.semaphoreci.com/jobs/0106da6d-46f5-44d3-9ebd-3421584220a0
330-
test.skip(
328+
test.serial(
331329
'mail.google.com - secure reply btn, reply draft',
332330
testWithBrowser(
333331
async (t, browser) => {
334332
await BrowserRecipe.setUpCommonAcct(t, browser, 'ci.tests.gmail');
335333
const gmailPage = await openGmailPage(t, browser);
336-
const threadId = '181d226b4e69f172'; // 1st message -- thread id
334+
const threadId = '19ae97b85fe4f50e'; // 1st message -- thread id
337335
await gotoGmailPage(gmailPage, `/${threadId}`); // go to encrypted convo
338336
await GmailPageRecipe.trimConvo(gmailPage, threadId);
339337
await gmailPage.waitAndClick('@secure-reply-button');
@@ -343,13 +341,16 @@ export const defineGmailTests = (testVariant: TestVariant, testWithBrowser: Test
343341
await createSecureDraft(t, browser, gmailPage, 'reply draft');
344342
await createSecureDraft(t, browser, gmailPage, 'offline reply draft', { offline: true });
345343
await gmailPage.reload({ timeout: TIMEOUT_PAGE_LOAD * 1000, waitUntil: 'load' }, true);
344+
// Wait for extension to re-inject iframes after reload
345+
await gmailPage.waitForIframes(3, 25); // 3 attempts, 25s each
346+
await Util.sleep(5); // Let Gmail settle after reload
346347
replyBox = await pageHasSecureDraft(gmailPage, 'offline reply draft');
347348
await Util.sleep(2);
348349
await replyBox.waitAndClick('@action-send', { confirmGone: true });
349350
await Util.sleep(2);
350351
await gmailPage.reload({ timeout: TIMEOUT_PAGE_LOAD * 1000, waitUntil: 'load' }, true);
351352
await gmailPage.waitAndClick('.h7:last-child .ajz', { delay: 1 }); // the small triangle which toggles the message details
352-
await gmailPage.waitForContent('.h7:last-child .ajA', 'Re: [ci.test] encrypted email for reply render'); // make sure that the subject of the sent draft is corrent
353+
await gmailPage.waitForContent('.h7:last-child .ajA', 'Re: [ci.test] secure reply btn, reply draft'); // make sure that the subject of the sent draft is corrent
353354
await GmailPageRecipe.trimConvo(gmailPage, threadId);
354355
},
355356
undefined,

test/source/tests/page-recipe/gmail-page-recipe.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ export class GmailPageRecipe extends PageRecipe {
4949
if (!lastMessageId || !lastMessageElement || lastMessageId === messageId) {
5050
break;
5151
}
52-
// deleting last reply
53-
const moreActionsButton = await lastMessageElement.$$('[aria-label="More message options"]');
54-
expect(moreActionsButton.length).to.equal(1);
55-
await moreActionsButton[0].click();
56-
await gmailPage.press('ArrowDown', 4);
52+
await Util.sleep(3);
53+
// deleting last reply - use waitAndClick for more reliable interaction with Gmail's dynamic UI
54+
await gmailPage.waitAndClick(`[${messageIdAttrName}="${lastMessageId}"] [aria-label="More message options"]`, { delay: 2 });
55+
await Util.sleep(3);
56+
await gmailPage.press('ArrowDown', 3);
5757
await gmailPage.press('Enter');
5858
await Util.sleep(3);
5959
await gmailPage.page.reload({ timeout: TIMEOUT_PAGE_LOAD * 1000, waitUntil: 'networkidle2' });

test/source/tests/tooling/browser-recipe.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export class BrowserRecipe {
7676
// close announcement about updated UI
7777
await chatFrame.waitAndClick('.fKz7Od', { delay: 1 });
7878
}
79-
await chatFrame.waitAny(['a.gb_6d', 'a.gb_Fc', 'a.gb_9d', 'a.gb_7d', 'a.gb_ce', 'a.gb_Sc']); // Google hangout logo
79+
await chatFrame.waitAny(['a.gb_de', 'a.gb_Vc', 'a.gb_he']); // Google hangout logo
8080
return googleChatPage;
8181
};
8282

test/source/util/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const ROOT_DIR = process.cwd();
1414

1515
export const getParsedCliParams = () => {
1616
let testVariant: TestVariant;
17-
let testGroup: 'FLAKY-GROUP' | 'STANDARD-GROUP' | 'UNIT-TESTS' | 'CONTENT-SCRIPT-TESTS' | undefined;
17+
let testGroup: 'FLAKY-GROUP' | 'FLAKY-GROUP-1' | 'FLAKY-GROUP-2' | 'STANDARD-GROUP' | 'UNIT-TESTS' | 'CONTENT-SCRIPT-TESTS' | undefined;
1818
if (process.argv.includes('CONTENT-SCRIPT-TESTS')) {
1919
testVariant = 'CONSUMER-CONTENT-SCRIPT-TESTS-MOCK';
2020
testGroup = 'CONTENT-SCRIPT-TESTS';
@@ -28,10 +28,10 @@ export const getParsedCliParams = () => {
2828
throw new Error('Unknown test type: specify CONSUMER-MOCK or ENTERPRISE-MOCK CONSUMER-LIVE-GMAIL');
2929
}
3030
if (!testGroup) {
31-
testGroup = process.argv.includes('UNIT-TESTS') ? 'UNIT-TESTS' : process.argv.includes('FLAKY-GROUP') ? 'FLAKY-GROUP' : 'STANDARD-GROUP';
31+
testGroup = process.argv.includes('UNIT-TESTS') ? 'UNIT-TESTS' : process.argv.includes('FLAKY-GROUP') ? 'FLAKY-GROUP' : process.argv.includes('FLAKY-GROUP-1') ? 'FLAKY-GROUP-1' : process.argv.includes('FLAKY-GROUP-2') ? 'FLAKY-GROUP-2' : 'STANDARD-GROUP';
3232
}
3333
const buildDir = join(ROOT_DIR, `build/chrome-${(testVariant === 'CONSUMER-LIVE-GMAIL' ? 'CONSUMER' : testVariant).toLowerCase()}`);
34-
const poolSizeOne = process.argv.includes('--pool-size=1') || ['FLAKY-GROUP', 'CONTENT-SCRIPT-TESTS'].includes(testGroup);
34+
const poolSizeOne = process.argv.includes('--pool-size=1') || ['FLAKY-GROUP', 'FLAKY-GROUP-1', 'FLAKY-GROUP-2', 'CONTENT-SCRIPT-TESTS'].includes(testGroup);
3535
const oneIfNotPooled = (suggestedPoolSize: number) => (poolSizeOne ? Math.min(1, suggestedPoolSize) : suggestedPoolSize);
3636
console.info(`TEST_VARIANT: ${testVariant}:${testGroup}, (build dir: ${buildDir}, poolSizeOne: ${poolSizeOne})`);
3737
return { testVariant, testGroup, oneIfNotPooled, buildDir, isMock: testVariant.includes('-MOCK') };

0 commit comments

Comments
 (0)