test(chat-machine): add test for ignoring repeated user login during active session
This commit is contained in:
@@ -164,6 +164,30 @@ describe("chatMachine transitions", () => {
|
|||||||
actor.stop();
|
actor.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("ignores repeated user login while an authenticated user session is active", async () => {
|
||||||
|
const actor = createActor(createTestChatMachine()).start();
|
||||||
|
|
||||||
|
actor.send({ type: "ChatUserLogin", token: "token" });
|
||||||
|
await waitFor(actor, (snapshot) =>
|
||||||
|
snapshot.matches({ userSession: "ready" }),
|
||||||
|
);
|
||||||
|
|
||||||
|
actor.send({ type: "ChatSendMessage", content: "keep this message" });
|
||||||
|
await waitFor(
|
||||||
|
actor,
|
||||||
|
(snapshot) => snapshot.context.messages.length === 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
actor.send({ type: "ChatUserLogin", token: "another-token" });
|
||||||
|
|
||||||
|
expect(actor.getSnapshot().matches({ userSession: "ready" })).toBe(true);
|
||||||
|
expect(actor.getSnapshot().context.messages).toMatchObject([
|
||||||
|
{ content: "keep this message", isFromAI: false },
|
||||||
|
]);
|
||||||
|
|
||||||
|
actor.stop();
|
||||||
|
});
|
||||||
|
|
||||||
it("allows multiple messages to be queued without leaving ready state", async () => {
|
it("allows multiple messages to be queued without leaving ready state", async () => {
|
||||||
const actor = createActor(createTestChatMachine()).start();
|
const actor = createActor(createTestChatMachine()).start();
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import { usePathname, useRouter } from "next/navigation";
|
import { usePathname, useRouter } from "next/navigation";
|
||||||
|
|
||||||
import { AuthStorage } from "@/data/storage/auth/auth_storage";
|
import { AuthStorage } from "@/data/storage/auth";
|
||||||
import { useAuthState } from "@/stores/auth/auth-context";
|
import { useAuthState } from "@/stores/auth/auth-context";
|
||||||
import { PROTECTED_ROUTES, ROUTES, type StaticRoute } from "@/router/routes";
|
import { PROTECTED_ROUTES, ROUTES, type StaticRoute } from "@/router/routes";
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* Chat 状态机(XState v5)
|
* Chat 状态机(XState v5)
|
||||||
*
|
*
|
||||||
* 鉴权解耦(事件驱动):
|
|
||||||
* chat 机器不感知鉴权 —— 由 <ChatAuthSync /> 派生 loginStatus
|
|
||||||
* ChatAuthSync 派发登录态生命周期事件:
|
|
||||||
* - `ChatGuestLogin` → 游客会话
|
|
||||||
* - `ChatUserLogin { token }` → 其他登录用户会话
|
|
||||||
* - `ChatLogout` → 正式登录用户登出
|
|
||||||
*
|
|
||||||
* 登录态流转约束:
|
* 登录态流转约束:
|
||||||
* - 未登录:可以进入游客登录 / 其他登录。
|
* - 未登录:可以进入游客登录 / 其他登录。
|
||||||
* - 游客登录:只可以升级为其他登录,不响应退出。
|
* - 游客登录:只可以升级为其他登录,不响应退出。
|
||||||
* - 其他登录:可以退出,不响应游客登录。
|
* - 其他登录:可以退出,不响应游客登录 / 重复其他登录。
|
||||||
*
|
*
|
||||||
* 状态结构(parent state 模式):
|
* 状态结构(parent state 模式):
|
||||||
* - `idle`:屏没挂 / 登出
|
* - `idle`:屏没挂 / 登出
|
||||||
@@ -363,11 +356,6 @@ export const chatMachine = setup({
|
|||||||
target: "#chat.idle",
|
target: "#chat.idle",
|
||||||
actions: "clearChatSession",
|
actions: "clearChatSession",
|
||||||
},
|
},
|
||||||
ChatUserLogin: {
|
|
||||||
target: "#chat.userSession",
|
|
||||||
reenter: true,
|
|
||||||
actions: "startUserSession",
|
|
||||||
},
|
|
||||||
ChatQueuedSendStarted: {
|
ChatQueuedSendStarted: {
|
||||||
actions: "markQueuedSendStarted",
|
actions: "markQueuedSendStarted",
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user