Skip to content

Commit 824ab1a

Browse files
Adds support for E2E tests against OIE org
Addresses Aaron's comments and adds facebook login tests OKTA-384942 <<<Jenkins Check-In of Tested SHA: 542c40b for [email protected]>>> Artifact: okta-auth-js Files changed count: 10
1 parent 0d7623d commit 824ab1a

File tree

10 files changed

+172
-18
lines changed

10 files changed

+172
-18
lines changed

.bacon.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ test_suites:
2020
script_name: e2e
2121
criteria: MERGE
2222
queue_name: small
23+
- name: e2e-oie
24+
script_path: /root/okta/okta-auth-js/scripts
25+
sort_order: '3'
26+
timeout: '10'
27+
script_name: e2e-oie
28+
criteria: MERGE
29+
queue_name: small
2330
- name: publish
2431
script_path: /root/okta/okta-auth-js/scripts
2532
sort_order: '4'

scripts/e2e-oie.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash -x
2+
3+
source ${OKTA_HOME}/${REPO}/scripts/setup.sh
4+
5+
setup_service java 1.8.222
6+
setup_service google-chrome-stable 85.0.4183.102-1
7+
8+
export TEST_SUITE_TYPE="junit"
9+
export TEST_RESULT_FILE_DIR="${REPO}/build2/reports/e2e"
10+
11+
export ISSUER=https://oie-widget-tests.sigmanetcorp.us/oauth2/default
12+
13+
get_secret prod/okta-sdk-vars/password PASSWORD
14+
15+
export CI=true
16+
export DBUS_SESSION_BUS_ADDRESS=/dev/null
17+
export ORG_OIE_ENABLED=true
18+
19+
# build is required to run E2E tests
20+
if ! yarn build; then
21+
echo "build failed! Exiting..."
22+
exit ${TEST_FAILURE}
23+
fi
24+
25+
# This client has refresh token enabled
26+
export CLIENT_ID=0oa3n0cgbfiNvI6Aa0g7
27+
export REFRESH_TOKEN=true
28+
29+
30+
get_secret prod/okta-sdk-vars/fb_password FB_PASSWORD
31+
32+
if ! yarn test:e2e; then
33+
echo "OIE e2e tests failed! Exiting..."
34+
exit ${TEST_FAILURE}
35+
fi
36+
37+
echo ${TEST_SUITE_TYPE} > ${TEST_SUITE_TYPE_FILE}
38+
echo ${TEST_RESULT_FILE_DIR} > ${TEST_RESULT_FILE_DIR_FILE}
39+
exit ${PUBLISH_TYPE_AND_RESULT_DIR}

