test: strengthen typing in promotionList tests

- Use `satisfies Partial<Omit<T, 'constructor'>>` for shape-checked mock
- Type mock param as NodeProperty instead of unknown
- Annotate test data with `satisfies ProxyWidgetsProperty`
- Document partial mock pattern in vitest-patterns.md

Amp-Thread-ID: https://ampcode.com/threads/T-019c5543-f50b-77a2-bca6-2549bdc15594
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Alexander Brown
2026-02-12 20:37:16 -08:00
parent c79e8a2251
commit e8af61e25d
2 changed files with 34 additions and 4 deletions

View File

@@ -61,6 +61,30 @@ vi.mock('@/services/myService', () => ({
}))
```
### Partial object mocks with `satisfies`
When mocking a class instance with only the properties your test needs, use
`satisfies Partial<Omit<T, 'constructor'>> as unknown as T`. This validates
the mock's shape against the real type while allowing the incomplete cast.
The `Omit<..., 'constructor'>` is needed because class types expose a
`constructor` property whose type (`LGraphNodeConstructor`, etc.) conflicts
with the plain object's `Function` constructor.
```typescript
// ✅ Shape-checked partial mock
function mockSubgraphNode(proxyWidgets?: NodeProperty) {
return {
properties: { proxyWidgets }
} satisfies Partial<Omit<SubgraphNode, 'constructor'>> as unknown as SubgraphNode
}
// ❌ Unchecked — typos and shape mismatches slip through
function mockSubgraphNode(proxyWidgets?: unknown): SubgraphNode {
return { properties: { proxyWidgets } } as unknown as SubgraphNode
}
```
### Configure mocks in tests
```typescript

View File

@@ -1,11 +1,17 @@
import { describe, expect, it } from 'vitest'
import type { ProxyWidgetsProperty } from '@/core/schemas/proxyWidget'
import type { NodeProperty } from '@/lib/litegraph/src/LGraphNode'
import type { SubgraphNode } from '@/lib/litegraph/src/subgraph/SubgraphNode'
import { getPromotionList } from './promotionList'
function mockSubgraphNode(proxyWidgets?: unknown): SubgraphNode {
return { properties: { proxyWidgets } } as unknown as SubgraphNode
function mockSubgraphNode(proxyWidgets?: NodeProperty) {
return {
properties: { proxyWidgets }
} satisfies Partial<
Omit<SubgraphNode, 'constructor'>
> as unknown as SubgraphNode
}
describe('getPromotionList', () => {
@@ -23,13 +29,13 @@ describe('getPromotionList', () => {
const entries = [
['42', 'seed'],
['7', 'steps']
]
] satisfies ProxyWidgetsProperty
const node = mockSubgraphNode(entries)
expect(getPromotionList(node)).toEqual(entries)
})
it('handles string-serialized proxyWidgets (JSON)', () => {
const entries = [['42', 'seed']]
const entries = [['42', 'seed']] satisfies ProxyWidgetsProperty
const node = mockSubgraphNode(JSON.stringify(entries))
expect(getPromotionList(node)).toEqual(entries)
})