-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Expand file tree
/
Copy pathtest-utils.ts
More file actions
137 lines (121 loc) · 3.52 KB
/
Copy pathtest-utils.ts
File metadata and controls
137 lines (121 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { isSignal, untracked } from '@angular/core'
import { SIGNAL, signalSetFn } from '@angular/core/primitives/signals'
import { expect } from 'vitest'
import type { InputSignal, Signal } from '@angular/core'
import type { ComponentFixture } from '@angular/core/testing'
let queryKeyCount = 0
export function queryKey() {
queryKeyCount++
return [`query_${queryKeyCount}`]
}
export function simpleFetcher(): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => {
return resolve('Some data')
}, 0)
})
}
export function delayedFetcher(timeout = 0): () => Promise<string> {
return () =>
new Promise((resolve) => {
setTimeout(() => {
return resolve('Some data')
}, timeout)
})
}
export function getSimpleFetcherWithReturnData(returnData: unknown) {
return () =>
new Promise((resolve) => setTimeout(() => resolve(returnData), 0))
}
export function rejectFetcher(): Promise<Error> {
return new Promise((_, reject) => {
setTimeout(() => {
return reject(new Error('Some error'))
}, 0)
})
}
export function infiniteFetcher({
pageParam,
}: {
pageParam?: number
}): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => {
return resolve('data on page ' + pageParam)
}, 0)
})
}
export function successMutator<T>(param: T): Promise<T> {
return new Promise((resolve) => {
setTimeout(() => {
return resolve(param)
}, 0)
})
}
export function errorMutator(_parameter?: unknown): Promise<Error> {
return rejectFetcher()
}
// Evaluate all signals on an object and return the result
function evaluateSignals<T extends Record<string, any>>(
obj: T,
): { [K in keyof T]: ReturnType<T[K]> } {
const result: Partial<{ [K in keyof T]: ReturnType<T[K]> }> = {}
untracked(() => {
for (const key in obj) {
if (
Object.prototype.hasOwnProperty.call(obj, key) &&
// Only evaluate signals, not normal functions
isSignal(obj[key])
) {
const func = obj[key]
result[key] = func()
}
}
})
return result as { [K in keyof T]: ReturnType<T[K]> }
}
export const expectSignals = <T extends Record<string, any>>(
obj: T,
expected: Partial<{
[K in keyof T]: T[K] extends Signal<any> ? ReturnType<T[K]> : never
}>,
): void => {
expect(evaluateSignals(obj)).toMatchObject(expected)
}
type ToSignalInputUpdatableMap<T> = {
[K in keyof T as T[K] extends InputSignal<any>
? K
: never]: T[K] extends InputSignal<infer Value> ? Value : never
}
function componentHasSignalInputProperty<TProperty extends string>(
component: object,
property: TProperty,
): component is { [key in TProperty]: InputSignal<unknown> } {
return (
component.hasOwnProperty(property) && (component as any)[property][SIGNAL]
)
}
/**
* Set required signal input value to component fixture
* @see https://github.com/angular/angular/issues/54013
*/
export function setSignalInputs<T extends NonNullable<unknown>>(
component: T,
inputs: ToSignalInputUpdatableMap<T>,
) {
for (const inputKey in inputs) {
if (componentHasSignalInputProperty(component, inputKey)) {
signalSetFn(component[inputKey][SIGNAL], inputs[inputKey])
}
}
}
export function setFixtureSignalInputs<T extends NonNullable<unknown>>(
componentFixture: ComponentFixture<T>,
inputs: ToSignalInputUpdatableMap<T>,
options: { detectChanges: boolean } = { detectChanges: true },
) {
setSignalInputs(componentFixture.componentInstance, inputs)
if (options.detectChanges) {
componentFixture.detectChanges()
}
}