Create Cypress command to log in
I'll use this to test outfit saving!
This commit is contained in:
parent
9f2629ae61
commit
531ca3c22f
5 changed files with 113 additions and 22 deletions
6
cypress/integration/WardrobePage/Outfit saving.spec.js
Normal file
6
cypress/integration/WardrobePage/Outfit saving.spec.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
describe("WardrobePage: Outfit saving", () => {
|
||||
it("logs in", () => {
|
||||
cy.logInAs("dti-test");
|
||||
cy.visit("/");
|
||||
});
|
||||
});
|
|
@ -1,6 +1,12 @@
|
|||
require("dotenv").config();
|
||||
const { initPlugin } = require("cypress-plugin-snapshots/plugin");
|
||||
|
||||
module.exports = (on, config) => {
|
||||
initPlugin(on, config);
|
||||
|
||||
config.env.AUTH0_TEST_CLIENT_ID = process.env.AUTH0_TEST_CLIENT_ID;
|
||||
config.env.AUTH0_TEST_CLIENT_SECRET = process.env.AUTH0_TEST_CLIENT_SECRET;
|
||||
config.env.DTI_TEST_USER_PASSWORD = process.env.DTI_TEST_USER_PASSWORD;
|
||||
|
||||
return config;
|
||||
};
|
||||
|
|
|
@ -1 +1,42 @@
|
|||
import "cypress-plugin-snapshots/commands";
|
||||
import * as jwt from "jsonwebtoken";
|
||||
|
||||
// https://docs.cypress.io/guides/testing-strategies/auth0-authentication#Custom-Command-for-Auth0-Authentication
|
||||
// Adapted and simplified by a lot though!
|
||||
Cypress.Commands.add("logInAs", (username) => {
|
||||
if (username !== "dti-test") {
|
||||
throw new Error(`Cypress can only log in as dti-test right now`);
|
||||
}
|
||||
const password = Cypress.env("DTI_TEST_USER_PASSWORD");
|
||||
|
||||
const client_id = Cypress.env("AUTH0_TEST_CLIENT_ID");
|
||||
const client_secret = Cypress.env("AUTH0_TEST_CLIENT_SECRET");
|
||||
const audience = "https://impress-2020.openneo.net/api";
|
||||
const scope = "";
|
||||
|
||||
// TODO: This grant doesn't seem to include the custom username field. The
|
||||
// app is generally resilient to that, but yeah, it means the username
|
||||
// might not show up in the global header UI during these tests.
|
||||
cy.request({
|
||||
method: "POST",
|
||||
url: `https://openneo.us.auth0.com/oauth/token`,
|
||||
body: {
|
||||
grant_type: "password",
|
||||
username,
|
||||
password,
|
||||
audience,
|
||||
scope,
|
||||
client_id,
|
||||
client_secret,
|
||||
},
|
||||
}).then(({ body }) => {
|
||||
const decodedUser = jwt.decode(body.access_token);
|
||||
|
||||
const auth0Cypress = {
|
||||
encodedToken: body.access_token,
|
||||
decodedUser,
|
||||
};
|
||||
|
||||
window.localStorage.setItem("auth0Cypress", JSON.stringify(auth0Cypress));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,6 +3,7 @@ import { setContext } from "@apollo/client/link/context";
|
|||
import { createPersistedQueryLink } from "apollo-link-persisted-queries";
|
||||
|
||||
import cachedZones from "./cached-data/zones.json";
|
||||
import { readCypressLoginData } from "./components/useCurrentUser";
|
||||
|
||||
// Teach Apollo to load certain fields from the cache, to avoid extra network
|
||||
// requests. This happens a lot - e.g. reusing data from item search on the
|
||||
|
@ -142,8 +143,26 @@ const buildAuthLink = (getAuth0) =>
|
|||
return;
|
||||
}
|
||||
|
||||
// Wait for auth0 to stop loading, so we can maybe get a token! We'll do
|
||||
// this hackily by checking every 100ms until it's true.
|
||||
const token = await getAccessToken(getAuth0);
|
||||
if (token) {
|
||||
return {
|
||||
headers: {
|
||||
...headers,
|
||||
authorization: token ? `Bearer ${token}` : "",
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
async function getAccessToken(getAuth0) {
|
||||
// Our Cypress tests store login data separately. Use it if available!
|
||||
const cypressToken = readCypressLoginData()?.encodedToken;
|
||||
if (cypressToken) {
|
||||
return cypressToken;
|
||||
}
|
||||
|
||||
// Otherwise, wait for auth0 to stop loading, so we can maybe get a token!
|
||||
// We'll do this hackily by checking every 100ms until it's true.
|
||||
await new Promise((resolve) => {
|
||||
function check() {
|
||||
if (getAuth0().isLoading) {
|
||||
|
@ -158,14 +177,9 @@ const buildAuthLink = (getAuth0) =>
|
|||
const { isAuthenticated, getAccessTokenSilently } = getAuth0();
|
||||
if (isAuthenticated) {
|
||||
const token = await getAccessTokenSilently();
|
||||
return {
|
||||
headers: {
|
||||
...headers,
|
||||
authorization: token ? `Bearer ${token}` : "",
|
||||
},
|
||||
};
|
||||
return token;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const initialCache = {};
|
||||
for (const zone of cachedZones) {
|
||||
|
|
|
@ -24,17 +24,41 @@ function useCurrentUser() {
|
|||
};
|
||||
}
|
||||
|
||||
// Additionally, our Cypress tests do an actual end-to-end login as a test
|
||||
// user. Use that token if present!
|
||||
const cypressUser = readCypressLoginData()?.decodedUser;
|
||||
if (cypressUser) {
|
||||
return { isLoading: false, isLoggedIn: true, ...getUserInfo(cypressUser) };
|
||||
}
|
||||
|
||||
if (isLoading || !isAuthenticated) {
|
||||
return { isLoading, isLoggedIn: false, id: null, username: null };
|
||||
}
|
||||
|
||||
// NOTE: Users created correctly should have these attributes... but I'm
|
||||
// coding defensively, because third-party integrations are always a
|
||||
// bit of a thing, and I don't want failures to crash us!
|
||||
const id = user.sub?.match(/^auth0\|impress-([0-9]+)$/)?.[1];
|
||||
const username = user["https://oauth.impress-2020.openneo.net/username"];
|
||||
return { isLoading, isLoggedIn: true, ...getUserInfo(user) };
|
||||
}
|
||||
|
||||
return { isLoading, isLoggedIn: true, id, username };
|
||||
export function readCypressLoginData() {
|
||||
const cypressUserJsonString = window.localStorage.getItem("auth0Cypress");
|
||||
if (!cypressUserJsonString) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(cypressUserJsonString);
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
"Could not parse auth0Cypress token in localStorage; ignoring."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getUserInfo(user) {
|
||||
return {
|
||||
id: user.sub?.match(/^auth0\|impress-([0-9]+)$/)?.[1],
|
||||
username: user["https://oauth.impress-2020.openneo.net/username"],
|
||||
};
|
||||
}
|
||||
|
||||
export default useCurrentUser;
|
||||
|
|
Loading…
Reference in a new issue