test/e2e/pageobjects/OktaHome.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ class OktaLogin {
33
get userMenu() { return $('[data-se="user-menu"] > a.link-button');}
44
get signOutBtn() { return $('[data-se="user-menu"] a[data-se="logout-link"]'); }
55
get popUpCloseButton() { return $('a[data-role="close-button"]'); }
6+
get widgetFormTitle() { return $('.okta-form-title.o-form-head'); }
67

78
async signOut() {
89
await browser.waitUntil(async () => this.userMenu.then(el => el.isDisplayed()), 5000, 'wait for user menu');
910
await this.userMenu.then(el => el.click());
1011
await browser.waitUntil(async () => this.signOutBtn.then(el => el.isDisplayed()), 5000, 'wait for signout btn');
11-
const url = await browser.getUrl();
1212
await this.signOutBtn.then(el => el.click());
13-
await browser.waitUntil(async () => browser.getUrl().then(cur => (cur !== url)), 5000, 'wait for url change');
13+
await browser.waitUntil(async () => this.widgetFormTitle.then(el => el.isDisplayed()), 5000, 'wait for widget');
1414
}
1515

1616
async waitForLoad() {

test/e2e/pageobjects/OktaLogin.js

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,58 @@ class OktaLogin {
55
get signinPassword() { return $('#okta-signin-password'); }
66
get signinSubmitBtn() { return $('#okta-signin-submit'); }
77

8+
get OIEsigninForm() { return $('form[data-se="o-form"]');}
9+
get OIEsigninUsername() { return $('[name="identifier"]'); }
10+
get OIEsigninPassword() { return $('[name="credentials.passcode"]'); }
11+
get OIEsigninSubmitBtn() { return $('[data-type="save"]'); }
12+
get facebookLoginBtn() { return $('[data-se="social-auth-facebook-button"]');}
13+
get facebookEmail() { return $('#email');}
14+
get facebookPassword() { return $('#pass');}
15+
get facebookSubmitBtn() { return $('#loginbutton');}
16+
817
async signin(username, password) {
918
await this.waitForLoad();
19+
20+
if (process.env.ORG_OIE_ENABLED) {
21+
this.signinOIE(username, password);
22+
} else {
23+
this.signinLegacy(username, password);
24+
}
25+
}
26+
27+
async signinOIE(username, password) {
28+
await this.OIEsigninUsername.then(el => el.setValue(username));
29+
await this.OIEsigninPassword.then(el => el.setValue(password));
30+
await this.OIEsigninSubmitBtn.then(el => el.click());
31+
}
32+
33+
async signinLegacy(username, password) {
1034
await this.signinUsername.then(el => el.setValue(username));
1135
await this.signinPassword.then(el => el.setValue(password));
1236
await this.signinSubmitBtn.then(el => el.click());
1337
}
1438

1539
async waitForLoad() {
16-
return browser.waitUntil(async () => this.signinSubmitBtn.then(el => el.isDisplayed()), 5000, 'wait for signin btn');
40+
if (process.env.ORG_OIE_ENABLED) {
41+
return browser.waitUntil(async () => this.OIEsigninSubmitBtn.then(el => el.isDisplayed()), 5000, 'wait for signin btn');
42+
} else {
43+
return browser.waitUntil(async () => this.signinSubmitBtn.then(el => el.isDisplayed()), 5000, 'wait for signin btn');
44+
}
45+
}
46+
47+
async signinFacebook(username, password) {
48+
await this.waitForLoad();
49+
await this.facebookLoginBtn.then(el => el.click());
50+
51+
(await this.facebookEmail).isDisplayed().then(async(displayed) => {
52+
// If a facebook session already exists, the email input won't display
53+
// it'll automatically log you in
54+
if (displayed) {
55+
await this.facebookEmail.then(el => el.setValue(username));
56+
await this.facebookPassword.then(el => el.setValue(password));
57+
await this.facebookSubmitBtn.then(el => el.click());
58+
}
59+
});
1760
}
1861
}
1962

test/e2e/pageobjects/TestApp.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class TestApp {
3939
get pkceOption() { return $('#pkce-on'); }
4040
get clientId() { return $('#clientId'); }
4141
get issuer() { return $('#issuer'); }
42+
get interactionCodeOption() { return $('#useInteractionCodeFlow-on'); }
4243

4344
// Callback
4445
get callbackSelector() { return $('#root.callback'); }

test/e2e/runner.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@ waitOn({
2020
wdioConfig = 'sauce.wdio.conf.js';
2121
}
2222

23-
if (process.env.REFRESH_TOKEN) {
24-
wdioConfig = 'tokens.wdio.conf.js';
25-
}
26-
2723
let opts = process.argv.slice(2); // pass extra arguments through
2824
const runner = spawn('./node_modules/.bin/wdio', [
2925
'run',

test/e2e/specs/interactionFlow.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe('interaction flow', () => {
1010
it('detects `interaction_required` on the redirect callback', async () => {
1111
await openPKCE({});
1212
await TestApp.loginRedirect();
13-
await OktaLogin.signin(USERNAME, PASSWORD); // on Okta
13+
await OktaLogin.signin(USERNAME, PASSWORD);
1414
await TestApp.waitForCallback();
1515

1616
// Manually change the URL. All other data should be present in browser storage

test/e2e/specs/login.js

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import assert from 'assert';
22
import TestApp from '../pageobjects/TestApp';
33
import { flows, openImplicit, openPKCE } from '../util/appUtils';
4-
import { loginWidget, loginRedirect, loginPopup, loginDirect } from '../util/loginUtils';
4+
import { loginWidget, loginRedirect, loginPopup, loginDirect, loginWidgetFacebook } from '../util/loginUtils';
55

66
describe('E2E login', () => {
77

@@ -11,6 +11,7 @@ describe('E2E login', () => {
1111
await TestApp.responseModeFragment.then(el => el.isSelected()).then(isSelected => {
1212
assert(isSelected === true);
1313
});
14+
await TestApp.interactionCodeOption.then(el => el.click());
1415
await loginRedirect('pkce', 'fragment');
1516
await TestApp.getUserInfo();
1617
await TestApp.assertUserInfo();
@@ -24,15 +25,23 @@ describe('E2E login', () => {
2425
}
2526

2627
it('can login using signin widget (no redirect)', async () => {
27-
await bootstrap();
28+
let options = {};
29+
if (process.env.ORG_OIE_ENABLED && flow === 'pkce') {
30+
options = { useInteractionCodeFlow: true };
31+
}
32+
await bootstrap(options);
2833
await loginWidget(flow);
2934
await TestApp.getUserInfo();
3035
await TestApp.assertUserInfo();
3136
await TestApp.logoutRedirect();
3237
});
3338

3439
it('can login using signin widget (with redirect)', async () => {
35-
await bootstrap({ _forceRedirect: true });
40+
let options = { _forceRedirect: true };
41+
if (process.env.ORG_OIE_ENABLED && flow === 'pkce') {
42+
options = Object.assign({ useInteractionCodeFlow: true }, options);
43+
}
44+
await bootstrap(options);
3645
await loginWidget(flow, true);
3746
await TestApp.getUserInfo();
3847
await TestApp.assertUserInfo();
@@ -62,6 +71,35 @@ describe('E2E login', () => {
6271
await TestApp.assertUserInfo();
6372
await TestApp.logoutRedirect();
6473
});
74+
75+
it('can login to social idp using signin widget (with redirect)', async () => {
76+
// Federated social auth with pinned social login buttons only works with OIE
77+
if (!process.env.ORG_OIE_ENABLED) {
78+
return;
79+
}
80+
81+
let options = { _forceRedirect: true };
82+
await bootstrap(options);
83+
await loginWidgetFacebook(flow, true);
84+
await TestApp.getUserInfo();
85+
await TestApp.assertUserInfo();
86+
await TestApp.logoutRedirect();
87+
});
88+
89+
it('can login to social idp using signin widget (no redirect)', async () => {
90+
// Federated social auth with pinned social login buttons only works with OIE
91+
if (!process.env.ORG_OIE_ENABLED) {
92+
return;
93+
}
94+
95+
let options = { useInteractionCodeFlow: true };
96+
await bootstrap(options);
97+
await loginWidgetFacebook(flow, true);
98+
await TestApp.getUserInfo();
99+
await TestApp.assertUserInfo();
100+
await TestApp.logoutRedirect();
101+
});
102+
65103
});
66104
});
67105
});

test/e2e/util/loginUtils.js

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { switchToPopupWindow, switchToLastFocusedWindow } from './browserUtils';
55

66
const USERNAME = process.env.USERNAME;
77
const PASSWORD = process.env.PASSWORD;
8+
const FB_USERNAME = process.env.FB_USERNAME;
9+
const FB_PASSWORD = process.env.FB_PASSWORD;
810

911
function assertPKCE(url, responseMode) {
1012
const char = responseMode === 'fragment' ? '#' : '?';
@@ -32,7 +34,13 @@ async function loginPopup() {
3234
const existingHandlesCount = (await browser.getWindowHandles()).length;
3335
await TestApp.loginPopup();
3436
await switchToPopupWindow(existingHandlesCount);
35-
await OktaLogin.signin(USERNAME, PASSWORD);
37+
38+
if (process.env.ORG_OIE_ENABLED) {
39+
await OktaLogin.signinOIE(USERNAME, PASSWORD);
40+
} else {
41+
await OktaLogin.signinLegacy(USERNAME, PASSWORD);
42+
}
43+
3644
await switchToLastFocusedWindow();
3745
await TestApp.assertLoggedIn();
3846
}
@@ -50,13 +58,31 @@ async function loginDirect(flow) {
5058
return handleCallback(flow);
5159
}
5260

53-
async function loginWidget(flow, forceRedirect) {
61+
async function loginWidget(flow, forceRedirect=false) {
5462
await TestApp.showLoginWidget();
55-
await OktaLogin.signin(USERNAME, PASSWORD);
63+
64+
// OIE widget is only displayed for direct auth with PKCE even with OIE enabled orgs
65+
// For direct auth implicit flow, we still use the v1 flow (since interaction code doesn't)
66+
if (flow === 'implicit' || !process.env.ORG_OIE_ENABLED) {
67+
await OktaLogin.signinLegacy(USERNAME, PASSWORD);
68+
} else {
69+
await OktaLogin.signinOIE(USERNAME, PASSWORD);
70+
}
71+
72+
if (forceRedirect) {
73+
return handleCallback(flow);
74+
}
75+
await TestApp.assertLoggedIn();
76+
}
77+
78+
async function loginWidgetFacebook(flow, forceRedirect) {
79+
await TestApp.loginRedirect();
80+
await OktaLogin.signinFacebook(FB_USERNAME, FB_PASSWORD);
81+
5682
if (forceRedirect) {
5783
return handleCallback(flow);
5884
}
5985
await TestApp.assertLoggedIn();
6086
}
6187

62-
export { loginWidget, loginDirect, loginPopup, loginRedirect };
88+
export { loginWidget, loginDirect, loginPopup, loginRedirect, loginWidgetFacebook };

test/e2e/wdio.conf.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ require('regenerator-runtime'); // Allows use of async/await
55
const DEBUG = process.env.DEBUG;
66
const CI = process.env.CI;
77
const REFRESH_TOKEN = process.env.REFRESH_TOKEN;
8+
const ORG_OIE_ENABLED = process.env.ORG_OIE_ENABLED;
89
const defaultTimeoutInterval = DEBUG ? (24 * 60 * 60 * 1000) : 10000;
910
const logLevel = CI ? 'warn' : 'info';
1011
const browserOptions = {
1112
args: []
1213
};
13-
const specs = REFRESH_TOKEN ? ['./specs/**/refreshTokens.js', './specs/**/crossTabs.js'] : ['./specs/**/*.js'];
14-
const excludeSpecs = REFRESH_TOKEN ? [] : ['./specs/**/refreshTokens.js'];
14+
15+
/* eslint-disable max-len */
16+
const specs = (REFRESH_TOKEN && !ORG_OIE_ENABLED) ? ['./specs/**/refreshTokens.js', './specs/**/crossTabs.js'] : ['./specs/**/*.js'];
17+
const excludeSpecs = (REFRESH_TOKEN || ORG_OIE_ENABLED) ? [] : ['./specs/**/refreshTokens.js'];
1518

1619
if (CI) {
1720
browserOptions.args = browserOptions.args.concat([
@@ -21,7 +24,8 @@ if (CI) {
2124
'--no-sandbox',
2225
'--whitelisted-ips',
2326
'--disable-extensions',
24-
'--verbose'
27+
'--verbose',
28+
'--disable-dev-shm-usage'
2529
]);
2630
}
2731

0 commit comments

Comments
 (0)