Skip to content

CHI-3340-fix_e2e_auth_on_remote #3088

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion .github/actions/run-e2e-tests/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,15 @@ runs:

- name: Run Playwright tests
if: ${{ inputs.run-ui-tests == 'false' }}
run: LOAD_SSM_CONFIG=true HL=${{inputs.helpline-shortcode}} HL_ENV=${{inputs.environment}} npm run test
run: npm run test
working-directory: ${{ inputs.path }}/e2e-tests
shell: bash
env:
# Uncomment for more logging
# DEBUG: 'pw:api'
LOAD_SSM_CONFIG: true
HL: ${{inputs.helpline-shortcode}}
HL_ENV: ${{inputs.environment}}

- name: Run UI tests
if: ${{ inputs.run-ui-tests == 'true' }}
Expand All @@ -85,3 +91,10 @@ runs:
with:
name: test-artifacts
path: ${{ inputs.path }}/e2e-tests/test-results


- uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: test-state
path: ${{ inputs.path }}/e2e-tests/temp
2 changes: 1 addition & 1 deletion .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
env_variable_name: "TWILIO_AUTH_TOKEN"

- name: Set E2E connection details in appConfig.js
run: npm ci && npm run setAppConfigCreds -- -a ${{env.TWILIO_ACCOUNT_SID}} -l
run: npm ci && npm run setAppConfigCreds -- -a ${{env.TWILIO_ACCOUNT_SID}}
working-directory: ./scripts
shell: bash

Expand Down
20 changes: 17 additions & 3 deletions e2e-tests/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,29 @@
export const setupContextAndPage = async (browser: Browser): Promise<SetupPageReturn> => {
await waitForBrowser(browser);

console.log('Launching page');
console.info('Launching page');
const context = await browser.newContext({
storageState: getConfigValue('storageStatePath') as string,
});
const page = await context.newPage();

logPageTelemetry(page);
if (process.env.TWILIO_RUNTIME_DOMAIN) {
console.debug(
`Visiting /${process.env.TWILIO_RUNTIME_DOMAIN} to ensure future requests route to correct account`,
);
await page.goto(`/${process.env.TWILIO_RUNTIME_DOMAIN}`, { waitUntil: 'domcontentloaded' });
console.debug(
`Visited /${process.env.TWILIO_RUNTIME_DOMAIN} - waiting for logged in page element to load`,
);
} else {

Check failure on line 64 in e2e-tests/browser.ts

View workflow job for this annotation

GitHub Actions / flex-ci / lint

Delete `⏎`
console.log('Plugin page browser session launched');
await page.goto(`/`, { waitUntil: 'domcontentloaded' });
}
// There are multiple elements so we need to use waitForSelector instead of a locator/waitFor
await page.waitForSelector('h2[data-testid="side-nav-header"]', { timeout: 1200000 });

console.info('Plugin page browser session launched');
return { page, context };
};

Expand All @@ -62,6 +76,6 @@
try {
await page.close();
} catch (e) {
console.log('Error closing page' + e);
console.log('Error closing page: ' + e);
}
};
11 changes: 8 additions & 3 deletions e2e-tests/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const skipDataUpdateEnvs = ['staging', 'production'];
const flexEnvs = ['development', 'staging', 'production'];

// This is kindof a hack to get the correct default remote webchat url and twilio account info for the local env
export const localOverrideEnv = helplineEnv == 'local' ? 'development' : helplineEnv;
export const localOverrideEnv = helplineEnv === 'local' ? 'development' : helplineEnv;

export const config: Config = {};

Expand Down Expand Up @@ -152,7 +152,11 @@ const configOptions: ConfigOptions = {
},
isDevelopment: {
envKey: 'IS_DEVELOPMENT',
default: helplineEnv === 'staging',
default: helplineEnv === 'development',
},
isLocal: {
envKey: 'IS_DEVELOPMENT',
default: helplineEnv === 'local',
},

