sendou.ink/app/utils/Test.ts
Kalle b4cc185d1d
Some checks are pending
Tests and checks on push / run-checks-and-tests (push) Waiting to run
Updates translation progress / update-translation-progress-issue (push) Waiting to run
Scrims (#2211)
* Initial

* Progress

* Initial UI

* Can submit request

* Progress

* Show text if no scrims

* Can cancel request, tabs

* Delete post

* Popover if can't delete

* Request rows

* Progress

* Scrim page initial

* Fix migration order

* Progress

* Progress

* Works again

* Make it compile

* Make it compile again

* Work

* Progress

* Progress

* Progress

* Associations initial

* Association visibility work

* notFoundVisibility form fields initial

* Progress

* Association leave/join + reset invite code

* Progress

* Select test

* Merge branch 'rewrite' into scrims

* Remeda for groupBy

* Select with search

* Outline styling for select

* Select done?

* Fix prop names

* Paginated badges

* Less important

* Select no results

* Handle limiting select width

* UserSearch non-working

* Fix problem from merge

* Remove UserSearch for now

* Remove todo

* Flaggable

* Remove TODOs

* i18n start + styling

* Progress

* i18n done

* Add association e2e test

* E2E tests

* Done?

* Couple leftovers
2025-04-20 22:51:23 +03:00

134 lines
3.2 KiB
TypeScript

import type { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/node";
import type { Params } from "@remix-run/react";
import { expect } from "vitest";
import type { z } from "zod";
import { ADMIN_ID } from "~/constants";
import { REGULAR_USER_TEST_ID } from "~/db/seed/constants";
import { db, sql } from "~/db/sql";
import { SESSION_KEY } from "~/features/auth/core/authenticator.server";
import { authSessionStorage } from "~/features/auth/core/session.server";
export function arrayContainsSameItems<T>(arr1: T[], arr2: T[]) {
return (
arr1.length === arr2.length && arr1.every((item) => arr2.includes(item))
);
}
export function wrappedAction<T extends z.ZodTypeAny>({
action,
}: {
// TODO: strongly type this
action: (args: ActionFunctionArgs) => any;
}) {
return async (
args: z.infer<T>,
{
user,
params = {},
}: { user?: "admin" | "regular"; params?: Params<string> } = {},
) => {
const body = new URLSearchParams(args);
const request = new Request("http://app.com/path", {
method: "POST",
body,
headers: await authHeader(user),
});
try {
const response = await action({
request,
context: {},
params,
});
return response;
} catch (thrown) {
if (thrown instanceof Response) {
// it was a redirect
if (thrown.status === 302) return thrown;
throw new Error(`Response thrown with status code: ${thrown.status}`);
}
throw thrown;
}
};
}
export function wrappedLoader<T>({
loader,
}: {
// TODO: strongly type this
loader: (args: LoaderFunctionArgs) => any;
}) {
return async ({
user,
params = {},
}: { user?: "admin" | "regular"; params?: Params<string> } = {}) => {
const request = new Request("http://app.com/path", {
method: "GET",
headers: await authHeader(user),
});
try {
const data = await loader({
request,
params,
context: {},
});
return data as T;
} catch (thrown) {
if (thrown instanceof Response) {
throw new Error(`Response thrown with status code: ${thrown.status}`);
}
throw thrown;
}
};
}
/**
* Asserts that the given response errored out (with a toast message, via `errorToastIfFalsy(cond)` call)
*/
export function assertResponseErrored(response: Response) {
expect(response.headers.get("Location")).toContain("?__error=");
}
async function authHeader(user?: "admin" | "regular"): Promise<HeadersInit> {
if (!user) return [];
const session = await authSessionStorage.getSession();
session.set(SESSION_KEY, user === "admin" ? ADMIN_ID : REGULAR_USER_TEST_ID);
return [["Cookie", await authSessionStorage.commitSession(session)]];
}
export const dbReset = () => {
const tables = sql
.prepare(
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE 'migrations';",
)
.all() as { name: string }[];
sql.prepare("PRAGMA foreign_keys = OFF").run();
for (const table of tables) {
sql.prepare(`DELETE FROM "${table.name}"`).run();
}
sql.prepare("PRAGMA foreign_keys = ON").run();
};
export const dbInsertUsers = (count?: number) =>
db
.insertInto("User")
.values(
// defaults to 2 = admin & regular "NZAP"
Array.from({ length: count ?? 2 }).map((_, i) => ({
id: i + 1,
discordName: `user${i + 1}`,
discordId: String(i),
})),
)
.execute();