squiffy-runtime 6.0.0-alpha.15 → 6.0.0-alpha.17
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/dist/animation.d.ts +11 -0
- package/dist/events.d.ts +8 -3
- package/dist/import.d.ts +4 -0
- package/dist/linkHandler.d.ts +8 -0
- package/dist/pluginManager.d.ts +23 -0
- package/dist/squiffy.runtime.d.ts +2 -2
- package/dist/squiffy.runtime.global.js +126 -0
- package/dist/squiffy.runtime.global.js.map +1 -0
- package/dist/squiffy.runtime.js +8785 -487
- package/dist/squiffy.runtime.js.map +1 -0
- package/dist/state.d.ts +19 -0
- package/dist/textProcessor.d.ts +8 -13
- package/dist/types.d.ts +5 -2
- package/dist/types.plugins.d.ts +27 -0
- package/dist/updater.d.ts +2 -0
- package/dist/utils.d.ts +1 -2
- package/package.json +12 -5
- package/src/__snapshots__/squiffy.runtime.test.ts.snap +53 -19
- package/src/animation.ts +68 -0
- package/src/events.ts +9 -10
- package/src/import.ts +5 -0
- package/src/linkHandler.ts +18 -0
- package/src/pluginManager.ts +74 -0
- package/src/plugins/animate.ts +97 -0
- package/src/plugins/index.ts +13 -0
- package/src/plugins/live.ts +83 -0
- package/src/plugins/random.ts +22 -0
- package/src/plugins/replaceLabel.ts +22 -0
- package/src/plugins/rotateSequence.ts +61 -0
- package/src/squiffy.runtime.test.ts +306 -134
- package/src/squiffy.runtime.ts +460 -332
- package/src/state.ts +106 -0
- package/src/textProcessor.ts +61 -164
- package/src/types.plugins.ts +41 -0
- package/src/types.ts +5 -2
- package/src/updater.ts +77 -0
- package/src/utils.ts +15 -12
- package/vite.config.ts +36 -0
- package/vitest.config.ts +9 -0
- package/vitest.setup.ts +16 -0
- package/dist/events.js +0 -35
- package/dist/squiffy.runtime.test.js +0 -394
- package/dist/textProcessor.js +0 -166
- package/dist/types.js +0 -1
- package/dist/utils.js +0 -14
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { expect, test, beforeEach, afterEach, vi } from
|
|
2
|
-
import fs from
|
|
3
|
-
import globalJsdom from
|
|
4
|
-
import { init } from
|
|
5
|
-
import { compile as squiffyCompile } from
|
|
1
|
+
import { expect, test, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import fs from "fs/promises";
|
|
3
|
+
import globalJsdom from "global-jsdom";
|
|
4
|
+
import { init } from "./squiffy.runtime.js";
|
|
5
|
+
import { compile as squiffyCompile } from "squiffy-compiler";
|
|
6
6
|
|
|
7
7
|
const html = `
|
|
8
8
|
<!DOCTYPE html>
|
|
@@ -24,11 +24,11 @@ const compile = async (script: string) => {
|
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
if (!compileResult.success) {
|
|
27
|
-
throw new Error(
|
|
27
|
+
throw new Error("Compile failed");
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const story = compileResult.output.story;
|
|
31
|
-
const js = compileResult.output.js.map(jsLines => new Function(
|
|
31
|
+
const js = compileResult.output.js.map(jsLines => new Function("squiffy", "get", "set", jsLines.join("\n")));
|
|
32
32
|
|
|
33
33
|
return {
|
|
34
34
|
story: {
|
|
@@ -36,26 +36,28 @@ const compile = async (script: string) => {
|
|
|
36
36
|
...story,
|
|
37
37
|
},
|
|
38
38
|
};
|
|
39
|
-
}
|
|
39
|
+
};
|
|
40
40
|
|
|
41
41
|
const initScript = async (script: string) => {
|
|
42
|
-
const element = document.getElementById(
|
|
42
|
+
const element = document.getElementById("squiffy");
|
|
43
43
|
|
|
44
44
|
if (!element) {
|
|
45
|
-
throw new Error(
|
|
45
|
+
throw new Error("Element not found");
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
const compileResult = await compile(script);
|
|
49
49
|
|
|
50
|
-
const squiffyApi = init({
|
|
50
|
+
const squiffyApi = await init({
|
|
51
51
|
element: element,
|
|
52
52
|
story: compileResult.story,
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
+
await squiffyApi.begin();
|
|
56
|
+
|
|
55
57
|
return {
|
|
56
58
|
squiffyApi,
|
|
57
59
|
element
|
|
58
|
-
}
|
|
60
|
+
};
|
|
59
61
|
};
|
|
60
62
|
|
|
61
63
|
const findLink = (element: HTMLElement, linkType: string, linkText: string, onlyEnabled: boolean = false) => {
|
|
@@ -66,12 +68,12 @@ const findLink = (element: HTMLElement, linkType: string, linkText: string, only
|
|
|
66
68
|
};
|
|
67
69
|
|
|
68
70
|
const getTestOutput = () => {
|
|
69
|
-
const testElement = document.getElementById(
|
|
71
|
+
const testElement = document.getElementById("test");
|
|
70
72
|
if (!testElement) {
|
|
71
|
-
throw new Error(
|
|
73
|
+
throw new Error("Test element not found");
|
|
72
74
|
}
|
|
73
75
|
return testElement.innerText;
|
|
74
|
-
}
|
|
76
|
+
};
|
|
75
77
|
|
|
76
78
|
let cleanup: { (): void };
|
|
77
79
|
|
|
@@ -88,76 +90,118 @@ test('"Hello world" script should run', async () => {
|
|
|
88
90
|
expect(element.innerHTML).toMatchSnapshot();
|
|
89
91
|
});
|
|
90
92
|
|
|
91
|
-
test(
|
|
92
|
-
const script = await fs.readFile(
|
|
93
|
+
test("Click a section link", async () => {
|
|
94
|
+
const script = await fs.readFile("../examples/test/example.squiffy", "utf-8");
|
|
93
95
|
const { squiffyApi, element } = await initScript(script);
|
|
94
96
|
expect(element.innerHTML).toMatchSnapshot();
|
|
95
97
|
|
|
96
|
-
expect(element.querySelectorAll(
|
|
97
|
-
const linkToPassage = findLink(element,
|
|
98
|
-
const section3Link = findLink(element,
|
|
98
|
+
expect(element.querySelectorAll("a.squiffy-link").length).toBe(10);
|
|
99
|
+
const linkToPassage = findLink(element, "passage", "a link to a passage");
|
|
100
|
+
const section3Link = findLink(element, "section", "section 3");
|
|
99
101
|
|
|
100
102
|
expect(linkToPassage).not.toBeNull();
|
|
101
103
|
expect(section3Link).not.toBeNull();
|
|
102
|
-
expect(linkToPassage.classList).not.toContain(
|
|
104
|
+
expect(linkToPassage.classList).not.toContain("disabled");
|
|
103
105
|
|
|
104
106
|
const handler = vi.fn();
|
|
105
|
-
const off = squiffyApi.on(
|
|
107
|
+
const off = squiffyApi.on("linkClick", handler);
|
|
106
108
|
|
|
107
|
-
const handled = squiffyApi.clickLink(section3Link);
|
|
109
|
+
const handled = await squiffyApi.clickLink(section3Link);
|
|
108
110
|
expect(handled).toBe(true);
|
|
109
111
|
|
|
110
112
|
expect(element.innerHTML).toMatchSnapshot();
|
|
111
113
|
|
|
112
114
|
// passage link is from the previous section, so should be unclickable
|
|
113
|
-
expect(squiffyApi.clickLink(linkToPassage)).toBe(false);
|
|
115
|
+
expect(await squiffyApi.clickLink(linkToPassage)).toBe(false);
|
|
114
116
|
|
|
115
117
|
// await for the event to be processed
|
|
116
118
|
await Promise.resolve();
|
|
117
119
|
|
|
118
120
|
expect(handler).toHaveBeenCalledTimes(1);
|
|
119
121
|
expect(handler).toHaveBeenCalledWith(
|
|
120
|
-
expect.objectContaining({ linkType:
|
|
122
|
+
expect.objectContaining({ linkType: "section" })
|
|
121
123
|
);
|
|
122
124
|
off();
|
|
123
125
|
});
|
|
124
126
|
|
|
125
|
-
test(
|
|
126
|
-
const script = await fs.readFile(
|
|
127
|
+
test("Click a section link and go back", async () => {
|
|
128
|
+
const script = await fs.readFile("../examples/test/example.squiffy", "utf-8");
|
|
129
|
+
const { squiffyApi, element } = await initScript(script);
|
|
130
|
+
|
|
131
|
+
const linkToPassage = findLink(element, "passage", "a link to a passage");
|
|
132
|
+
const section3Link = findLink(element, "section", "section 3");
|
|
133
|
+
expect(section3Link).not.toBeNull();
|
|
134
|
+
|
|
135
|
+
await squiffyApi.clickLink(section3Link);
|
|
136
|
+
|
|
137
|
+
// passage link is from the previous section, so should be unclickable
|
|
138
|
+
expect(await squiffyApi.clickLink(linkToPassage)).toBe(false);
|
|
139
|
+
|
|
140
|
+
// now go back
|
|
141
|
+
squiffyApi.goBack();
|
|
142
|
+
|
|
143
|
+
expect(element.innerHTML).toMatchSnapshot();
|
|
144
|
+
|
|
145
|
+
// passage link should be clickable now
|
|
146
|
+
expect(await squiffyApi.clickLink(linkToPassage)).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("Click a passage link", async () => {
|
|
150
|
+
const script = await fs.readFile("../examples/test/example.squiffy", "utf-8");
|
|
127
151
|
const { squiffyApi, element } = await initScript(script);
|
|
128
152
|
expect(element.innerHTML).toMatchSnapshot();
|
|
129
153
|
|
|
130
|
-
expect(element.querySelectorAll(
|
|
131
|
-
const linkToPassage = findLink(element,
|
|
132
|
-
const section3Link = findLink(element,
|
|
154
|
+
expect(element.querySelectorAll("a.squiffy-link").length).toBe(10);
|
|
155
|
+
const linkToPassage = findLink(element, "passage", "a link to a passage");
|
|
156
|
+
const section3Link = findLink(element, "section", "section 3");
|
|
133
157
|
|
|
134
158
|
expect(linkToPassage).not.toBeNull();
|
|
135
159
|
expect(section3Link).not.toBeNull();
|
|
136
|
-
expect(linkToPassage.classList).not.toContain(
|
|
160
|
+
expect(linkToPassage.classList).not.toContain("disabled");
|
|
137
161
|
|
|
138
162
|
const handler = vi.fn();
|
|
139
|
-
const off = squiffyApi.on(
|
|
163
|
+
const off = squiffyApi.on("linkClick", handler);
|
|
140
164
|
|
|
141
|
-
const handled = squiffyApi.clickLink(linkToPassage);
|
|
165
|
+
const handled = await squiffyApi.clickLink(linkToPassage);
|
|
142
166
|
expect(handled).toBe(true);
|
|
143
167
|
|
|
144
|
-
expect(linkToPassage.classList).toContain(
|
|
168
|
+
expect(linkToPassage.classList).toContain("disabled");
|
|
145
169
|
expect(element.innerHTML).toMatchSnapshot();
|
|
146
170
|
|
|
147
171
|
// shouldn't be able to click it again
|
|
148
|
-
expect(squiffyApi.clickLink(linkToPassage)).toBe(false);
|
|
172
|
+
expect(await squiffyApi.clickLink(linkToPassage)).toBe(false);
|
|
149
173
|
|
|
150
174
|
// await for the event to be processed
|
|
151
175
|
await Promise.resolve();
|
|
152
176
|
|
|
153
177
|
expect(handler).toHaveBeenCalledTimes(1);
|
|
154
178
|
expect(handler).toHaveBeenCalledWith(
|
|
155
|
-
expect.objectContaining({ linkType:
|
|
179
|
+
expect.objectContaining({ linkType: "passage" })
|
|
156
180
|
);
|
|
157
181
|
off();
|
|
158
182
|
});
|
|
159
183
|
|
|
160
|
-
test(
|
|
184
|
+
test("Click a passage link and go back", async () => {
|
|
185
|
+
const script = await fs.readFile("../examples/test/example.squiffy", "utf-8");
|
|
186
|
+
const { squiffyApi, element } = await initScript(script);
|
|
187
|
+
|
|
188
|
+
const linkToPassage = findLink(element, "passage", "a link to a passage");
|
|
189
|
+
|
|
190
|
+
await squiffyApi.clickLink(linkToPassage);
|
|
191
|
+
|
|
192
|
+
// the passage link was clicked, so should be disabled
|
|
193
|
+
expect(linkToPassage.classList).toContain("disabled");
|
|
194
|
+
|
|
195
|
+
// now go back
|
|
196
|
+
squiffyApi.goBack();
|
|
197
|
+
|
|
198
|
+
expect(element.innerHTML).toMatchSnapshot();
|
|
199
|
+
|
|
200
|
+
// passage link should be clickable now
|
|
201
|
+
expect(await squiffyApi.clickLink(linkToPassage)).toBe(true);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test("Run JavaScript functions", async () => {
|
|
161
205
|
const script = `
|
|
162
206
|
document.getElementById('test').innerText = 'Initial JavaScript';
|
|
163
207
|
@set some_string = some_value
|
|
@@ -180,32 +224,33 @@ test('Run JavaScript functions', async () => {
|
|
|
180
224
|
document.getElementById('test').innerText = "In other section";
|
|
181
225
|
`;
|
|
182
226
|
|
|
183
|
-
const clickContinue = () => {
|
|
184
|
-
const continueLink = findLink(element,
|
|
227
|
+
const clickContinue = async () => {
|
|
228
|
+
const continueLink = findLink(element, "section", "Continue...", true);
|
|
185
229
|
expect(continueLink).not.toBeNull();
|
|
186
|
-
|
|
230
|
+
expect(continueLink).not.toBeUndefined();
|
|
231
|
+
const handled = await squiffyApi.clickLink(continueLink);
|
|
187
232
|
expect(handled).toBe(true);
|
|
188
233
|
};
|
|
189
234
|
|
|
190
235
|
const { squiffyApi, element } = await initScript(script);
|
|
191
236
|
|
|
192
|
-
expect(getTestOutput()).toBe(
|
|
193
|
-
clickContinue();
|
|
237
|
+
expect(getTestOutput()).toBe("Initial JavaScript");
|
|
238
|
+
await clickContinue();
|
|
194
239
|
|
|
195
|
-
expect(getTestOutput()).toBe(
|
|
196
|
-
clickContinue();
|
|
240
|
+
expect(getTestOutput()).toBe("Value: 5");
|
|
241
|
+
await clickContinue();
|
|
197
242
|
|
|
198
|
-
expect(getTestOutput()).toBe(
|
|
199
|
-
clickContinue();
|
|
243
|
+
expect(getTestOutput()).toBe("Value: some_value");
|
|
244
|
+
await clickContinue();
|
|
200
245
|
|
|
201
|
-
expect(getTestOutput()).toBe(
|
|
246
|
+
expect(getTestOutput()).toBe("Value: 10");
|
|
202
247
|
|
|
203
|
-
clickContinue();
|
|
204
|
-
clickContinue();
|
|
205
|
-
expect(getTestOutput()).toBe(
|
|
248
|
+
await clickContinue();
|
|
249
|
+
await clickContinue();
|
|
250
|
+
expect(getTestOutput()).toBe("Value: 11");
|
|
206
251
|
|
|
207
|
-
clickContinue();
|
|
208
|
-
expect(getTestOutput()).toBe(
|
|
252
|
+
await clickContinue();
|
|
253
|
+
expect(getTestOutput()).toBe("In other section");
|
|
209
254
|
});
|
|
210
255
|
|
|
211
256
|
function safeQuerySelector(name: string) {
|
|
@@ -220,33 +265,33 @@ function getPassageContent(element: HTMLElement, section: string, passage: strin
|
|
|
220
265
|
return element.querySelector(`[data-source='[[${safeQuerySelector(section)}]][${safeQuerySelector(passage)}]']`)?.textContent || null;
|
|
221
266
|
}
|
|
222
267
|
|
|
223
|
-
test(
|
|
268
|
+
test("Update default section output", async () => {
|
|
224
269
|
const { squiffyApi, element } = await initScript("Hello world");
|
|
225
|
-
let defaultOutput = getSectionContent(element,
|
|
226
|
-
expect(defaultOutput).toBe(
|
|
270
|
+
let defaultOutput = getSectionContent(element, "_default");
|
|
271
|
+
expect(defaultOutput).toBe("Hello world");
|
|
227
272
|
expect(element.innerHTML).toMatchSnapshot();
|
|
228
273
|
|
|
229
274
|
const updated = await compile("Updated content");
|
|
230
275
|
squiffyApi.update(updated.story);
|
|
231
|
-
defaultOutput = getSectionContent(element,
|
|
232
|
-
expect(defaultOutput).toBe(
|
|
276
|
+
defaultOutput = getSectionContent(element, "_default");
|
|
277
|
+
expect(defaultOutput).toBe("Updated content");
|
|
233
278
|
expect(element.innerHTML).toMatchSnapshot();
|
|
234
279
|
});
|
|
235
280
|
|
|
236
|
-
test.each([
|
|
281
|
+
test.each(["a", "a'1"])('Update passage output - passage name "%s"', async (name) => {
|
|
237
282
|
const { squiffyApi, element } = await initScript(`Click this: [${name}]
|
|
238
283
|
|
|
239
284
|
[${name}]:
|
|
240
285
|
Passage a content`);
|
|
241
286
|
|
|
242
|
-
const link = findLink(element,
|
|
243
|
-
const handled = squiffyApi.clickLink(link);
|
|
287
|
+
const link = findLink(element, "passage", name);
|
|
288
|
+
const handled = await squiffyApi.clickLink(link);
|
|
244
289
|
expect(handled).toBe(true);
|
|
245
290
|
|
|
246
|
-
let defaultOutput = getSectionContent(element,
|
|
291
|
+
let defaultOutput = getSectionContent(element, "_default");
|
|
247
292
|
expect(defaultOutput).toBe(`Click this: ${name}`);
|
|
248
|
-
let passageOutput = getPassageContent(element,
|
|
249
|
-
expect(passageOutput).toBe(
|
|
293
|
+
let passageOutput = getPassageContent(element, "_default", name);
|
|
294
|
+
expect(passageOutput).toBe("Passage a content");
|
|
250
295
|
expect(element.innerHTML).toMatchSnapshot();
|
|
251
296
|
|
|
252
297
|
const updated = await compile(`Click this: [${name}]
|
|
@@ -256,71 +301,71 @@ Updated passage content`);
|
|
|
256
301
|
|
|
257
302
|
squiffyApi.update(updated.story);
|
|
258
303
|
|
|
259
|
-
defaultOutput = getSectionContent(element,
|
|
304
|
+
defaultOutput = getSectionContent(element, "_default");
|
|
260
305
|
expect(defaultOutput).toBe(`Click this: ${name}`);
|
|
261
306
|
|
|
262
|
-
passageOutput = getPassageContent(element,
|
|
263
|
-
expect(passageOutput).toBe(
|
|
307
|
+
passageOutput = getPassageContent(element, "_default", name);
|
|
308
|
+
expect(passageOutput).toBe("Updated passage content");
|
|
264
309
|
expect(element.innerHTML).toMatchSnapshot();
|
|
265
310
|
});
|
|
266
311
|
|
|
267
|
-
test(
|
|
312
|
+
test("Delete section", async () => {
|
|
268
313
|
const { squiffyApi, element } = await initScript(`Click this: [[a]]
|
|
269
314
|
|
|
270
315
|
[[a]]:
|
|
271
316
|
New section`);
|
|
272
317
|
|
|
273
|
-
const link = findLink(element,
|
|
274
|
-
const handled = squiffyApi.clickLink(link);
|
|
318
|
+
const link = findLink(element, "section", "a");
|
|
319
|
+
const handled = await squiffyApi.clickLink(link);
|
|
275
320
|
expect(handled).toBe(true);
|
|
276
321
|
|
|
277
|
-
let defaultOutput = getSectionContent(element,
|
|
278
|
-
expect(defaultOutput).toBe(
|
|
279
|
-
let sectionOutput = getSectionContent(element,
|
|
280
|
-
expect(sectionOutput).toBe(
|
|
322
|
+
let defaultOutput = getSectionContent(element, "_default");
|
|
323
|
+
expect(defaultOutput).toBe("Click this: a");
|
|
324
|
+
let sectionOutput = getSectionContent(element, "a");
|
|
325
|
+
expect(sectionOutput).toBe("New section");
|
|
281
326
|
expect(element.innerHTML).toMatchSnapshot();
|
|
282
327
|
|
|
283
|
-
const updated = await compile(
|
|
328
|
+
const updated = await compile("Click this: [[a]]");
|
|
284
329
|
|
|
285
330
|
squiffyApi.update(updated.story);
|
|
286
331
|
|
|
287
|
-
defaultOutput = getSectionContent(element,
|
|
288
|
-
expect(defaultOutput).toBe(
|
|
289
|
-
sectionOutput = getSectionContent(element,
|
|
332
|
+
defaultOutput = getSectionContent(element, "_default");
|
|
333
|
+
expect(defaultOutput).toBe("Click this: a");
|
|
334
|
+
sectionOutput = getSectionContent(element, "a");
|
|
290
335
|
expect(sectionOutput).toBeNull();
|
|
291
336
|
|
|
292
337
|
expect(element.innerHTML).toMatchSnapshot();
|
|
293
338
|
});
|
|
294
339
|
|
|
295
|
-
test(
|
|
340
|
+
test("Delete passage", async () => {
|
|
296
341
|
const { squiffyApi, element } = await initScript(`Click this: [a]
|
|
297
342
|
|
|
298
343
|
[a]:
|
|
299
344
|
New passage`);
|
|
300
345
|
|
|
301
|
-
const link = findLink(element,
|
|
302
|
-
const handled = squiffyApi.clickLink(link);
|
|
346
|
+
const link = findLink(element, "passage", "a");
|
|
347
|
+
const handled = await squiffyApi.clickLink(link);
|
|
303
348
|
expect(handled).toBe(true);
|
|
304
349
|
|
|
305
|
-
let defaultOutput = getSectionContent(element,
|
|
306
|
-
expect(defaultOutput).toBe(
|
|
307
|
-
let passageOutput = getPassageContent(element,
|
|
308
|
-
expect(passageOutput).toBe(
|
|
350
|
+
let defaultOutput = getSectionContent(element, "_default");
|
|
351
|
+
expect(defaultOutput).toBe("Click this: a");
|
|
352
|
+
let passageOutput = getPassageContent(element, "_default", "a");
|
|
353
|
+
expect(passageOutput).toBe("New passage");
|
|
309
354
|
expect(element.innerHTML).toMatchSnapshot();
|
|
310
355
|
|
|
311
|
-
const updated = await compile(
|
|
356
|
+
const updated = await compile("Click this: [a]");
|
|
312
357
|
|
|
313
358
|
squiffyApi.update(updated.story);
|
|
314
359
|
|
|
315
|
-
defaultOutput = getSectionContent(element,
|
|
316
|
-
expect(defaultOutput).toBe(
|
|
317
|
-
passageOutput = getPassageContent(element,
|
|
360
|
+
defaultOutput = getSectionContent(element, "_default");
|
|
361
|
+
expect(defaultOutput).toBe("Click this: a");
|
|
362
|
+
passageOutput = getPassageContent(element, "_default", "a");
|
|
318
363
|
expect(passageOutput).toBeNull();
|
|
319
364
|
|
|
320
365
|
expect(element.innerHTML).toMatchSnapshot();
|
|
321
366
|
});
|
|
322
367
|
|
|
323
|
-
test(
|
|
368
|
+
test("Clicked passage links remain disabled after an update", async () => {
|
|
324
369
|
const { squiffyApi, element } = await initScript(`Click one of these: [a] [b]
|
|
325
370
|
|
|
326
371
|
[a]:
|
|
@@ -331,9 +376,9 @@ Output for passage B.`);
|
|
|
331
376
|
|
|
332
377
|
// click linkA
|
|
333
378
|
|
|
334
|
-
let linkA = findLink(element,
|
|
335
|
-
expect(linkA.classList).not.toContain(
|
|
336
|
-
expect(squiffyApi.clickLink(linkA)).toBe(true);
|
|
379
|
+
let linkA = findLink(element, "passage", "a");
|
|
380
|
+
expect(linkA.classList).not.toContain("disabled");
|
|
381
|
+
expect(await squiffyApi.clickLink(linkA)).toBe(true);
|
|
337
382
|
|
|
338
383
|
const updated = await compile(`Click one of these (updated): [a] [b]
|
|
339
384
|
|
|
@@ -347,18 +392,18 @@ Output for passage B.`);
|
|
|
347
392
|
|
|
348
393
|
// linkA should still be disabled
|
|
349
394
|
|
|
350
|
-
linkA = findLink(element,
|
|
351
|
-
expect(linkA.classList).toContain(
|
|
352
|
-
expect(squiffyApi.clickLink(linkA)).toBe(false);
|
|
395
|
+
linkA = findLink(element, "passage", "a");
|
|
396
|
+
expect(linkA.classList).toContain("disabled");
|
|
397
|
+
expect(await squiffyApi.clickLink(linkA)).toBe(false);
|
|
353
398
|
|
|
354
399
|
// linkB should still be enabled
|
|
355
400
|
|
|
356
|
-
|
|
357
|
-
expect(linkB.classList).not.toContain(
|
|
358
|
-
expect(squiffyApi.clickLink(linkB)).toBe(true);
|
|
401
|
+
const linkB = findLink(element, "passage", "b");
|
|
402
|
+
expect(linkB.classList).not.toContain("disabled");
|
|
403
|
+
expect(await squiffyApi.clickLink(linkB)).toBe(true);
|
|
359
404
|
});
|
|
360
405
|
|
|
361
|
-
test(
|
|
406
|
+
test("Deleting the current section activates the previous section", async () => {
|
|
362
407
|
const { squiffyApi, element } = await initScript(`Choose a section: [[a]] [[b]], or passage [start1].
|
|
363
408
|
|
|
364
409
|
[start1]:
|
|
@@ -372,17 +417,17 @@ Output for section B.`);
|
|
|
372
417
|
|
|
373
418
|
// click linkA
|
|
374
419
|
|
|
375
|
-
|
|
376
|
-
let linkB = findLink(element,
|
|
377
|
-
expect(linkA.classList).not.toContain(
|
|
378
|
-
expect(squiffyApi.clickLink(linkA)).toBe(true);
|
|
420
|
+
const linkA = findLink(element, "section", "a");
|
|
421
|
+
let linkB = findLink(element, "section", "b");
|
|
422
|
+
expect(linkA.classList).not.toContain("disabled");
|
|
423
|
+
expect(await squiffyApi.clickLink(linkA)).toBe(true);
|
|
379
424
|
|
|
380
425
|
// can't click start1 passage as we're in section [[a]] now
|
|
381
|
-
let linkStart1 = findLink(element,
|
|
382
|
-
expect(squiffyApi.clickLink(linkStart1)).toBe(false);
|
|
426
|
+
let linkStart1 = findLink(element, "passage", "start1");
|
|
427
|
+
expect(await squiffyApi.clickLink(linkStart1)).toBe(false);
|
|
383
428
|
|
|
384
429
|
// can't click linkB as we're in section [[a]] now
|
|
385
|
-
expect(squiffyApi.clickLink(linkB)).toBe(false);
|
|
430
|
+
expect(await squiffyApi.clickLink(linkB)).toBe(false);
|
|
386
431
|
|
|
387
432
|
// now we delete section [[a]]
|
|
388
433
|
|
|
@@ -400,22 +445,22 @@ Passage in section B.`);
|
|
|
400
445
|
squiffyApi.update(updated.story);
|
|
401
446
|
|
|
402
447
|
// We're in the first section, so the start1 passage should be clickable now
|
|
403
|
-
linkStart1 = findLink(element,
|
|
404
|
-
expect(squiffyApi.clickLink(linkStart1)).toBe(true);
|
|
448
|
+
linkStart1 = findLink(element, "passage", "start1");
|
|
449
|
+
expect(await squiffyApi.clickLink(linkStart1)).toBe(true);
|
|
405
450
|
|
|
406
451
|
// We're in the first section, so linkB should be clickable now
|
|
407
|
-
linkB = findLink(element,
|
|
408
|
-
expect(squiffyApi.clickLink(linkB)).toBe(true);
|
|
452
|
+
linkB = findLink(element, "section", "b");
|
|
453
|
+
expect(await squiffyApi.clickLink(linkB)).toBe(true);
|
|
409
454
|
|
|
410
455
|
// and the passage [b1] within it should be clickable
|
|
411
|
-
const linkB1 = findLink(element,
|
|
412
|
-
expect(squiffyApi.clickLink(linkB1)).toBe(true);
|
|
456
|
+
const linkB1 = findLink(element, "passage", "b1");
|
|
457
|
+
expect(await squiffyApi.clickLink(linkB1)).toBe(true);
|
|
413
458
|
});
|
|
414
459
|
|
|
415
|
-
test(
|
|
460
|
+
test("Embed text from a section", async () => {
|
|
416
461
|
const script = `
|
|
417
462
|
[[section1]]:
|
|
418
|
-
Here is some text from the next section: {section2}
|
|
463
|
+
Here is some text from the next section: {{embed "section2"}}
|
|
419
464
|
|
|
420
465
|
[[section2]]:
|
|
421
466
|
Text from next section.
|
|
@@ -423,14 +468,14 @@ Text from next section.
|
|
|
423
468
|
|
|
424
469
|
const { element } = await initScript(script);
|
|
425
470
|
|
|
426
|
-
|
|
427
|
-
expect(output).toBe(
|
|
471
|
+
const output = getSectionContent(element, "section1");
|
|
472
|
+
expect(output).toBe("Here is some text from the next section: Text from next section.");
|
|
428
473
|
});
|
|
429
474
|
|
|
430
|
-
test(
|
|
475
|
+
test("Embed text from a passage", async () => {
|
|
431
476
|
const script = `
|
|
432
477
|
[[section1]]:
|
|
433
|
-
Here is some text from a passage: {passage}
|
|
478
|
+
Here is some text from a passage: {{embed "passage"}}
|
|
434
479
|
|
|
435
480
|
[passage]:
|
|
436
481
|
Text from a passage.
|
|
@@ -438,14 +483,14 @@ Text from a passage.
|
|
|
438
483
|
|
|
439
484
|
const { element } = await initScript(script);
|
|
440
485
|
|
|
441
|
-
|
|
442
|
-
expect(output).toBe(
|
|
486
|
+
const output = getSectionContent(element, "section1");
|
|
487
|
+
expect(output).toBe("Here is some text from a passage: Text from a passage.");
|
|
443
488
|
});
|
|
444
489
|
|
|
445
|
-
test(
|
|
490
|
+
test("Update section with embedded text", async () => {
|
|
446
491
|
const script = `
|
|
447
492
|
[[section1]]:
|
|
448
|
-
Here is some text from the next section: {section2}
|
|
493
|
+
Here is some text from the next section: {{embed "section2"}}
|
|
449
494
|
|
|
450
495
|
[[section2]]:
|
|
451
496
|
Text from next section.
|
|
@@ -453,12 +498,12 @@ Text from next section.
|
|
|
453
498
|
|
|
454
499
|
const { squiffyApi, element } = await initScript(script);
|
|
455
500
|
|
|
456
|
-
let output = getSectionContent(element,
|
|
457
|
-
expect(output).toBe(
|
|
501
|
+
let output = getSectionContent(element, "section1");
|
|
502
|
+
expect(output).toBe("Here is some text from the next section: Text from next section.");
|
|
458
503
|
|
|
459
504
|
const script2 = `
|
|
460
505
|
[[section1]]:
|
|
461
|
-
Here is an updated script with text from the next section: {section2}
|
|
506
|
+
Here is an updated script with text from the next section: {{embed "section2"}}
|
|
462
507
|
|
|
463
508
|
[[section2]]:
|
|
464
509
|
Updated text from next section.
|
|
@@ -466,17 +511,17 @@ Updated text from next section.
|
|
|
466
511
|
|
|
467
512
|
const updated = await compile(script2);
|
|
468
513
|
squiffyApi.update(updated.story);
|
|
469
|
-
output = getSectionContent(element,
|
|
514
|
+
output = getSectionContent(element, "section1");
|
|
470
515
|
|
|
471
516
|
// NOTE: The embedded text does not currently get updated. We would need to track where the embedded
|
|
472
517
|
// text has been written.
|
|
473
|
-
expect(output).toBe(
|
|
518
|
+
expect(output).toBe("Here is an updated script with text from the next section: Text from next section.");
|
|
474
519
|
});
|
|
475
520
|
|
|
476
|
-
test(
|
|
521
|
+
test("Update passage with embedded text", async () => {
|
|
477
522
|
const script = `
|
|
478
523
|
[[section1]]:
|
|
479
|
-
Here is some text from a passage: {passage}
|
|
524
|
+
Here is some text from a passage: {{embed "passage"}}
|
|
480
525
|
|
|
481
526
|
[passage]:
|
|
482
527
|
Text from a passage.
|
|
@@ -484,12 +529,12 @@ Text from a passage.
|
|
|
484
529
|
|
|
485
530
|
const { squiffyApi, element } = await initScript(script);
|
|
486
531
|
|
|
487
|
-
let output = getSectionContent(element,
|
|
488
|
-
expect(output).toBe(
|
|
532
|
+
let output = getSectionContent(element, "section1");
|
|
533
|
+
expect(output).toBe("Here is some text from a passage: Text from a passage.");
|
|
489
534
|
|
|
490
535
|
const script2 = `
|
|
491
536
|
[[section1]]:
|
|
492
|
-
Here is an updated script with text from a passage: {passage}
|
|
537
|
+
Here is an updated script with text from a passage: {{embed "passage"}}
|
|
493
538
|
|
|
494
539
|
[passage]:
|
|
495
540
|
Updated text from a passage.
|
|
@@ -497,9 +542,136 @@ Updated text from a passage.
|
|
|
497
542
|
|
|
498
543
|
const updated = await compile(script2);
|
|
499
544
|
squiffyApi.update(updated.story);
|
|
500
|
-
output = getSectionContent(element,
|
|
545
|
+
output = getSectionContent(element, "section1");
|
|
501
546
|
|
|
502
547
|
// NOTE: The embedded text does not currently get updated. We would need to track where the embedded
|
|
503
548
|
// text has been written.
|
|
504
|
-
expect(output).toBe(
|
|
549
|
+
expect(output).toBe("Here is an updated script with text from a passage: Text from a passage.");
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
test("Clear entire script, then update", async () => {
|
|
553
|
+
const script = "Original content";
|
|
554
|
+
|
|
555
|
+
const { squiffyApi, element } = await initScript(script);
|
|
556
|
+
|
|
557
|
+
let output = getSectionContent(element, "_default");
|
|
558
|
+
expect(output).toBe("Original content");
|
|
559
|
+
|
|
560
|
+
const script2 = "";
|
|
561
|
+
const update2 = await compile(script2);
|
|
562
|
+
squiffyApi.update(update2.story);
|
|
563
|
+
output = getSectionContent(element, "_default");
|
|
564
|
+
expect(output).toBeNull();
|
|
565
|
+
|
|
566
|
+
const script3 = "New content";
|
|
567
|
+
const update3 = await compile(script3);
|
|
568
|
+
squiffyApi.update(update3.story);
|
|
569
|
+
output = getSectionContent(element, "_default");
|
|
570
|
+
expect(output).toBe("New content");
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
test("Changing the start section", async () => {
|
|
574
|
+
const script = "Original content in default section";
|
|
575
|
+
|
|
576
|
+
const { squiffyApi, element } = await initScript(script);
|
|
577
|
+
|
|
578
|
+
let output = getSectionContent(element, "_default");
|
|
579
|
+
expect(output).toBe("Original content in default section");
|
|
580
|
+
|
|
581
|
+
const script2 = `[[new]]:
|
|
582
|
+
This is the new start section`;
|
|
583
|
+
const update2 = await compile(script2);
|
|
584
|
+
squiffyApi.update(update2.story);
|
|
585
|
+
output = getSectionContent(element, "new");
|
|
586
|
+
expect(output).toBe("This is the new start section");
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
test("Going back handling @clear and attribute changes", async () => {
|
|
590
|
+
const script = `
|
|
591
|
+
Choose: [a], [b]
|
|
592
|
+
|
|
593
|
+
[a]:
|
|
594
|
+
@set test = 123
|
|
595
|
+
You chose a. Now [[continue]]
|
|
596
|
+
|
|
597
|
+
[b]:
|
|
598
|
+
@set test = 456
|
|
599
|
+
You chose b. Now [[continue]]
|
|
600
|
+
|
|
601
|
+
[[continue]]:
|
|
602
|
+
@set test = 789
|
|
603
|
+
Now choose: [c], [d]
|
|
604
|
+
|
|
605
|
+
[c]:
|
|
606
|
+
@clear
|
|
607
|
+
@set test = 321
|
|
608
|
+
You chose c. Now [[finish]]
|
|
609
|
+
|
|
610
|
+
[d]:
|
|
611
|
+
You chose d. Now [[finish]]
|
|
612
|
+
|
|
613
|
+
[[finish]]:
|
|
614
|
+
Done.
|
|
615
|
+
`;
|
|
616
|
+
|
|
617
|
+
const { squiffyApi, element } = await initScript(script);
|
|
618
|
+
|
|
619
|
+
const linkA = findLink(element, "passage", "a");
|
|
620
|
+
|
|
621
|
+
// Click link to "a"
|
|
622
|
+
await squiffyApi.clickLink(linkA);
|
|
623
|
+
|
|
624
|
+
// "a" should be marked as seen
|
|
625
|
+
expect(squiffyApi.get("_seen_sections") as []).toContain("a");
|
|
626
|
+
expect(squiffyApi.get("test")).toBe(123);
|
|
627
|
+
|
|
628
|
+
// Go back
|
|
629
|
+
squiffyApi.goBack();
|
|
630
|
+
|
|
631
|
+
// "a" should not be marked as seen
|
|
632
|
+
expect(squiffyApi.get("_seen_sections") as []).not.toContain("a");
|
|
633
|
+
expect(squiffyApi.get("test")).toBe(null);
|
|
634
|
+
|
|
635
|
+
// Click link to "b", then click link to "continue"
|
|
636
|
+
let linkB = findLink(element, "passage", "b");
|
|
637
|
+
await squiffyApi.clickLink(linkB);
|
|
638
|
+
expect(squiffyApi.get("test")).toBe(456);
|
|
639
|
+
let continueLink = findLink(element, "section", "continue");
|
|
640
|
+
await squiffyApi.clickLink(continueLink);
|
|
641
|
+
|
|
642
|
+
expect(squiffyApi.get("_seen_sections") as []).toContain("b");
|
|
643
|
+
expect(squiffyApi.get("test")).toBe(789);
|
|
644
|
+
|
|
645
|
+
// Go back
|
|
646
|
+
squiffyApi.goBack();
|
|
647
|
+
|
|
648
|
+
// "b" should still be marked as seen, because we didn't go back that far yet
|
|
649
|
+
expect(squiffyApi.get("_seen_sections") as []).toContain("b");
|
|
650
|
+
expect(squiffyApi.get("test")).toBe(456);
|
|
651
|
+
|
|
652
|
+
// Go back
|
|
653
|
+
squiffyApi.goBack();
|
|
654
|
+
|
|
655
|
+
// Now "b" should not be marked as seen
|
|
656
|
+
expect(squiffyApi.get("_seen_sections") as []).not.toContain("b");
|
|
657
|
+
expect(squiffyApi.get("test")).toBe(null);
|
|
658
|
+
|
|
659
|
+
// Click "b" again, then "continue", and "c", which clears the screen
|
|
660
|
+
linkB = findLink(element, "passage", "b");
|
|
661
|
+
await squiffyApi.clickLink(linkB);
|
|
662
|
+
continueLink = findLink(element, "section", "continue");
|
|
663
|
+
await squiffyApi.clickLink(continueLink);
|
|
664
|
+
const linkC = findLink(element, "passage", "c");
|
|
665
|
+
await squiffyApi.clickLink(linkC);
|
|
666
|
+
|
|
667
|
+
// Should match snapshot, where passage "c" is the only thing visible
|
|
668
|
+
expect(element.innerHTML).toMatchSnapshot();
|
|
669
|
+
expect(squiffyApi.get("test")).toBe(321);
|
|
670
|
+
|
|
671
|
+
// Go back
|
|
672
|
+
squiffyApi.goBack();
|
|
673
|
+
|
|
674
|
+
// Should match snapshot, where the previous text is visible again
|
|
675
|
+
expect(element.innerHTML).toMatchSnapshot();
|
|
676
|
+
expect(squiffyApi.get("test")).toBe(789);
|
|
505
677
|
});
|