Skip to content
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

Convert Auth0 tests to use experimentalSessionAndOrigin #1270

Merged
merged 6 commits into from
Nov 28, 2022
Merged
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
3 changes: 0 additions & 3 deletions .env
Original file line number Diff line number Diff line change
@@ -20,13 +20,10 @@ REACT_APP_BACKEND_PORT=3001
# Auth0 Configuration to be added to .env when running "yarn dev:auth0"
#AUTH0_USERNAME="username@domain.com"
#AUTH0_PASSWORD="s3cret1234$"
#AUTH0_CLIENT_SECRET="your-auth0-client-secret"
#REACT_APP_AUTH0_DOMAIN="your-auth0-domain.auth0.com"
#REACT_APP_AUTH0_CLIENTID="1234567890"
#REACT_APP_AUTH0_AUDIENCE="https://your-auth0-domain.auth0.com/api/v2/"
#REACT_APP_AUTH0_SCOPE="openid email profile"
#AUTH0_MGMT_API_TOKEN="YOUR-MANAGEMENT-API-TOKEN"


# Okta Configuration to be added to .env when running "yarn dev:okta"
#OKTA_USERNAME="username@domain.com"
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -175,13 +175,13 @@ Support for 3rd party authentication is available in the application to demonstr

### Auth0

