Fix recorder finalize path and add invite-gated login
这个提交包含在:
@@ -1,8 +1,10 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { appRouter } from "./routers";
|
||||
import { COOKIE_NAME } from "../shared/const";
|
||||
import type { TrpcContext } from "./_core/context";
|
||||
import * as db from "./db";
|
||||
import { ENV } from "./_core/env";
|
||||
import { sdk } from "./_core/sdk";
|
||||
|
||||
type AuthenticatedUser = NonNullable<TrpcContext["user"]>;
|
||||
|
||||
@@ -114,6 +116,68 @@ describe("auth.loginWithUsername input validation", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("auth.loginWithUsername invite flow", () => {
|
||||
const originalInviteCode = ENV.registrationInviteCode;
|
||||
|
||||
beforeEach(() => {
|
||||
ENV.registrationInviteCode = "CA2026";
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
ENV.registrationInviteCode = originalInviteCode;
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("allows existing users to log in without an invite code", async () => {
|
||||
const existingUser = createTestUser({ name: "ExistingPlayer", openId: "existing-1" });
|
||||
const { ctx, setCookies } = createMockContext(null);
|
||||
const caller = appRouter.createCaller(ctx);
|
||||
|
||||
vi.spyOn(db, "getUserByUsername").mockResolvedValueOnce(existingUser);
|
||||
const createUsernameAccountSpy = vi.spyOn(db, "createUsernameAccount").mockResolvedValueOnce({
|
||||
user: existingUser,
|
||||
isNew: false,
|
||||
});
|
||||
vi.spyOn(sdk, "createSessionToken").mockResolvedValueOnce("session-token");
|
||||
|
||||
const result = await caller.auth.loginWithUsername({ username: "ExistingPlayer" });
|
||||
|
||||
expect(result.isNew).toBe(false);
|
||||
expect(createUsernameAccountSpy).toHaveBeenCalledWith("ExistingPlayer", undefined);
|
||||
expect(setCookies[0]?.name).toBe(COOKIE_NAME);
|
||||
});
|
||||
|
||||
it("rejects new users without the correct invite code", async () => {
|
||||
const { ctx } = createMockContext(null);
|
||||
const caller = appRouter.createCaller(ctx);
|
||||
|
||||
vi.spyOn(db, "getUserByUsername").mockResolvedValueOnce(undefined);
|
||||
const createUsernameAccountSpy = vi.spyOn(db, "createUsernameAccount");
|
||||
|
||||
await expect(caller.auth.loginWithUsername({ username: "NewPlayer" })).rejects.toThrow("新用户注册需要正确的邀请码");
|
||||
expect(createUsernameAccountSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("allows new users with the correct invite code", async () => {
|
||||
const newUser = createTestUser({ name: "NewPlayer", openId: "new-1" });
|
||||
const { ctx, setCookies } = createMockContext(null);
|
||||
const caller = appRouter.createCaller(ctx);
|
||||
|
||||
vi.spyOn(db, "getUserByUsername").mockResolvedValueOnce(undefined);
|
||||
const createUsernameAccountSpy = vi.spyOn(db, "createUsernameAccount").mockResolvedValueOnce({
|
||||
user: newUser,
|
||||
isNew: true,
|
||||
});
|
||||
vi.spyOn(sdk, "createSessionToken").mockResolvedValueOnce("session-token");
|
||||
|
||||
const result = await caller.auth.loginWithUsername({ username: "NewPlayer", inviteCode: "CA2026" });
|
||||
|
||||
expect(result.isNew).toBe(true);
|
||||
expect(createUsernameAccountSpy).toHaveBeenCalledWith("NewPlayer", "CA2026");
|
||||
expect(setCookies[0]?.name).toBe(COOKIE_NAME);
|
||||
});
|
||||
});
|
||||
|
||||
// ===== PROFILE TESTS =====
|
||||
|
||||
describe("profile.stats", () => {
|
||||
|
||||
在新工单中引用
屏蔽一个用户