Files
multica/packages/core/paths/resolve.test.ts
Matt Voska 700cd97407 feat(workspace): add per-workspace logo upload (#2760)
Adds avatar_url column to workspace, threads it through the API +
WorkspaceAvatar component, and adds a click-to-upload editor in the
workspace settings tab. Mirrors the squad avatar pattern (migration 086);
UI strings use "logo" while the schema/code uses avatar_url for codebase
consistency with user.avatar_url and squad.avatar_url.

- migration 093: ALTER TABLE workspace ADD COLUMN avatar_url TEXT
- UpdateWorkspace SQL + handler accept avatar_url (auth gated to
  owner/admin at the router via RequireWorkspaceRoleFromURL)
- WorkspaceAvatar renders <img> when avatar_url is set, falls back to
  the initial-letter span otherwise
- workspace-tab.tsx adds a 16x16 click-to-upload logo editor at the
  top of the general settings card, using useFileUpload + accept=
  image/png,image/jpeg,image/webp (server stores under workspaces/{id}/)
- en + zh-Hans settings i18n strings added

Co-authored-by: Matt Voska <voska@users.noreply.github.com>
2026-06-01 16:48:05 +02:00

48 lines
1.6 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { Workspace } from "../types";
import { paths } from "./paths";
import { resolvePostAuthDestination } from "./resolve";
function makeWs(slug: string): Workspace {
return {
id: `id-${slug}`,
name: slug,
slug,
description: null,
context: null,
settings: {},
repos: [],
issue_prefix: slug.toUpperCase(),
avatar_url: null,
created_at: "",
updated_at: "",
};
}
describe("resolvePostAuthDestination", () => {
it("!onboarded → /onboarding (even with a workspace)", () => {
// V3 invariant: onboarded_at is the single source of truth for
// workspace access. A user holding workspaces but flagged !onboarded
// (rare mid-flow state: closed app between Step 2 and Step 3) gets
// routed to /onboarding so they can finish; the layout hard gate
// would redirect them anyway.
const ws = [makeWs("acme")];
expect(resolvePostAuthDestination(ws, false)).toBe(paths.onboarding());
expect(resolvePostAuthDestination([], false)).toBe(paths.onboarding());
});
it("onboarded + workspace[0] → /<first.slug>/issues", () => {
const ws = [makeWs("acme"), makeWs("beta")];
expect(resolvePostAuthDestination(ws, true)).toBe(
paths.workspace("acme").issues(),
);
});
it("onboarded + no workspace → /workspaces/new", () => {
// Already-onboarded user without any workspace — usually a returning
// user whose last workspace got deleted or who left it. They skip
// re-onboarding and go straight to workspace creation.
expect(resolvePostAuthDestination([], true)).toBe(paths.newWorkspace());
});
});