mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-10-01 23:58:36 -05:00
Cypress with user page test
This commit is contained in:
@@ -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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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
5
cypress.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"baseUrl": "http://localhost:5800",
|
||||
"pluginsFile": false,
|
||||
"fixturesFolder": false
|
||||
}
|
||||
34
cypress/integration/user-page.spec.ts
Normal file
34
cypress/integration/user-page.spec.ts
Normal 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
27
cypress/support/index.ts
Normal 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
2442
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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
41
scripts/seed.ts
Normal 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();
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user