rockstar-strudel 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/PLAN.md +227 -0
- package/README.md +123 -0
- package/package.json +31 -0
- package/src/index.js +210 -0
- package/test/rockstar.test.js +159 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the non-WASM helper logic in src/index.js.
|
|
3
|
+
*
|
|
4
|
+
* These tests cover `buildSource` and `coerce` — the two pure functions that
|
|
5
|
+
* can be exercised without loading the .NET WASM runtime.
|
|
6
|
+
*
|
|
7
|
+
* Run with: npm test
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, it } from 'node:test';
|
|
11
|
+
import assert from 'node:assert/strict';
|
|
12
|
+
import { buildSource, coerce, isTrustedUrl } from '../src/index.js';
|
|
13
|
+
|
|
14
|
+
// ─── buildSource ────────────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
describe('buildSource', () => {
|
|
17
|
+
it('returns the raw template string when there are no interpolations', () => {
|
|
18
|
+
const src = buildSource`My heart is 123`;
|
|
19
|
+
assert.equal(src, 'My heart is 123');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('splices a single string interpolation', () => {
|
|
23
|
+
const name = 'Alice';
|
|
24
|
+
const src = buildSource`Let ${name} be 42`;
|
|
25
|
+
assert.equal(src, 'Let Alice be 42');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('stringifies a numeric interpolation', () => {
|
|
29
|
+
const n = 99;
|
|
30
|
+
const src = buildSource`Tommy was ${n}`;
|
|
31
|
+
assert.equal(src, 'Tommy was 99');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('handles multiple interpolations in the correct order', () => {
|
|
35
|
+
const a = 'my heart';
|
|
36
|
+
const b = 123;
|
|
37
|
+
const src = buildSource`${a} is ${b}`;
|
|
38
|
+
assert.equal(src, 'my heart is 123');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('preserves leading and trailing whitespace / newlines in the template', () => {
|
|
42
|
+
const src = buildSource`
|
|
43
|
+
Shout "hello"
|
|
44
|
+
`;
|
|
45
|
+
assert.equal(src, '\n Shout "hello"\n');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('treats undefined interpolation values as empty strings', () => {
|
|
49
|
+
// Simulates calling buildSource(['a', 'b'], undefined)
|
|
50
|
+
const src = buildSource(['a', 'b'], undefined);
|
|
51
|
+
assert.equal(src, 'ab');
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// ─── coerce ─────────────────────────────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
describe('coerce', () => {
|
|
58
|
+
it('converts an integer string to a JS number', () => {
|
|
59
|
+
assert.equal(coerce('123\n'), 123);
|
|
60
|
+
assert.strictEqual(typeof coerce('123\n'), 'number');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('converts a decimal string to a JS number', () => {
|
|
64
|
+
assert.equal(coerce('3.14\n'), 3.14);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('converts a negative number string', () => {
|
|
68
|
+
assert.equal(coerce('-7\n'), -7);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('handles Windows-style CRLF line endings', () => {
|
|
72
|
+
assert.equal(coerce('42\r\n'), 42);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('converts zero', () => {
|
|
76
|
+
assert.equal(coerce('0\n'), 0);
|
|
77
|
+
assert.strictEqual(typeof coerce('0\n'), 'number');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('returns a string for non-numeric output', () => {
|
|
81
|
+
assert.equal(coerce('hello\n'), 'hello');
|
|
82
|
+
assert.strictEqual(typeof coerce('hello\n'), 'string');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('returns a string for boolean-like output', () => {
|
|
86
|
+
assert.equal(coerce('true\n'), 'true');
|
|
87
|
+
assert.equal(coerce('false\n'), 'false');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('returns a string for null-like output', () => {
|
|
91
|
+
assert.equal(coerce('null\n'), 'null');
|
|
92
|
+
assert.equal(coerce('mysterious\n'), 'mysterious');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('returns undefined for an empty line', () => {
|
|
96
|
+
assert.equal(coerce(''), undefined);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('returns undefined for a line containing only a newline', () => {
|
|
100
|
+
assert.equal(coerce('\n'), undefined);
|
|
101
|
+
assert.equal(coerce('\r\n'), undefined);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('does not coerce Infinity to a number (not finite)', () => {
|
|
105
|
+
assert.equal(coerce('Infinity\n'), 'Infinity');
|
|
106
|
+
assert.strictEqual(typeof coerce('Infinity\n'), 'string');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('does not coerce NaN to a number', () => {
|
|
110
|
+
assert.equal(coerce('NaN\n'), 'NaN');
|
|
111
|
+
assert.strictEqual(typeof coerce('NaN\n'), 'string');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('strips multiple trailing newlines', () => {
|
|
115
|
+
assert.equal(coerce('42\n\n'), 42);
|
|
116
|
+
assert.equal(coerce('hi\n\n'), 'hi');
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// ─── isTrustedUrl ────────────────────────────────────────────────────────────
|
|
121
|
+
|
|
122
|
+
describe('isTrustedUrl', () => {
|
|
123
|
+
it('trusts codewithrockstar.com', () => {
|
|
124
|
+
assert.ok(isTrustedUrl('https://codewithrockstar.com/wasm/wwwroot/_framework/dotnet.js'));
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('trusts cdn.jsdelivr.net', () => {
|
|
128
|
+
assert.ok(isTrustedUrl('https://cdn.jsdelivr.net/gh/someone/rockstar@v1/wasm/dotnet.js'));
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('trusts unpkg.com', () => {
|
|
132
|
+
assert.ok(isTrustedUrl('https://unpkg.com/some-package/dotnet.js'));
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('trusts any *.github.io subdomain', () => {
|
|
136
|
+
assert.ok(isTrustedUrl('https://stretchyboy.github.io/rockstar/wasm/wwwroot/_framework/dotnet.js'));
|
|
137
|
+
assert.ok(isTrustedUrl('https://anyone.github.io/rockstar/wasm/wwwroot/_framework/dotnet.js'));
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('trusts localhost with a port', () => {
|
|
141
|
+
assert.ok(isTrustedUrl('http://localhost:8080/_framework/dotnet.js'));
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('trusts 127.0.0.1 with a port', () => {
|
|
145
|
+
assert.ok(isTrustedUrl('http://127.0.0.1:3000/_framework/dotnet.js'));
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('rejects an arbitrary https URL', () => {
|
|
149
|
+
assert.ok(!isTrustedUrl('https://evil.example.com/dotnet.js'));
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('rejects a bare github.io URL without a subdomain', () => {
|
|
153
|
+
assert.ok(!isTrustedUrl('https://github.io/dotnet.js'));
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('rejects http (non-localhost)', () => {
|
|
157
|
+
assert.ok(!isTrustedUrl('http://codewithrockstar.com/wasm/dotnet.js'));
|
|
158
|
+
});
|
|
159
|
+
});
|