import { createPinia, setActivePinia } from 'pinia' import { beforeEach, describe, expect, test, vi } from 'vitest' import { authApi } from '../api/auth' import { useOrganizationStore } from './organization' import { resetOrganizationContext } from '../utils/organizationContext' vi.mock('../api/auth', () => ({ authApi: { listOrganizations: vi.fn(), switchOrganizationContext: vi.fn() } })) // 模拟某个账号已登录:公司选择按用户 id 分开存储,这里写入对应账号。 function loginAs(id) { localStorage.setItem('wmms_user', JSON.stringify({ id, username: `user${id}` })) } function orgList(organizations, defaultOrganizationId) { return { data: { organizations, default_organization_id: defaultOrganizationId } } } function switchResult(organizationId, warehouse = null) { return { data: { organization_id: organizationId, organization: { id: organizationId }, warehouse } } } const ACTIVE_WAREHOUSE = { id: 10, name: '武汉仓', status: 'active', location: { id: 100, name: 'A库位', status: 'active' } } describe('organization store', () => { beforeEach(() => { localStorage.clear() sessionStorage.clear() resetOrganizationContext() setActivePinia(createPinia()) authApi.listOrganizations.mockReset() authApi.switchOrganizationContext.mockReset() }) test('默认公司进入并自动选中唯一启用的仓库与库位', async () => { loginAs(1) authApi.listOrganizations.mockResolvedValue(orgList([{ id: 1, name: '北京' }, { id: 2, name: '武汉' }], 2)) authApi.switchOrganizationContext.mockResolvedValue(switchResult(2, ACTIVE_WAREHOUSE)) const store = useOrganizationStore() await store.initialize() expect(store.organizations.map(o => o.id)).toEqual([1, 2]) expect(store.currentOrganizationId).toBe(2) expect(store.currentWarehouseId).toBe(10) expect(store.currentLocationId).toBe(100) expect(store.initialized).toBe(true) expect(authApi.switchOrganizationContext).toHaveBeenCalledWith(2, 0) }) test('只展示接口返回的授权公司', async () => { loginAs(1) authApi.listOrganizations.mockResolvedValue(orgList([{ id: 3, name: '上海' }], 3)) authApi.switchOrganizationContext.mockResolvedValue(switchResult(3)) const store = useOrganizationStore() await store.initialize() expect(store.organizations.map(o => o.id)).toEqual([3]) expect(store.currentOrganizationId).toBe(3) }) test('默认公司失效时保留列表并要求重新选择', async () => { loginAs(1) authApi.listOrganizations.mockResolvedValue(orgList([{ id: 1, name: '北京' }], 99)) authApi.switchOrganizationContext.mockRejectedValue(new Error('公司不可访问')) const store = useOrganizationStore() await store.initialize() expect(store.organizations.map(o => o.id)).toEqual([1]) expect(store.currentOrganizationId).toBeNull() expect(store.initialized).toBe(true) }) test('没有授权公司时进入空状态且不发起校验', async () => { loginAs(1) authApi.listOrganizations.mockResolvedValue(orgList([], null)) const store = useOrganizationStore() await store.initialize() expect(store.organizations).toEqual([]) expect(store.currentOrganizationId).toBeNull() expect(store.currentWarehouseId).toBeNull() expect(store.currentLocationId).toBeNull() expect(authApi.switchOrganizationContext).not.toHaveBeenCalled() }) test('切换失败时保留旧公司', async () => { loginAs(1) authApi.listOrganizations.mockResolvedValue(orgList([{ id: 1 }, { id: 2 }], 1)) authApi.switchOrganizationContext.mockResolvedValueOnce( switchResult(1, { id: 9, name: '北京仓', status: 'active', location: { id: 90, name: '库位', status: 'active' } }) ) const store = useOrganizationStore() await store.initialize() expect(store.currentOrganizationId).toBe(1) authApi.switchOrganizationContext.mockRejectedValueOnce(new Error('公司不可访问')) await expect(store.switchOrganization(2)).rejects.toThrow() expect(store.currentOrganizationId).toBe(1) expect(store.currentWarehouseId).toBe(9) expect(store.currentLocationId).toBe(90) expect(store.switching).toBe(false) }) test('切换成功后提交新公司并递增上下文版本', async () => { loginAs(1) authApi.listOrganizations.mockResolvedValue(orgList([{ id: 1 }, { id: 2 }], 1)) authApi.switchOrganizationContext.mockResolvedValueOnce(switchResult(1)) const store = useOrganizationStore() await store.initialize() const versionBefore = store.contextVersion authApi.switchOrganizationContext.mockResolvedValueOnce(switchResult(2, ACTIVE_WAREHOUSE)) await store.switchOrganization(2) expect(store.currentOrganizationId).toBe(2) expect(store.contextVersion).toBeGreaterThan(versionBefore) expect(store.currentWarehouseId).toBe(10) expect(store.currentLocationId).toBe(100) expect(authApi.switchOrganizationContext).toHaveBeenLastCalledWith(2, 1) }) test('切换到当前公司不重复发起校验', async () => { loginAs(1) authApi.listOrganizations.mockResolvedValue(orgList([{ id: 1 }], 1)) authApi.switchOrganizationContext.mockResolvedValueOnce(switchResult(1)) const store = useOrganizationStore() await store.initialize() authApi.switchOrganizationContext.mockClear() await store.switchOrganization(1) expect(authApi.switchOrganizationContext).not.toHaveBeenCalled() }) test('仓库停用时仓库与库位都为空', async () => { loginAs(1) authApi.listOrganizations.mockResolvedValue(orgList([{ id: 1 }], 1)) authApi.switchOrganizationContext.mockResolvedValue(switchResult(1, { id: 5, name: '停用仓', status: 'inactive', location: { id: 50, name: '库位', status: 'active' } })) const store = useOrganizationStore() await store.initialize() expect(store.currentWarehouseId).toBeNull() expect(store.currentLocationId).toBeNull() }) test('库位缺失或停用时仅库位为空', async () => { loginAs(1) authApi.listOrganizations.mockResolvedValue(orgList([{ id: 1 }], 1)) authApi.switchOrganizationContext.mockResolvedValue(switchResult(1, { id: 5, name: '启用仓', status: 'active', location: null })) const store = useOrganizationStore() await store.initialize() expect(store.currentWarehouseId).toBe(5) expect(store.currentLocationId).toBeNull() }) test('目标公司没有仓库时清空旧公司的仓库与库位', async () => { loginAs(1) authApi.listOrganizations.mockResolvedValue(orgList([{ id: 1 }, { id: 2 }], 1)) authApi.switchOrganizationContext.mockResolvedValueOnce(switchResult(1, ACTIVE_WAREHOUSE)) const store = useOrganizationStore() await store.initialize() expect(store.currentWarehouseId).toBe(10) authApi.switchOrganizationContext.mockResolvedValueOnce(switchResult(2, null)) await store.switchOrganization(2) expect(store.currentOrganizationId).toBe(2) expect(store.currentWarehouseId).toBeNull() expect(store.currentLocationId).toBeNull() }) test('不同账号不继承上一账号的公司选择', async () => { // 账号 1 上次在本标签页选择了公司 2 loginAs(1) sessionStorage.setItem('wmms_organization_id:1', '2') // 换成账号 2 登录:读到的应是账号 2 的存储(为空),回落到默认公司 1 loginAs(2) authApi.listOrganizations.mockResolvedValue(orgList([{ id: 1 }, { id: 2 }], 1)) authApi.switchOrganizationContext.mockResolvedValue(switchResult(1)) const store = useOrganizationStore() await store.initialize() expect(store.currentOrganizationId).toBe(1) expect(authApi.switchOrganizationContext).toHaveBeenCalledWith(1, 0) }) test('切换进行中禁止再次切换', async () => { loginAs(1) authApi.listOrganizations.mockResolvedValue(orgList([{ id: 1 }], 1)) authApi.switchOrganizationContext.mockResolvedValueOnce(switchResult(1)) const store = useOrganizationStore() await store.initialize() authApi.switchOrganizationContext.mockClear() store.switching = true await store.switchOrganization(2) expect(authApi.switchOrganizationContext).not.toHaveBeenCalled() expect(store.currentOrganizationId).toBe(1) }) test('reset 清空公司状态与上下文', async () => { loginAs(1) authApi.listOrganizations.mockResolvedValue(orgList([{ id: 1 }], 1)) authApi.switchOrganizationContext.mockResolvedValue(switchResult(1, ACTIVE_WAREHOUSE)) const store = useOrganizationStore() await store.initialize() expect(store.currentOrganizationId).toBe(1) store.reset() expect(store.organizations).toEqual([]) expect(store.currentOrganizationId).toBeNull() expect(store.currentWarehouseId).toBeNull() expect(store.currentLocationId).toBeNull() expect(store.initialized).toBe(false) }) })