Merge remote-tracking branch 'origin/master' into feat/web-message-feedback-ui
Adapt to two contract changes master introduced: - The generated Remote face now wraps every business result in RemoteResult, folding carrier failures into an ok:false branch instead of rejecting. The controller reads that envelope at its three call sites and maps a carrier failure onto the same settled shape the controls already render; three specs cover the new branch. - Client packages split their tsconfig into host and client halves, and the host aggregate now compiles any test not named *.client.spec.*. Rename this package's specs to the client convention and drop the ../connection project reference, which pointed at a solution file that no longer carries the client sources. Keep master's mount loop with its rollback-on-failure in api-remotes and add messageFeedbackRemote to it.
This commit is contained in:
103
packages/client/ui-layout/tests/layout-store.client.spec.ts
Normal file
103
packages/client/ui-layout/tests/layout-store.client.spec.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
// @vitest-environment jsdom
|
||||
/**
|
||||
* createLayoutStore unit account: init shape, the action write set (clamp
|
||||
* inside actions), and the absence of browser persistence. Uses the
|
||||
* test-sanctioned path: factory self-call + .create() gives the
|
||||
* real engine instance (same create path as production).
|
||||
*/
|
||||
import { beforeEach, describe, expect, it } from 'vitest'
|
||||
import { createLayoutStore } from '@deepseek-ai/dsh-client-ui-layout/src/client/stores.ts'
|
||||
import {
|
||||
DETAILS_DEFAULT, DETAILS_MAX, DETAILS_MIN,
|
||||
SIDEBAR_DEFAULT, SIDEBAR_MAX, SIDEBAR_MIN,
|
||||
} from '@deepseek-ai/dsh-client-ui-layout/src/client/columns.ts'
|
||||
|
||||
const PERSIST_KEY = 'dsh.layout.panels'
|
||||
|
||||
beforeEach(() => { localStorage.clear() })
|
||||
|
||||
describe('createLayoutStore', () => {
|
||||
it('initializes the sidebar at its default width, details closed, wide viewport assumed', () => {
|
||||
const { store } = createLayoutStore().create()
|
||||
expect(store.getSnapshot()).toEqual({ sidebar: SIDEBAR_DEFAULT, details: 0, narrow: false, narrowExpanded: false })
|
||||
})
|
||||
|
||||
it('each create() is an independent instance (factory is not a singleton)', () => {
|
||||
const a = createLayoutStore().create()
|
||||
const b = createLayoutStore().create()
|
||||
a.actions.setSidebar(400)
|
||||
expect(b.store.getSnapshot().sidebar).toBe(SIDEBAR_DEFAULT)
|
||||
})
|
||||
|
||||
it('setSidebar/setDetails clamp into the contract ranges', () => {
|
||||
const { store, actions } = createLayoutStore().create()
|
||||
actions.setSidebar(1)
|
||||
expect(store.getSnapshot().sidebar).toBe(SIDEBAR_MIN)
|
||||
actions.setSidebar(9999)
|
||||
expect(store.getSnapshot().sidebar).toBe(SIDEBAR_MAX)
|
||||
actions.setDetails(1)
|
||||
expect(store.getSnapshot().details).toBe(DETAILS_MIN)
|
||||
actions.setDetails(9999)
|
||||
expect(store.getSnapshot().details).toBe(DETAILS_MAX)
|
||||
})
|
||||
|
||||
it('toggleSidebar flips closed <-> contract default (drag width forgotten)', () => {
|
||||
const { store, actions } = createLayoutStore().create()
|
||||
actions.setSidebar(400)
|
||||
actions.toggleSidebar()
|
||||
expect(store.getSnapshot().sidebar).toBe(0)
|
||||
actions.toggleSidebar()
|
||||
expect(store.getSnapshot().sidebar).toBe(SIDEBAR_DEFAULT)
|
||||
})
|
||||
|
||||
it('narrow toggleSidebar flips only the re-expand override; the width preference survives', () => {
|
||||
const { store, actions } = createLayoutStore().create()
|
||||
actions.setSidebar(400)
|
||||
actions.setNarrow(true)
|
||||
actions.toggleSidebar()
|
||||
expect(store.getSnapshot()).toEqual({ sidebar: 400, details: 0, narrow: true, narrowExpanded: true })
|
||||
actions.toggleSidebar()
|
||||
expect(store.getSnapshot().narrowExpanded).toBe(false)
|
||||
expect(store.getSnapshot().sidebar).toBe(400)
|
||||
})
|
||||
|
||||
it('crossing the breakpoint drops the override; a same-value setNarrow keeps it', () => {
|
||||
const { store, actions } = createLayoutStore().create()
|
||||
actions.setNarrow(true)
|
||||
actions.toggleSidebar()
|
||||
expect(store.getSnapshot().narrowExpanded).toBe(true)
|
||||
actions.setNarrow(true)
|
||||
expect(store.getSnapshot().narrowExpanded).toBe(true)
|
||||
actions.setNarrow(false)
|
||||
expect(store.getSnapshot()).toMatchObject({ narrow: false, narrowExpanded: false })
|
||||
actions.setNarrow(true)
|
||||
expect(store.getSnapshot().narrowExpanded).toBe(false)
|
||||
})
|
||||
|
||||
it('openDetails uses the contract default, preserves an open width, and closeDetails zeroes', () => {
|
||||
const { store, actions } = createLayoutStore().create()
|
||||
actions.openDetails()
|
||||
expect(store.getSnapshot().details).toBe(DETAILS_DEFAULT)
|
||||
actions.setDetails(500)
|
||||
actions.openDetails()
|
||||
expect(store.getSnapshot().details).toBe(500)
|
||||
actions.closeDetails()
|
||||
expect(store.getSnapshot().details).toBe(0)
|
||||
})
|
||||
|
||||
it('does not persist panel geometry', () => {
|
||||
const first = createLayoutStore().create()
|
||||
first.actions.setSidebar(400)
|
||||
first.actions.openDetails()
|
||||
first.actions.setDetails(500)
|
||||
expect(localStorage.getItem(PERSIST_KEY)).toBeNull()
|
||||
|
||||
const second = createLayoutStore().create()
|
||||
expect(second.store.getSnapshot()).toEqual({
|
||||
sidebar: SIDEBAR_DEFAULT,
|
||||
details: 0,
|
||||
narrow: false,
|
||||
narrowExpanded: false,
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user