Skip to content

Commit e9efd72

Browse files
committed
tests(angular): test against input signal support
1 parent cd1efa4 commit e9efd72

6 files changed

Lines changed: 279 additions & 14 deletions

File tree

packages/angular-store/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
},
5353
"devDependencies": {
5454
"@analogjs/vite-plugin-angular": "^2.2.3",
55+
"@analogjs/vitest-angular": "^2.3.1",
5556
"@angular/common": "^21.1.2",
5657
"@angular/compiler": "^21.1.2",
5758
"@angular/compiler-cli": "^21.1.2",

packages/angular-store/tests/index.test.ts

Lines changed: 145 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
11
import { describe, expect, test } from 'vitest'
2-
import { Component, effect } from '@angular/core'
2+
import {
3+
Component,
4+
computed,
5+
effect,
6+
input,
7+
OnInit,
8+
signal,
9+
untracked,
10+
inputBinding,
11+
} from '@angular/core'
312
import { TestBed } from '@angular/core/testing'
413
import { By } from '@angular/platform-browser'
514
import { createStore } from '@tanstack/store'
615
import { injectStore } from '../src/index'
716

17+
function createStableSignal<T>(fn: () => T): () => T {
18+
return computed(() => untracked(fn))
19+
}
20+
21+
const selectorReadsInputStore = createStore({ cats: 2, dogs: 4 })
22+
823
describe('injectStore', () => {
924
test(`allows us to select state using a selector`, () => {
1025
const store = createStore({ select: 0, ignored: 1 })
@@ -92,6 +107,135 @@ describe('injectStore', () => {
92107
expect(element.textContent).toContain('Store: 10')
93108
expect(count).toEqual(2)
94109
})
110+
111+
test('supports a store created inside a stable signal', () => {
112+
const count = signal(1)
113+
114+
const storeVal = TestBed.runInInjectionContext(() => {
115+
const store = createStableSignal(() => createStore({ value: count() }))
116+
const storeVal = injectStore(() => store(), (state) => state.value)
117+
118+
effect(() => {
119+
store().setState(() => ({ value: count() }))
120+
})
121+
122+
return storeVal
123+
})
124+
125+
expect(storeVal()).toBe(1)
126+
127+
count.set(5)
128+
TestBed.tick()
129+
130+
expect(storeVal()).toBe(5)
131+
})
132+
133+
test('supports a store created from input signals', () => {
134+
@Component({
135+
template: `<p id="displayStoreVal">{{ storeVal() }}</p>`,
136+
standalone: true,
137+
})
138+
class StoreFromInputChildCmp {
139+
value = input.required<number>()
140+
store = createStableSignal(() =>
141+
createStore({ doubled: this.value() * 2 }),
142+
)
143+
storeVal = injectStore(() => this.store(), (state) => state.doubled)
144+
145+
constructor() {
146+
effect(() => {
147+
this.store().setState(() => ({ doubled: this.value() * 2 }))
148+
})
149+
}
150+
}
151+
152+
const value = signal(3)
153+
const fixture = TestBed.createComponent(StoreFromInputChildCmp, {
154+
bindings: [inputBinding('value', value)],
155+
})
156+
fixture.detectChanges()
157+
158+
const debugElement = fixture.debugElement
159+
160+
expect(
161+
debugElement.query(By.css('p#displayStoreVal')).nativeElement.textContent,
162+
).toContain('6')
163+
164+
value.set(4)
165+
fixture.detectChanges()
166+
167+
expect(
168+
debugElement.query(By.css('p#displayStoreVal')).nativeElement.textContent,
169+
).toContain('8')
170+
})
171+
172+
test('supports selectors that read input signals', () => {
173+
@Component({
174+
selector: 'app-selector-reads-input',
175+
template: `<p id="displayStoreVal">{{ count() }}</p>`,
176+
standalone: true,
177+
})
178+
class SelectorReadsInputChildCmp {
179+
animal = input.required<'cats' | 'dogs'>()
180+
count = injectStore(
181+
selectorReadsInputStore,
182+
(state) => state[this.animal()],
183+
)
184+
}
185+
186+
const animal = signal<'cats' | 'dogs'>('cats')
187+
const fixture = TestBed.createComponent(SelectorReadsInputChildCmp, {
188+
bindings: [inputBinding('animal', animal)],
189+
})
190+
fixture.detectChanges()
191+
192+
const debugElement = fixture.debugElement
193+
194+
expect(
195+
debugElement.query(By.css('p#displayStoreVal')).nativeElement.textContent,
196+
).toContain('2')
197+
198+
animal.set('dogs')
199+
fixture.detectChanges()
200+
201+
expect(
202+
debugElement.query(By.css('p#displayStoreVal')).nativeElement.textContent,
203+
).toContain('4')
204+
})
205+
206+
test('makes the selected store value available on ngOnInit', () => {
207+
let didAssertOnInit = false
208+
209+
@Component({
210+
template: ``,
211+
standalone: true,
212+
})
213+
class StoreFromInputOnInitCmp implements OnInit {
214+
value = input.required<number>()
215+
store = createStableSignal(() =>
216+
createStore({ doubled: this.value() * 2 }),
217+
)
218+
storeVal = injectStore(() => this.store(), (state) => state.doubled)
219+
220+
constructor() {
221+
effect(() => {
222+
this.store().setState(() => ({ doubled: this.value() * 2 }))
223+
})
224+
}
225+
226+
ngOnInit() {
227+
expect(this.storeVal()).toBe(14)
228+
didAssertOnInit = true
229+
}
230+
}
231+
232+
const value = signal(7)
233+
const fixture = TestBed.createComponent(StoreFromInputOnInitCmp, {
234+
bindings: [inputBinding('value', value)],
235+
})
236+
fixture.detectChanges()
237+
expect(didAssertOnInit).toBe(true)
238+
})
95239
})
96240

97241
describe('dataType', () => {
Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
1-
import '@analogjs/vite-plugin-angular/setup-vitest'
1+
import '@angular/compiler';
2+
import { setupTestBed } from '@analogjs/vitest-angular/setup-testbed';
23

3-
import {
4-
BrowserDynamicTestingModule,
5-
platformBrowserDynamicTesting,
6-
} from '@angular/platform-browser-dynamic/testing'
7-
import { getTestBed } from '@angular/core/testing'
8-
9-
getTestBed().initTestEnvironment(
10-
BrowserDynamicTestingModule,
11-
platformBrowserDynamicTesting(),
12-
)
4+
setupTestBed();
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"noEmit": false,
5+
"types": ["vitest/globals", "node"]
6+
},
7+
"files": ["src/test-setup.ts"],
8+
"include": ["tests/**/*.ts"]
9+
}

packages/angular-store/vite.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { defineConfig } from 'vitest/config'
22
import packageJson from './package.json'
3+
import angular from '@analogjs/vite-plugin-angular';
34

45
export default defineConfig({
6+
plugins: [angular()],
57
test: {
68
name: packageJson.name,
79
dir: './tests',

pnpm-lock.yaml

Lines changed: 119 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)