A [guide has been written with detail around adapting the RWA](http://on.cypress.io/auth0) to use [Auth0][auth0] and to explain the programmatic command used for Cypress tests.
The [Auth0](https://auth0.com/) tests have been rewritten to take advantage of our (currently experimental) [`cy.session`](https://docs.cypress.io/api/commands/session) and [`cy.origin`](https://docs.cypress.io/api/commands/origin) commands.

Prerequisites include an Auth0 account and a Tenant configured for use with a SPA. Environment variables from Auth0 are to be placed in the [.env](./.env).
Prerequisites include an Auth0 account and a Tenant configured for use with a SPA. Environment variables from Auth0 are to be placed in the [.env](./.env). For more details see [Auth0 Application Setup](http://on.cypress.io/auth0#Auth0-Application-Setup) and [Setting Auth0 app credentials in Cypress](http://on.cypress.io/auth0#Setting-Auth0-app-credentials-in-Cypress).

Start the application with `yarn dev:auth0` and run Cypress with `yarn cypress:open`.

The only passing spec on this branch will be the [auth0 spec](./cypress/tests/ui-auth-providers/auth0.spec.ts); all others will fail.
The only passing spec on this branch will be the [auth0 spec](./cypress/tests/ui-auth-providers/auth0.spec.ts); all others will fail. Please note that your test user will need to authorize your Auth0 app before the tests will pass.

### Okta

6 changes: 1 addition & 5 deletions cypress.config.js
Original file line number Diff line number Diff line change
@@ -31,11 +31,6 @@ module.exports = defineConfig({
auth0_username: process.env.AUTH0_USERNAME,
auth0_password: process.env.AUTH0_PASSWORD,
auth0_domain: process.env.REACT_APP_AUTH0_DOMAIN,
auth0_audience: process.env.REACT_APP_AUTH0_AUDIENCE,
auth0_scope: process.env.REACT_APP_AUTH0_SCOPE,
auth0_client_id: process.env.REACT_APP_AUTH0_CLIENTID,
auth0_client_secret: process.env.AUTH0_CLIENT_SECRET,
auth_token_name: process.env.REACT_APP_AUTH_TOKEN_NAME,

// Okta
okta_username: process.env.OKTA_USERNAME,
@@ -68,6 +63,7 @@ module.exports = defineConfig({
supportFile: "cypress/support/e2e.ts",
viewportHeight: 1000,
viewportWidth: 1280,
experimentalSessionAndOrigin: !!process.env.REACT_APP_AUTH0_CLIENTID,
setupNodeEvents(on, config) {
const testDataApiEndpoint = `${config.env.apiUrl}/testData`;

4 changes: 2 additions & 2 deletions cypress/global.d.ts
Original file line number Diff line number Diff line change
@@ -126,9 +126,9 @@ declare namespace Cypress {
logoutByXstate(): Chainable<string>;

/**
* Logs in via Auth0 API
* Logs in via Auth0 login page
*/
loginByAuth0Api(username: string, password?: string): Chainable<any>;
loginToAuth0(username: string, password: string): Chainable<any>;

/**
* Switch current user by logging out current user and logging as user with specified username
65 changes: 27 additions & 38 deletions cypress/support/auth-provider-commands/auth0.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,42 @@
// @ts-check
///<reference path="../../global.d.ts" />

import * as jwt from "jsonwebtoken";

Cypress.Commands.add("loginByAuth0Api", (username: string, password?: string) => {
// Note: this function leaves you on a blank page, so you must call cy.visit()
// afterwards, before continuing with your test.
Cypress.Commands.add("loginToAuth0", (username: string, password: string) => {
const log = Cypress.log({
displayName: "AUTH0 LOGIN",
message: [`🔐 Authenticating | ${username}`],
// @ts-ignore
autoEnd: false,
});

const client_id = Cypress.env("auth0_client_id");
const client_secret = Cypress.env("auth0_client_secret");
const audience = Cypress.env("auth0_audience");
const scope = Cypress.env("auth0_scope");

log.snapshot("before");

cy.request({
method: "POST",
url: `https://${Cypress.env("auth0_domain")}/oauth/token`,
body: {
grant_type: "password",
username,
password,
audience,
scope,
client_id,
client_secret,
const args = { username, password };
cy.session(
args,
() => {
// App landing page redirects to Auth0.
cy.visit("/");

// Login on Auth0.
cy.origin(Cypress.env("auth0_domain"), { args }, ({ username, password }) => {
cy.get("input#username").type(username);
cy.get("input#password").type(password);
cy.contains("button[value=default]", "Continue").click();
});

// Ensure Auth0 has redirected us back to the RWA.
cy.url().should("equal", "http://localhost:3000/");
},
}).then(({ body }) => {
const user: any = jwt.decode(body.id_token);

const userItem = {
token: body.access_token,
user: {
sub: user.sub,
nickname: user.nickname,
picture: user.name,
email: user.email,
{
validate: () => {
// Validate presence of access token in localStorage.
cy.wrap(localStorage).invoke("getItem", "authAccessToken").should("exist");
},
};

window.localStorage.setItem("auth0Cypress", JSON.stringify(userItem));

log.snapshot("after");
log.end();
});
}
);

cy.visit("/");
log.snapshot("after");
log.end();
});
11 changes: 5 additions & 6 deletions cypress/tests/ui-auth-providers/auth0.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { isMobile } from "../../support/utils";

if (Cypress.env("auth0_client_id")) {
if (Cypress.env("auth0_username")) {
describe("Auth0", function () {
beforeEach(function () {
cy.task("db:seed");

cy.intercept("POST", "/graphql").as("createBankAccount");

cy.loginByAuth0Api(Cypress.env("auth0_username"), Cypress.env("auth0_password"));
cy.loginToAuth0(Cypress.env("auth0_username"), Cypress.env("auth0_password"));
cy.visit("/");
});

it("should allow a visitor to login, onboard and logout", function () {
@@ -24,8 +23,6 @@ if (Cypress.env("auth0_client_id")) {
cy.getBySelLike("routingNumber-input").type("987654321");
cy.getBySelLike("submit").click();

cy.wait("@createBankAccount");

cy.getBySel("user-onboarding-dialog-title").should("contain", "Finished");
cy.getBySel("user-onboarding-dialog-content").should("contain", "You're all set!");
cy.getBySel("user-onboarding-next").click();
@@ -41,6 +38,8 @@ if (Cypress.env("auth0_client_id")) {
cy.location("pathname").should("eq", "/");
});

// This test should pass without needing to go through the login flow again,
// due to the session data being cached by cy.loginToAuth0.
it("shows onboarding", function () {
cy.contains("Get Started").should("be.visible");
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -92,7 +92,7 @@
"concurrently": "7.1.0",
"cors": "2.8.5",
"cross-env": "7.0.3",
"cypress": "^10.7.0",
"cypress": "^11.2.0",
"dotenv": "16.0.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-cypress": "2.12.1",
29 changes: 8 additions & 21 deletions src/containers/AppAuth0.tsx
Original file line number Diff line number Diff line change
@@ -36,25 +36,13 @@ const AppAuth0: React.FC = () => {

const [, , bankAccountsService] = useMachine(bankAccountsMachine);

// @ts-ignore
if (window.Cypress) {
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
const auth0 = JSON.parse(localStorage.getItem("auth0Cypress")!);
authService.send("AUTH0", {
user: auth0.user,
token: auth0.token,
});
}, []);
} else {
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
(async function waitForToken() {
const token = await getAccessTokenSilently();
authService.send("AUTH0", { user, token });
})();
}, [isAuthenticated, user, getAccessTokenSilently]);
}
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
(async function waitForToken() {
const token = await getAccessTokenSilently();
authService.send("AUTH0", { user, token });
debrisapron marked this conversation as resolved.
Show resolved Hide resolved
})();
}, [isAuthenticated, user, getAccessTokenSilently]);

const isLoggedIn =
authState.matches("authorized") ||
@@ -80,6 +68,5 @@ const AppAuth0: React.FC = () => {
);
};

//@ts-ignore
let appAuth0 = window.Cypress ? AppAuth0 : withAuthenticationRequired(AppAuth0);
const appAuth0 = withAuthenticationRequired(AppAuth0);
export default appAuth0;
8 changes: 1 addition & 7 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -18,11 +18,5 @@
"noFallthroughCasesInSwitch": true,
"types": ["cypress"]
},
"include": [
"src/**/*.cy.{js,ts,jsx,tsx}",
"scripts",
"backend",
"src/__tests__",
"cypress/support/component.ts"
]
"include": ["src/**/*.cy.{js,ts,jsx,tsx}", "scripts", "backend", "src/__tests__"]
}
18 changes: 9 additions & 9 deletions yarn.lock
Original file line number Diff line number Diff line change
@@ -7456,10 +7456,10 @@ cyclist@^1.0.1:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=

cypress@^10.7.0:
version "10.7.0"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-10.7.0.tgz#2d37f8b9751c6de33ee48639cb7e67a2ce593231"
integrity sha512-gTFvjrUoBnqPPOu9Vl5SBHuFlzx/Wxg/ZXIz2H4lzoOLFelKeF7mbwYUOzgzgF0oieU2WhJAestQdkgwJMMTvQ==
cypress@^11.2.0:
version "11.2.0"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-11.2.0.tgz#63edef8c387b687066c5493f6f0ad7b9ced4b2b7"
integrity sha512-u61UGwtu7lpsNWLUma/FKNOsrjcI6wleNmda/TyKHe0dOBcVjbCPlp1N6uwFZ0doXev7f/91YDpU9bqDCFeBLA==
dependencies:
"@cypress/request" "^2.88.10"
"@cypress/xvfb" "^1.2.4"
@@ -7480,7 +7480,7 @@ cypress@^10.7.0:
dayjs "^1.10.4"
debug "^4.3.2"
enquirer "^2.3.6"
eventemitter2 "^6.4.3"
eventemitter2 "6.4.7"
execa "4.1.0"
executable "^4.1.1"
extract-zip "2.0.1"
@@ -8568,10 +8568,10 @@ event-stream@=3.3.4:
stream-combiner "~0.0.4"
through "~2.3.1"

eventemitter2@^6.4.3:
version "6.4.4"
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.4.tgz#aa96e8275c4dbeb017a5d0e03780c65612a1202b"
integrity sha512-HLU3NDY6wARrLCEwyGKRBvuWYyvW6mHYv72SJJAH3iJN3a6eVUvkjFkcxah1bcTgGVBBrFdIopBJPhCQFMLyXw==
eventemitter2@6.4.7:
version "6.4.7"
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d"
integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==

eventemitter3@^4.0.0:
version "4.0.7"