mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-10-01 07:37:55 -05:00
@@ -311,10 +311,7 @@ export async function update({
|
||||
bio,
|
||||
bsky,
|
||||
tag,
|
||||
customTheme,
|
||||
}: Pick<Insertable<Tables["Team"]>, "id" | "name" | "bio" | "bsky" | "tag"> & {
|
||||
customTheme: CustomTheme | null;
|
||||
}) {
|
||||
}: Pick<Insertable<Tables["Team"]>, "id" | "name" | "bio" | "bsky" | "tag">) {
|
||||
const customUrl = mySlugify(name);
|
||||
|
||||
const team = await db
|
||||
@@ -325,7 +322,6 @@ export async function update({
|
||||
bio,
|
||||
bsky,
|
||||
tag,
|
||||
customTheme: customTheme ? JSON.stringify(customTheme) : null,
|
||||
})
|
||||
.where("id", "=", id)
|
||||
.returningAll()
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { REGULAR_USER_TEST_ID } from "~/db/seed/constants";
|
||||
import { db } from "~/db/sql";
|
||||
import * as TeamRepository from "~/features/team/TeamRepository.server";
|
||||
import { clampThemeToGamut } from "~/utils/oklch-gamut";
|
||||
import {
|
||||
assertResponseErrored,
|
||||
dbInsertUsers,
|
||||
@@ -20,7 +24,7 @@ const editTeamProfileAction = wrappedAction<typeof editTeamSchema>({
|
||||
isJsonSubmission: true,
|
||||
});
|
||||
|
||||
const DEFAULT_FIELDS = {
|
||||
const DEFAULT_EDIT_FIELDS = {
|
||||
_action: "EDIT",
|
||||
name: "Team 1",
|
||||
bio: "",
|
||||
@@ -28,6 +32,31 @@ const DEFAULT_FIELDS = {
|
||||
tag: "",
|
||||
} as const;
|
||||
|
||||
const VALID_CUSTOM_THEME = {
|
||||
baseHue: 180,
|
||||
baseChroma: 0.05,
|
||||
accentHue: 200,
|
||||
accentChroma: 0.1,
|
||||
chatHue: null,
|
||||
radiusBox: 3,
|
||||
radiusField: 2,
|
||||
radiusSelector: 2,
|
||||
borderWidth: 2,
|
||||
sizeField: 1,
|
||||
sizeSelector: 1,
|
||||
sizeSpacing: 1,
|
||||
} as const;
|
||||
|
||||
const expectedStoredTheme = () =>
|
||||
JSON.parse(JSON.stringify(clampThemeToGamut(VALID_CUSTOM_THEME)));
|
||||
|
||||
const makeUserPatron = () =>
|
||||
db
|
||||
.updateTable("User")
|
||||
.set({ patronTier: 2 })
|
||||
.where("id", "=", REGULAR_USER_TEST_ID)
|
||||
.execute();
|
||||
|
||||
describe("team page editing", () => {
|
||||
beforeEach(async () => {
|
||||
await dbInsertUsers();
|
||||
@@ -37,65 +66,85 @@ describe("team page editing", () => {
|
||||
dbReset();
|
||||
});
|
||||
|
||||
it("adds valid custom theme", async () => {
|
||||
it("sets a custom theme via UPDATE_CUSTOM_THEME", async () => {
|
||||
await makeUserPatron();
|
||||
|
||||
const response = await editTeamProfileAction(
|
||||
{
|
||||
customTheme: {
|
||||
baseHue: 180,
|
||||
baseChroma: 0.05,
|
||||
accentHue: 200,
|
||||
accentChroma: 0.1,
|
||||
chatHue: null,
|
||||
radiusBox: 3,
|
||||
radiusField: 2,
|
||||
radiusSelector: 2,
|
||||
borderWidth: 2,
|
||||
sizeField: 1,
|
||||
sizeSelector: 1,
|
||||
sizeSpacing: 1,
|
||||
},
|
||||
...DEFAULT_FIELDS,
|
||||
_action: "UPDATE_CUSTOM_THEME",
|
||||
newValue: VALID_CUSTOM_THEME,
|
||||
},
|
||||
{ user: "regular", params: { customUrl: "team-1" } },
|
||||
);
|
||||
|
||||
expect(response.status).toBe(302);
|
||||
expect(response).toEqual({ ok: true });
|
||||
|
||||
const team = await TeamRepository.findByCustomUrl("team-1");
|
||||
expect(team?.customTheme).toEqual(expectedStoredTheme());
|
||||
});
|
||||
|
||||
it("allows null custom theme", async () => {
|
||||
const response = await editTeamProfileAction(
|
||||
it("clears a custom theme via UPDATE_CUSTOM_THEME with null", async () => {
|
||||
await makeUserPatron();
|
||||
|
||||
await editTeamProfileAction(
|
||||
{
|
||||
customTheme: null,
|
||||
...DEFAULT_FIELDS,
|
||||
_action: "UPDATE_CUSTOM_THEME",
|
||||
newValue: VALID_CUSTOM_THEME,
|
||||
},
|
||||
{ user: "regular", params: { customUrl: "team-1" } },
|
||||
);
|
||||
|
||||
expect(response.status).toBe(302);
|
||||
});
|
||||
|
||||
it("prevents adding custom theme with invalid values", async () => {
|
||||
const response = await editTeamProfileAction(
|
||||
{
|
||||
customTheme: {
|
||||
_action: "UPDATE_CUSTOM_THEME",
|
||||
newValue: null,
|
||||
},
|
||||
{ user: "regular", params: { customUrl: "team-1" } },
|
||||
);
|
||||
|
||||
expect(response).toEqual({ ok: true });
|
||||
|
||||
const team = await TeamRepository.findByCustomUrl("team-1");
|
||||
expect(team?.customTheme).toBeNull();
|
||||
});
|
||||
|
||||
it("prevents setting an invalid custom theme", async () => {
|
||||
await makeUserPatron();
|
||||
|
||||
const response = await editTeamProfileAction(
|
||||
{
|
||||
_action: "UPDATE_CUSTOM_THEME",
|
||||
newValue: {
|
||||
...VALID_CUSTOM_THEME,
|
||||
baseHue: 500, // Invalid: max is 360
|
||||
baseChroma: 0.05,
|
||||
accentHue: 200,
|
||||
accentChroma: 0.1,
|
||||
chatHue: null,
|
||||
radiusBox: 3,
|
||||
radiusField: 2,
|
||||
radiusSelector: 2,
|
||||
borderWidth: 2,
|
||||
sizeField: 1,
|
||||
sizeSelector: 1,
|
||||
sizeSpacing: 1,
|
||||
},
|
||||
...DEFAULT_FIELDS,
|
||||
},
|
||||
{ user: "regular", params: { customUrl: "team-1" } },
|
||||
);
|
||||
|
||||
assertResponseErrored(response);
|
||||
});
|
||||
|
||||
it("preserves an existing custom theme when editing the team profile", async () => {
|
||||
await makeUserPatron();
|
||||
|
||||
await editTeamProfileAction(
|
||||
{
|
||||
_action: "UPDATE_CUSTOM_THEME",
|
||||
newValue: VALID_CUSTOM_THEME,
|
||||
},
|
||||
{ user: "regular", params: { customUrl: "team-1" } },
|
||||
);
|
||||
|
||||
const response = await editTeamProfileAction(
|
||||
{ ...DEFAULT_EDIT_FIELDS, bio: "Updated bio" },
|
||||
{ user: "regular", params: { customUrl: "team-1" } },
|
||||
);
|
||||
|
||||
expect(response.status).toBe(302);
|
||||
|
||||
const team = await TeamRepository.findByCustomUrl("team-1");
|
||||
expect(team?.customTheme).toEqual(expectedStoredTheme());
|
||||
expect(team?.bio).toBe("Updated bio");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -87,15 +87,9 @@ export const action: ActionFunction = async ({ request, params }) => {
|
||||
return { errors: ["forms:errors.duplicateName"] };
|
||||
}
|
||||
|
||||
const customTheme =
|
||||
canAddCustomizedColors(team) && data.customTheme
|
||||
? clampThemeToGamut(data.customTheme)
|
||||
: null;
|
||||
|
||||
const updatedTeam = await TeamRepository.update({
|
||||
id: team.id,
|
||||
...data,
|
||||
customTheme,
|
||||
});
|
||||
|
||||
throw redirect(teamPage(updatedTeam.customUrl));
|
||||
|
||||
@@ -61,10 +61,6 @@ export const editTeamSchema = z.union([
|
||||
falsyToNull,
|
||||
z.string().max(TEAM.TAG_MAX_LENGTH).nullable(),
|
||||
),
|
||||
customTheme: z.preprocess(
|
||||
(val) => (!val || val === "null" ? null : val),
|
||||
themeInputSchema.nullable(),
|
||||
),
|
||||
}),
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user