// We can skip data updates in certain environments to keep from impacting real data
Expand Down Expand Up @@ -260,9 +264,10 @@ const initSsmConfigValues = async () => {
if (!helplineShortCode) {
throw new Error('Trying to load config from SSM, but HELPLINE_SHORT_CODE is not set');
}

console.info('Setting config values from AWS SSM', Object.keys(configOptions));
// This must be done in series because some config options depend on others
for (const key of Object.keys(configOptions)) {
console.info('Setting config value from AWS SSM', key);
await setConfigValueFromSsm(key);
}
};
Expand Down
15 changes: 14 additions & 1 deletion e2e-tests/global-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/* eslint-disable import/no-extraneous-dependencies */
import { FullConfig, request } from '@playwright/test';
import { differenceInMilliseconds } from 'date-fns';
import { legacyOktaSsoLoginViaApi, oktaSsoLoginViaApi } from './okta/sso-login';
import { legacyOktaSsoLoginViaApi, oktaSsoLoginViaApi } from './okta/ssoLogin';
import { getConfigValue, initConfig } from './config';
import { getSidForWorker } from './twilio/worker';
import { clearOfflineTask } from './hrm/clearOfflineTask';
Expand Down Expand Up @@ -56,6 +56,19 @@ async function globalSetup(config: FullConfig) {
);
}
process.env.ARTIFACT_PATH = config.projects[0].outputDir;
const configResponse = await fetch(`https://flex-api.twilio.com/v1/Configuration`, {
headers: new Headers({
'Content-Type': 'application/json',
Authorization: `Basic ${Buffer.from(
`${getConfigValue('twilioAccountSid')}:${getConfigValue('twilioAuthToken')}`,
).toString('base64')}`,
}),
});
const { runtime_domain: runtimeDomain } = await configResponse.json();
process.env.TWILIO_RUNTIME_DOMAIN = getConfigValue('baseURL')?.toString().includes('localhost')
? ''
: runtimeDomain.split('.')[0];
console.info('TWILIO_RUNTIME_DOMAIN', process.env.TWILIO_RUNTIME_DOMAIN);
console.log(
'Global setup completed',
`Took ${differenceInMilliseconds(new Date(), start) / 1000} seconds`,
Expand Down
18 changes: 11 additions & 7 deletions e2e-tests/okta/sso-login.ts → e2e-tests/okta/ssoLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,12 @@ export async function oktaSsoLoginViaApi(
accountSid: string,
): Promise<string> {
const apiRequest = await request.newContext();
const configResp = await fetch(
const configResp = await apiRequest.get(
`https://services.twilio.com/v1/Flex/Authentication/Config?AccountSid=${accountSid}`,
);
if (!configResp.ok) {
if (!configResp.ok()) {
throw new Error(
`Failed to fetch auth config for ${accountSid}: [${
configResp.status
}]: ${await configResp.text()}`,
`Failed to fetch auth config for ${accountSid}: [${configResp.status()}]: ${await configResp.text()}`,
);
}
const {
Expand Down Expand Up @@ -101,7 +99,12 @@ export async function oktaSsoLoginViaApi(
// Scrape required SAML response values from the HTML response in the redirected page
// this is kinda :vomit but I couldn't see an alternative API that provides this via JSON or another API friendly format
const samlResponseHtml = await redirectResponse.text();
// commented debug lines are spammy, but handy debugging auth problems
// console.debug('SAML response HTML:', samlResponseHtml);
const { samlResponse, relayState, actionUrl } = samlResponseHtml.match(formRegex)!.groups!;
// console.debug('Extracted SAML Response', samlResponse);
// console.debug('Extracted SAML relayState', relayState);
// console.debug('Extracted SAML actionURL', actionUrl);

const flexTimeoutTime = Date.now() + 120000; // 2 minutes
// Post the SAML response to twilio - if successful this redirects to the flex landing page, whose contents we drop on the floor, we just want to ensure the cookies get set
Expand Down Expand Up @@ -153,8 +156,9 @@ export async function oktaSsoLoginViaApi(
console.error(`Looking up token failed`, await tokenLookupResponse.text());
}
expect(tokenLookupResponse.ok()).toBe(true);
const { token } = await tokenLookupResponse.json();
return token!;
const tokenLookupResponseBody = await tokenLookupResponse.json();

return tokenLookupResponseBody.token!;
}

export async function legacyOktaSsoLoginViaApi(
Expand Down
6 changes: 4 additions & 2 deletions e2e-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
"deleteChatChannels": "tsx deleteChatChannels.ts",
"test": "npx playwright test --workers 1",
"test:ui": "npx playwright test --workers 1 --config ui-tests/playwright.ui-test.config.ts",
"test:local": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true npm run test",
"test:local": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true npm run test caselist",
"test:local:debug": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true npm run test -- --headed --retries 0",
"test:development:as": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true HL_ENV=development HL=as SKIP_DATA_UPDATE=true npm run test",
"test:development:as:debug": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true HL_ENV=development HL=as SKIP_DATA_UPDATE=true npm run test -- --headed --retries 0 login",
"test:development:e2e": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true HL_ENV=development HL=e2e npm run test",
"test:development:e2e:local": "cross-env LOAD_SSM_CONFIG=true HL_ENV=development HL=e2e npm run test -- --headed",
"test:development:e2e:debug": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true HL_ENV=development HL=e2e npm run test -- --headed --retries 0 webchat",
"test:development:e2e:debug": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true HL_ENV=development HL=e2e npm run test -- --headed --debug --retries 0 login",
"test:staging:ca": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true HL_ENV=staging HL=ca npm run test",
"test:staging:ca:headed": "LOAD_SSM_CONFIG=true HL_ENV=staging HL=ca SKIP_DATA_UPDATE=true PLAYWRIGHT_BROWSER_TELEMETRY_LEVEL=none npm test -- --headed",
"test:production:ca": "cross-env DEBUG=pw:api LOAD_SSM_CONFIG=true HL_ENV=production HL=ca npm run test",
Expand Down
Loading