Skip to content

Commit 1581988

Browse files
crisbetoAndrewKushnir
authored andcommitted
test(core): add type tests for ɵunwrapWritableSignal (#54387)
Getting the typing for `ɵunwrapWritableSignal` just right was tricky so these changes add some tests to ensure that we don't regress. Also reworks the type tester a bit to make it easier to find where to add new test files. PR Close #54387
1 parent 0ecc2d1 commit 1581988

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

packages/core/test/authoring/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ ts_library(
77
"signal_input_signature_test.ts",
88
"signal_model_signature_test.ts",
99
"signal_queries_signature_test.ts",
10+
"unwrap_writable_signal_signature_test.ts",
1011
],
1112
deps = ["//packages/core"],
1213
)

packages/core/test/authoring/type_tester.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ import path from 'path';
1111
import ts from 'typescript';
1212
import url from 'url';
1313

14+
/** Currently-configured tests. */
15+
const TESTS = new Map<string, (value: string) => string>([
16+
[
17+
'signal_input_signature_test',
18+
v => v.includes(',') ? `InputSignalWithTransform<${v}>` : `InputSignal<${v}>`
19+
],
20+
['signal_queries_signature_test', v => `Signal<${v}>`],
21+
['signal_model_signature_test', v => `ModelSignal<${v}>`],
22+
['unwrap_writable_signal_signature_test', v => v]
23+
]);
24+
1425
const containingDir = path.dirname(url.fileURLToPath(import.meta.url));
1526

1627
/**
@@ -21,8 +32,7 @@ function isTestClass(classDeclaration: ts.ClassDeclaration): boolean {
2132
return classDeclaration.name !== undefined && classDeclaration.name.text.endsWith('Test');
2233
}
2334

24-
function testFile(
25-
testFileName: string, getType: (v: string) => string, inferWriteType: boolean): boolean {
35+
function testFile(testFileName: string, getType: (v: string) => string): boolean {
2636
const fileContent = fs.readFileSync(path.join(containingDir, `${testFileName}.d.ts`), 'utf8');
2737
const sourceFile = ts.createSourceFile('test.ts', fileContent, ts.ScriptTarget.ESNext, true);
2838
const testClazz = sourceFile.statements.find(
@@ -63,11 +73,7 @@ function testFile(
6373
async function main() {
6474
let failing = false;
6575

66-
failing ||= testFile(
67-
'signal_input_signature_test',
68-
v => v.includes(',') ? `InputSignalWithTransform<${v}>` : `InputSignal<${v}>`, true);
69-
failing ||= testFile('signal_queries_signature_test', v => `Signal<${v}>`, false);
70-
failing ||= testFile('signal_model_signature_test', v => `ModelSignal<${v}>`, false);
76+
TESTS.forEach((callback, filename) => failing ||= testFile(filename, callback));
7177

7278
if (failing) {
7379
throw new Error('Failing assertions');
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
/**
10+
* @fileoverview
11+
* This file contains various signal `model()` patterns and ensures
12+
* the resulting types match our expectations (via comments asserting the `.d.ts`).
13+
*/
14+
15+
import {input, model, signal, ɵunwrapWritableSignal as unwrapWritableSignal} from '@angular/core';
16+
// clang-format off
17+
// import preserved to simplify `.d.ts` emit and simplify the `type_tester` logic.
18+
// tslint:disable-next-line no-duplicate-imports
19+
import {InputSignal, WritableSignal} from '@angular/core';
20+
// clang-format on
21+
22+
export class SignalModelSignatureTest {
23+
/** string | undefined */
24+
optionalModel = unwrapWritableSignal(model<string>());
25+
26+
/** string */
27+
requiredModel = unwrapWritableSignal(model.required<string>());
28+
29+
/** string | number */
30+
writableSignal = unwrapWritableSignal(signal<string|number>(0));
31+
32+
/** InputSignal<string | undefined> */
33+
optionalReadonlySignal = unwrapWritableSignal(input<string>());
34+
35+
/** InputSignal<string> */
36+
requiredReadonlySignal = unwrapWritableSignal(input.required<string>());
37+
38+
/** number */
39+
primitiveValue = unwrapWritableSignal(123);
40+
41+
/** (value: string | null | undefined) => number */
42+
getterFunction =
43+
unwrapWritableSignal((value: string|null|undefined) => value ? parseInt(value) : 0);
44+
}

0 commit comments

Comments
 (0)