diff --git a/test/source/test.ts b/test/source/test.ts index a389ed7356d..8e8e1d600f9 100644 --- a/test/source/test.ts +++ b/test/source/test.ts @@ -24,7 +24,7 @@ import { defineSetupTests } from './tests/setup'; import { defineUnitBrowserTests } from './tests/unit-browser'; import { defineUnitNodeTests } from './tests/unit-node'; -export const { testVariant, testGroup, oneIfNotPooled, poolSize, buildDir, isMock } = getParsedCliParams(); +export const { testVariant, testGroup, oneIfNotPooled, poolSize, buildDir, extensionId, isMock } = getParsedCliParams(); export const internalTestState = { expectIntentionalErrReport: false }; // updated when a particular test that causes an error is run const DEBUG_BROWSER_LOG = false; // set to true to print / export information from browser const DEBUG_MOCK_LOG = false; // set to true to print mock server logs @@ -65,7 +65,7 @@ const testWithBrowser = ( if (isMock) { t.context.mockApi = mockApi; } else { - t.context.urls = new TestUrls(await browserPool.getExtensionId(t)); + t.context.urls = new TestUrls(extensionId ?? (await browserPool.getExtensionId(t))); } try { await browserPool.withNewBrowserTimeoutAndRetry( diff --git a/test/source/tests/page-recipe/oauth-page-recipe.ts b/test/source/tests/page-recipe/oauth-page-recipe.ts index 96a991fd23f..2cc62918f88 100644 --- a/test/source/tests/page-recipe/oauth-page-recipe.ts +++ b/test/source/tests/page-recipe/oauth-page-recipe.ts @@ -78,6 +78,7 @@ export class OauthPageRecipe extends PageRecipe { auth0loginBtn: 'button[type=submit][name=action][value=default]', googleApproveBtn: '#submit_approve_access', googleContinueAuthBtn: '.VfPpkd-LgbsSe', + googleSignInWithGoogleContinueBtn: '//button[.//span[normalize-space(.)="Continue"]]', }; try { const alreadyLoggedSelector = '.w6VTHd, .wLBAL, .yAlK0b'; @@ -123,6 +124,17 @@ export class OauthPageRecipe extends PageRecipe { const actionButtons = await oauthPage.target.$$(selectors.googleContinueAuthBtn); await oauthPage.waitForNavigationIfAny(() => actionButtons[actionButtons.length - 1].click()); } + if (await oauthPage.isElementPresent(selectors.googleSignInWithGoogleContinueBtn)) { + // "Sign in with Google" can show a re-auth confirmation before the OAuth approval screen. + await oauthPage.waitForNavigationIfAny( + () => oauthPage.waitAndClick(selectors.googleSignInWithGoogleContinueBtn, { delay: 1 }), + OauthPageRecipe.longTimeout + ); + await Util.sleep(2); + if (oauthPage.page.isClosed()) { + return; + } + } await oauthPage.waitAny([selectors.googleApproveBtn, selectors.auth0username]); if (await oauthPage.isElementPresent(selectors.auth0username)) { await oauthPage.waitAndType(selectors.auth0username, acctEmail); diff --git a/test/source/util/index.ts b/test/source/util/index.ts index 9b18f59c98d..d789b08eb60 100644 --- a/test/source/util/index.ts +++ b/test/source/util/index.ts @@ -1,6 +1,7 @@ /* ©️ 2016 - present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com */ import * as fs from 'fs'; +import { createHash } from 'crypto'; import { join } from 'path'; import { ElementHandle, Keyboard, KeyInput } from 'puppeteer'; import { BrowserHandle } from '../browser/browser-handle.js'; @@ -32,12 +33,22 @@ export const getParsedCliParams = () => { } const buildVariant = testVariant === 'CONSUMER-LIVE-GMAIL' ? 'CONSUMER-LOCAL' : testVariant; const buildDir = join(ROOT_DIR, `build/chrome-${buildVariant.toLowerCase()}`); + const extensionId = testVariant === 'CONSUMER-LIVE-GMAIL' ? getExtensionIdFromManifestKey(buildDir) : undefined; const poolSizeArg = process.argv.find(a => a.startsWith('--pool-size=')); const poolSize = poolSizeArg ? parseInt(poolSizeArg.split('=')[1], 10) : undefined; const poolSizeOne = poolSize === 1; const oneIfNotPooled = (suggestedPoolSize: number) => (poolSizeOne ? 1 : suggestedPoolSize); console.info(`TEST_VARIANT: ${testVariant}:${testGroup}, (build dir: ${buildDir}, poolSize: ${poolSize ?? 'default'})`); - return { testVariant, testGroup, oneIfNotPooled, poolSize, buildDir, isMock: testVariant.includes('-MOCK') }; + return { testVariant, testGroup, oneIfNotPooled, poolSize, buildDir, extensionId, isMock: testVariant.includes('-MOCK') }; +}; + +const getExtensionIdFromManifestKey = (buildDir: string): string => { + const manifest = JSON.parse(fs.readFileSync(join(buildDir, 'manifest.json'), 'utf8')) as { key?: string }; + if (!manifest.key) { + throw new Error(`Cannot determine fixed extension id because manifest key is missing from ${buildDir}/manifest.json`); + } + const hash = createHash('sha256').update(Buffer.from(manifest.key, 'base64')).digest('hex').slice(0, 32); + return hash.replace(/[0-9a-f]/g, c => String.fromCharCode('a'.charCodeAt(0) + parseInt(c, 16))); }; export type TestMessage = {