Cypress with user page test

This commit is contained in:
Kalle
2022-05-17 19:50:05 +03:00
parent f2d547fa01
commit 7d73a0478c
13 changed files with 2545 additions and 42 deletions

View File

@@ -6,10 +6,11 @@ export function Avatar({
discordAvatar,
size,
className,
...rest
}: Pick<User, "discordId" | "discordAvatar"> & {
className?: string;
size?: "lg";
}) {
} & React.ButtonHTMLAttributes<HTMLImageElement>) {
// TODO: just show text... my profile?
// TODO: also show this if discordAvatar is stale and 404's
if (!discordAvatar) return <div className="avatar" />;
@@ -25,6 +26,7 @@ export function Avatar({
alt="My avatar"
width={dimensions}
height={dimensions}
{...rest}
/>
);
}

View File

@@ -13,7 +13,15 @@ export function UserItem() {
if (user && user.discordAvatar)
return (
<Popover trigger={<Avatar {...user} />}>
<Popover
trigger={
<Avatar
data-cy="user-avatar"
discordAvatar={user.discordAvatar}
discordId={user.discordId}
/>
}
>
<div className="layout__user-popover">
{/* TODO: make the Button component transformable to Link instead of creating a wrapper */}
<Link to={userPage(user.discordId)}>
@@ -21,6 +29,7 @@ export function UserItem() {
className="w-full"
tiny
variant="outlined"
data-cy="profile-button"
icon={<UserIcon />}
>
Profile

View File

@@ -8,7 +8,10 @@ export const sessionStorage = createCookieSessionStorage({
sameSite: "lax",
path: "/",
httpOnly: true,
secrets: [process.env.SESSION_SECRET],
secrets:
process.env.NODE_ENV === "production"
? [process.env.SESSION_SECRET]
: ["secret"],
secure: process.env.NODE_ENV === "production",
},
});

View File

@@ -61,7 +61,9 @@ export default function UserPageLayout() {
return (
<>
<SubNav>
<SubNavLink to="">Profile</SubNavLink>
<SubNavLink to="" data-cy="profile-page-link">
Profile
</SubNavLink>
{isOwnPage ? (
<SubNavLink to="edit" data-cy="edit-page-link">
Edit

View File

@@ -51,6 +51,7 @@ export default function UserEditPage() {
name="country"
id="country"
defaultValue={data.country?.code ?? ""}
data-cy="country-select"
>
<option value="" />
{Object.entries(countries).map(([code, country]) => (
@@ -61,11 +62,12 @@ export default function UserEditPage() {
</select>
</div>
<Button
loadingText="Submitting..."
loadingText="Saving..."
type="submit"
loading={transition.state === "submitting"}
data-cy="submit-button"
>
Submit
Save
</Button>
</Form>
);

View File

@@ -2,7 +2,7 @@
display: flex;
flex-direction: column;
align-items: flex-start;
gap: var(--s-4);
gap: var(--s-6);
}
.u-edit__country-select {

5
cypress.json Normal file
View File

@@ -0,0 +1,5 @@
{
"baseUrl": "http://localhost:5800",
"pluginsFile": false,
"fixturesFolder": false
}

View File

@@ -0,0 +1,34 @@
export {};
describe("User page", () => {
beforeEach(() => {
cy.seed();
});
it("views profile not logged in", function () {
cy.visit("/u/79237403620945920");
cy.contains("Sendou");
cy.getCy("edit-page-link").should("not.exist");
});
it("edits own profile", function () {
cy.auth();
cy.visit("/");
cy.getCy("user-avatar").click();
cy.getCy("profile-button").click();
cy.getCy("edit-page-link").click();
cy.getCy("country-select").select("FI");
cy.getCy("submit-button").click();
cy.getCy("profile-page-link").click();
cy.contains("Sendou");
cy.contains("Finland");
// let's also check clearing select is possible
cy.getCy("edit-page-link").click();
cy.getCy("country-select").select(0);
cy.getCy("submit-button").click();
cy.getCy("profile-page-link").click();
cy.contains("Sendou");
cy.contains("Finland").should("not.exist");
});
});

27
cypress/support/index.ts Normal file
View File

@@ -0,0 +1,27 @@
export {};
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
interface Chainable {
getCy(id: string): Chainable<JQuery<HTMLElement>>;
seed(): void;
auth(): void;
}
}
}
Cypress.Commands.add("getCy", (id) => {
return cy.get(`[data-cy=${id}]`);
});
Cypress.Commands.add("seed", () => {
cy.exec("npm run seed");
});
const SENDOU_COOKIE =
"eyJvYXV0aDI6c3RhdGUiOiJhMDE0MjI5Mi03YjRiLTRkYTYtYWQxZC1jMTI5ZWExZGVhNjUiLCJ1c2VyIjp7ImlkIjoxLCJkaXNjb3JkSWQiOiI3OTIzNzQwMzYyMDk0NTkyMCIsImRpc2NvcmRBdmF0YXIiOiJmY2ZkNjVhM2JlYTU5ODkwNWFiYjljYTI1Mjk2ODE2YiJ9LCJzdHJhdGVneSI6ImRpc2NvcmQifQ%3D%3D.yf5YER%2B15VPqVk6Kys2jnpPAQqbq2Yv%2FF50lmGAIilc";
Cypress.Commands.add("auth", () => {
cy.setCookie("_session", SENDOU_COOKIE);
});

2442
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,12 +9,14 @@
"start": "remix-serve build",
"migrate": "node ./migrations/index.mjs",
"migrate:reset": "node scripts/delete-db-files.mjs && npm run migrate",
"seed": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/seed.ts",
"lint:ts": "eslint . --ext .ts,.tsx",
"lint:styles": "stylelint \"app/styles/**/*.css\"",
"lf": "npm run lint:styles -- --fix && npm run lint:ts -- --fix && npm run prettier:write",
"prettier:check": "prettier --check .",
"prettier:write": "prettier --write .",
"typecheck": "tsc --noEmit",
"cy:open": "cypress open",
"checks": "npm run lint:styles && npm run lint:ts && npm run prettier:check && npm run typecheck"
},
"dependencies": {
@@ -44,6 +46,7 @@
"@types/react-dom": "^17.0.9",
"@typescript-eslint/eslint-plugin": "^5.23.0",
"@typescript-eslint/parser": "^5.23.0",
"cypress": "^9.6.1",
"eslint": "^8.15.0",
"eslint-plugin-react": "^7.29.4",
"eslint-plugin-react-hooks": "^4.5.0",
@@ -53,6 +56,8 @@
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-standard": "^25.0.0",
"stylelint-order": "^5.0.0",
"ts-node": "^10.7.0",
"tsconfig-paths": "^4.0.0",
"typescript": "^4.5.5"
},
"engines": {

41
scripts/seed.ts Normal file
View File

@@ -0,0 +1,41 @@
import { db } from "~/db";
import { sql } from "~/db/sql";
const ADMIN_TEST_DISCORD_ID = "79237403620945920";
const ADMIN_TEST_AVATAR = "fcfd65a3bea598905abb9ca25296816b";
function adminUser() {
db.users.upsert({
discordDiscriminator: "4059",
discordId: ADMIN_TEST_DISCORD_ID,
discordName: "Sendou",
twitch: "Sendou",
youtubeId: "UCWbJLXByvsfQvTcR4HLPs5Q",
discordAvatar: ADMIN_TEST_AVATAR,
twitter: "sendouc",
});
}
function wipeDB() {
const tablesToDelete = ["User"];
for (const table of tablesToDelete) {
sql.prepare(`delete from "${table}"`).run();
}
}
const basicSeeds = [adminUser];
export function seed() {
wipeDB();
// eslint-disable-next-line no-console
console.log("database wiped...");
for (const seedFunc of basicSeeds) {
seedFunc();
}
// eslint-disable-next-line no-console
console.log("seeded!");
}
seed();

View File

@@ -2,6 +2,7 @@
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2019"],
"types": ["cypress"],
"isolatedModules": true,
"esModuleInterop": true,
"jsx": "react-jsx",