extwee 2.2.1 → 2.2.3
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/.eslintrc.json +7 -13
- package/.github/codeql-analysis.yml +51 -0
- package/README.md +9 -3
- package/build/extwee +0 -0
- package/build/extwee.web.min.js +1 -1
- package/docs/objects/story.md +1 -2
- package/index.js +2 -0
- package/jest.config.json +5 -0
- package/package.json +24 -21
- package/src/IFID/generate.js +20 -0
- package/src/JSON/parse.js +43 -0
- package/src/Passage.js +52 -3
- package/src/Story.js +266 -107
- package/src/StoryFormat/parse.js +190 -80
- package/src/StoryFormat.js +78 -88
- package/src/TWS/parse.js +2 -2
- package/src/Twee/parse.js +2 -3
- package/src/Twine1HTML/compile.js +2 -0
- package/src/Twine1HTML/parse.js +2 -3
- package/src/Twine2ArchiveHTML/compile.js +8 -0
- package/src/Twine2ArchiveHTML/parse.js +33 -3
- package/src/Twine2HTML/compile.js +31 -6
- package/src/Twine2HTML/parse.js +49 -54
- package/test/IFID/IFID.Generate.test.js +10 -0
- package/test/JSON/JSON.Parse.test.js +4 -4
- package/test/{Passage.test.js → Objects/Passage.test.js} +4 -4
- package/test/{Story.test.js → Objects/Story.test.js} +259 -50
- package/test/{StoryFormat.test.js → Objects/StoryFormat.test.js} +10 -3
- package/test/StoryFormat/StoryFormat.Parse.test.js +442 -55
- package/test/TWS/Parse.test.js +1 -1
- package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Parse.test.js +20 -4
- package/test/Twine2HTML/Twine2HTML.Compile.test.js +35 -120
- package/test/Twine2HTML/Twine2HTML.Parse.test.js +57 -38
- package/test/Twine2HTML/Twine2HTMLCompiler/format.js +9 -0
- package/test/Twine2HTML/Twine2HTMLParser/missingZoom.html +1 -1
- package/types/IFID/generate.d.ts +14 -0
- package/types/JSON/parse.d.ts +51 -0
- package/types/Passage.d.ts +117 -0
- package/types/Story.d.ts +230 -0
- package/types/StoryFormat/parse.d.ts +50 -0
- package/types/StoryFormat.d.ts +121 -0
- package/types/TWS/parse.d.ts +10 -0
- package/types/Twee/parse.d.ts +9 -0
- package/types/Twine1HTML/compile.d.ts +19 -0
- package/types/Twine1HTML/parse.d.ts +9 -0
- package/types/Twine2ArchiveHTML/compile.d.ts +14 -0
- package/types/Twine2ArchiveHTML/parse.d.ts +36 -0
- package/types/Twine2HTML/compile.d.ts +14 -0
- package/types/Twine2HTML/parse.d.ts +20 -0
- package/web-index.js +2 -0
- package/test/StoryFormat/StoryFormatParser/example.js +0 -3
- package/test/StoryFormat/StoryFormatParser/example2.js +0 -3
- package/test/StoryFormat/StoryFormatParser/format.js +0 -1
- package/test/StoryFormat/StoryFormatParser/format_doublename.js +0 -1
- package/test/StoryFormat/StoryFormatParser/harlowe.js +0 -3
- package/test/StoryFormat/StoryFormatParser/missingAuthor.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingDescription.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingImage.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingLicense.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingName.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingProofing.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingSource.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingURL.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingVersion.js +0 -1
- package/test/StoryFormat/StoryFormatParser/versionWrong.js +0 -1
- package/test/Twine2HTML/Twine2HTMLParser/missingName.html +0 -33
- package/test/Twine2HTML/Twine2HTMLParser/missingPID.html +0 -15
- package/test/Twine2HTML/Twine2HTMLParser/missingPassageName.html +0 -15
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Story, creatorName, creatorVersion } from '
|
|
2
|
-
import Passage from '
|
|
3
|
-
import { parse as parseTwee } from '
|
|
1
|
+
import { Story, creatorName, creatorVersion } from '../../src/Story.js';
|
|
2
|
+
import Passage from '../../src/Passage.js';
|
|
3
|
+
import { parse as parseTwee } from '../../src/Twee/parse.js';
|
|
4
4
|
import { readFileSync } from 'node:fs';
|
|
5
5
|
import { parse as HTMLParser } from 'node-html-parser';
|
|
6
|
+
import { generate as generateIFID } from '../../src/IFID/generate.js';
|
|
6
7
|
|
|
7
8
|
// Pull the name and version of this project from package.json.
|
|
8
9
|
// These are used as the 'creator' and 'creator-version'.
|
|
@@ -28,6 +29,11 @@ describe('Story', () => {
|
|
|
28
29
|
s = new Story('Test');
|
|
29
30
|
expect(s.name).toBe('Test');
|
|
30
31
|
});
|
|
32
|
+
|
|
33
|
+
it('Should have default name', () => {
|
|
34
|
+
s = new Story();
|
|
35
|
+
expect(s.name).toBe('Untitled Story');
|
|
36
|
+
});
|
|
31
37
|
});
|
|
32
38
|
|
|
33
39
|
describe('creator', () => {
|
|
@@ -223,6 +229,31 @@ describe('Story', () => {
|
|
|
223
229
|
});
|
|
224
230
|
});
|
|
225
231
|
|
|
232
|
+
describe('passages', () => {
|
|
233
|
+
let s = null;
|
|
234
|
+
|
|
235
|
+
beforeEach(() => {
|
|
236
|
+
s = new Story();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('Set passages to a new array containing at least one Passage', () => {
|
|
240
|
+
s.passages = [new Passage()];
|
|
241
|
+
expect(s.passages.length).toBe(1);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('Should throw error if trying to set to a non-Array type', () => {
|
|
245
|
+
expect(() => {
|
|
246
|
+
s.passages = null;
|
|
247
|
+
}).toThrow();
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('Should throw error if trying to set to an array containing non-Passage types', () => {
|
|
251
|
+
expect(() => {
|
|
252
|
+
s.passages = [null];
|
|
253
|
+
}).toThrow();
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
226
257
|
describe('addPassage()', () => {
|
|
227
258
|
let s = null;
|
|
228
259
|
|
|
@@ -242,14 +273,6 @@ describe('Story', () => {
|
|
|
242
273
|
}).toThrow();
|
|
243
274
|
});
|
|
244
275
|
|
|
245
|
-
it('addPassage() - should prevent passages with same name being added', () => {
|
|
246
|
-
const p = new Passage('A');
|
|
247
|
-
const p2 = new Passage('A');
|
|
248
|
-
s.addPassage(p);
|
|
249
|
-
s.addPassage(p2);
|
|
250
|
-
expect(s.size()).toBe(1);
|
|
251
|
-
});
|
|
252
|
-
|
|
253
276
|
it('addPassage() - should override StoryData: ifid', function () {
|
|
254
277
|
// Generate object.
|
|
255
278
|
const o = {
|
|
@@ -351,30 +374,6 @@ describe('Story', () => {
|
|
|
351
374
|
});
|
|
352
375
|
});
|
|
353
376
|
|
|
354
|
-
describe('forEachPassage()', () => {
|
|
355
|
-
let s = null;
|
|
356
|
-
|
|
357
|
-
beforeEach(() => {
|
|
358
|
-
s = new Story();
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
it('forEachPassage() - should return if non-function', () => {
|
|
362
|
-
s.addPassage(new Passage('A'));
|
|
363
|
-
s.addPassage(new Passage('B'));
|
|
364
|
-
let passageNames = '';
|
|
365
|
-
s.forEachPassage((p) => {
|
|
366
|
-
passageNames += p.name;
|
|
367
|
-
});
|
|
368
|
-
expect(passageNames).toBe('AB');
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
it('forEachPassage() - should throw error if non-function', () => {
|
|
372
|
-
expect(() => {
|
|
373
|
-
s.forEachPassage(null);
|
|
374
|
-
}).toThrow();
|
|
375
|
-
});
|
|
376
|
-
});
|
|
377
|
-
|
|
378
377
|
describe('size()', () => {
|
|
379
378
|
let s = null;
|
|
380
379
|
|
|
@@ -400,7 +399,7 @@ describe('Story', () => {
|
|
|
400
399
|
const s = new Story();
|
|
401
400
|
// Convert to string and then back to object.
|
|
402
401
|
const result = JSON.parse(s.toJSON());
|
|
403
|
-
expect(result.name).toBe('');
|
|
402
|
+
expect(result.name).toBe('Untitled Story');
|
|
404
403
|
expect(Object.keys(result.tagColors).length).toBe(0);
|
|
405
404
|
expect(result.ifid).toBe('');
|
|
406
405
|
expect(result.start).toBe('');
|
|
@@ -408,7 +407,7 @@ describe('Story', () => {
|
|
|
408
407
|
expect(result.format).toBe('');
|
|
409
408
|
expect(result.creator).toBe(creatorName);
|
|
410
409
|
expect(result.creatorVersion).toBe(creatorVersion);
|
|
411
|
-
expect(result.zoom).toBe(
|
|
410
|
+
expect(result.zoom).toBe(1);
|
|
412
411
|
expect(Object.keys(result.metadata).length).toBe(0);
|
|
413
412
|
});
|
|
414
413
|
|
|
@@ -431,10 +430,81 @@ describe('Story', () => {
|
|
|
431
430
|
s = new Story();
|
|
432
431
|
});
|
|
433
432
|
|
|
433
|
+
it('Should not generate format if empty', function () {
|
|
434
|
+
// Add one passage.
|
|
435
|
+
s.addPassage(new Passage('Start', 'Content'));
|
|
436
|
+
|
|
437
|
+
// Add an IFID (to prevent warning)
|
|
438
|
+
s.IFID = generateIFID();
|
|
439
|
+
|
|
440
|
+
// Set format to empty string.
|
|
441
|
+
s.format = '';
|
|
442
|
+
|
|
443
|
+
// Convert to Twee.
|
|
444
|
+
const t = s.toTwee();
|
|
445
|
+
|
|
446
|
+
// Test for format in metadata, should not exist.
|
|
447
|
+
expect(t.includes('"\'format":')).not.toBe(true);
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
it('Should not generate formatVersion if empty', function () {
|
|
451
|
+
// Add one passage.
|
|
452
|
+
s.addPassage(new Passage('Start', 'Content'));
|
|
453
|
+
|
|
454
|
+
// Add an IFID (to prevent warning)
|
|
455
|
+
s.IFID = generateIFID();
|
|
456
|
+
|
|
457
|
+
// Set formatVersion to empty string.
|
|
458
|
+
s.formatVersion = '';
|
|
459
|
+
|
|
460
|
+
// Convert to Twee.
|
|
461
|
+
const t = s.toTwee();
|
|
462
|
+
|
|
463
|
+
// Test for formatVersion in metadata, should not exist.
|
|
464
|
+
expect(t.includes('"\'format-version":')).not.toBe(true);
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
it('Should not generate zoom if zero', function () {
|
|
468
|
+
// Add one passage.
|
|
469
|
+
s.addPassage(new Passage('Start', 'Content'));
|
|
470
|
+
|
|
471
|
+
// Add an IFID (to prevent warning)
|
|
472
|
+
s.IFID = generateIFID();
|
|
473
|
+
|
|
474
|
+
// Set zoom to 0.
|
|
475
|
+
s.zoom = 0;
|
|
476
|
+
|
|
477
|
+
// Convert to Twee.
|
|
478
|
+
const t = s.toTwee();
|
|
479
|
+
|
|
480
|
+
// Test for zoom in metadata, should not exist.
|
|
481
|
+
expect(t.includes('"\'zoom":')).not.toBe(true);
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
it('Should not generate start if empty', function () {
|
|
485
|
+
// Add one passage.
|
|
486
|
+
s.addPassage(new Passage('Start', 'Content'));
|
|
487
|
+
|
|
488
|
+
// Add an IFID (to prevent warning)
|
|
489
|
+
s.IFID = generateIFID();
|
|
490
|
+
|
|
491
|
+
// Set start to empty string.
|
|
492
|
+
s.start = '';
|
|
493
|
+
|
|
494
|
+
// Convert to Twee.
|
|
495
|
+
const t = s.toTwee();
|
|
496
|
+
|
|
497
|
+
// Test for start in metadata, should not exist.
|
|
498
|
+
expect(t.includes('"\'start":')).not.toBe(true);
|
|
499
|
+
});
|
|
500
|
+
|
|
434
501
|
it('Should detect StoryTitle text', function () {
|
|
435
502
|
// Add one passage.
|
|
436
503
|
s.addPassage(new Passage('StoryTitle', 'Content'));
|
|
437
504
|
|
|
505
|
+
// Add an IFID (to prevent warning)
|
|
506
|
+
s.IFID = generateIFID();
|
|
507
|
+
|
|
438
508
|
// Convert to Twee.
|
|
439
509
|
const t = s.toTwee();
|
|
440
510
|
|
|
@@ -473,6 +543,7 @@ describe('Story', () => {
|
|
|
473
543
|
s.formatVersion = '1.2.3';
|
|
474
544
|
s.zoom = 1;
|
|
475
545
|
s.start = 'Untitled';
|
|
546
|
+
s.IFID = 'DE7DF8AD-E4CD-499E-A4E7-C5B98B73449A';
|
|
476
547
|
|
|
477
548
|
// Convert to Twee.
|
|
478
549
|
const t = s.toTwee();
|
|
@@ -485,6 +556,7 @@ describe('Story', () => {
|
|
|
485
556
|
expect(story2.format).toBe('Test');
|
|
486
557
|
expect(story2.zoom).toBe(1);
|
|
487
558
|
expect(story2.start).toBe('Untitled');
|
|
559
|
+
expect(story2.IFID).toBe('DE7DF8AD-E4CD-499E-A4E7-C5B98B73449A');
|
|
488
560
|
});
|
|
489
561
|
|
|
490
562
|
it('Should write tag colors', () => {
|
|
@@ -492,6 +564,8 @@ describe('Story', () => {
|
|
|
492
564
|
s.addPassage(new Passage('Start', 'Content'));
|
|
493
565
|
s.addPassage(new Passage('Untitled', 'Some stuff'));
|
|
494
566
|
|
|
567
|
+
s.IFID = 'DE7DF8AD-E4CD-499E-A4E7-C5B98B73449A';
|
|
568
|
+
|
|
495
569
|
// Add tag colors.
|
|
496
570
|
s.tagColors = {
|
|
497
571
|
bar: 'green',
|
|
@@ -516,6 +590,9 @@ describe('Story', () => {
|
|
|
516
590
|
s.addPassage(new Passage('Test', 'Test', ['script']));
|
|
517
591
|
s.addPassage(new Passage('Start', 'Content'));
|
|
518
592
|
|
|
593
|
+
// Set IFID.
|
|
594
|
+
s.IFID = 'DE7DF8AD-E4CD-499E-A4E7-C5B98B73449A';
|
|
595
|
+
|
|
519
596
|
// Convert into Twee.
|
|
520
597
|
const t = s.toTwee();
|
|
521
598
|
|
|
@@ -534,6 +611,9 @@ describe('Story', () => {
|
|
|
534
611
|
s.addPassage(new Passage('Test', 'Test', ['stylesheet']));
|
|
535
612
|
s.addPassage(new Passage('Start', 'Content'));
|
|
536
613
|
|
|
614
|
+
// Set IFID.
|
|
615
|
+
s.IFID = 'DE7DF8AD-E4CD-499E-A4E7-C5B98B73449A';
|
|
616
|
+
|
|
537
617
|
// Convert into Twee.
|
|
538
618
|
const t = s.toTwee();
|
|
539
619
|
|
|
@@ -555,18 +635,6 @@ describe('Story', () => {
|
|
|
555
635
|
s = new Story();
|
|
556
636
|
});
|
|
557
637
|
|
|
558
|
-
it('Should throw error if no starting passage', function () {
|
|
559
|
-
// No start set.
|
|
560
|
-
expect(() => { s.toTwine2HTML(); }).toThrow();
|
|
561
|
-
});
|
|
562
|
-
|
|
563
|
-
it('Should throw error if starting passage cannot be found', function () {
|
|
564
|
-
// Set start.
|
|
565
|
-
s.start = 'Unknown';
|
|
566
|
-
// Has a start, but not part of collection.
|
|
567
|
-
expect(() => { s.toTwine2HTML(); }).toThrow();
|
|
568
|
-
});
|
|
569
|
-
|
|
570
638
|
it('Should encode name', () => {
|
|
571
639
|
// Add passage.
|
|
572
640
|
s.addPassage(new Passage('Start', 'Word'));
|
|
@@ -618,6 +686,113 @@ describe('Story', () => {
|
|
|
618
686
|
// Expect the script passage text to be encoded.
|
|
619
687
|
expect(result.includes('<script role="script" id="twine-user-script" type="text/twine-javascript">Word')).toBe(true);
|
|
620
688
|
});
|
|
689
|
+
|
|
690
|
+
it('Should encode format', () => {
|
|
691
|
+
// Add passage.
|
|
692
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
693
|
+
// Set start.
|
|
694
|
+
s.start = 'Start';
|
|
695
|
+
// Set format.
|
|
696
|
+
s.format = 'Harlowe';
|
|
697
|
+
// Create HTML.
|
|
698
|
+
const result = s.toTwine2HTML();
|
|
699
|
+
// Expect the format to be encoded.
|
|
700
|
+
expect(result.includes('format="Harlowe"')).toBe(true);
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
it('Should encode formatVersion', () => {
|
|
704
|
+
// Add passage.
|
|
705
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
706
|
+
// Set start.
|
|
707
|
+
s.start = 'Start';
|
|
708
|
+
// Set formatVersion.
|
|
709
|
+
s.formatVersion = '3.2.0';
|
|
710
|
+
// Create HTML.
|
|
711
|
+
const result = s.toTwine2HTML();
|
|
712
|
+
// Expect the formatVersion to be encoded.
|
|
713
|
+
expect(result.includes('format-version="3.2.0"')).toBe(true);
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
it('Should encode zoom', () => {
|
|
717
|
+
// Add passage.
|
|
718
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
719
|
+
// Set start.
|
|
720
|
+
s.start = 'Start';
|
|
721
|
+
// Set zoom.
|
|
722
|
+
s.zoom = 2;
|
|
723
|
+
// Create HTML.
|
|
724
|
+
const result = s.toTwine2HTML();
|
|
725
|
+
// Expect the zoom to be encoded.
|
|
726
|
+
expect(result.includes('zoom="2"')).toBe(true);
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
it('Should encode start', () => {
|
|
730
|
+
// Add passage.
|
|
731
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
732
|
+
// Set start.
|
|
733
|
+
s.start = 'Start';
|
|
734
|
+
// Create HTML.
|
|
735
|
+
const result = s.toTwine2HTML();
|
|
736
|
+
// Expect the start to be encoded.
|
|
737
|
+
expect(result.includes('startnode="1"')).toBe(true);
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
it('Should encode start if property is not set but Start passage is', () => {
|
|
741
|
+
// Add passage.
|
|
742
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
743
|
+
// Create HTML.
|
|
744
|
+
const result = s.toTwine2HTML();
|
|
745
|
+
// Expect the start to be encoded.
|
|
746
|
+
expect(result.includes('startnode="1"')).toBe(true);
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
it('Should encode creator', () => {
|
|
750
|
+
// Add passage.
|
|
751
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
752
|
+
// Set start.
|
|
753
|
+
s.start = 'Start';
|
|
754
|
+
// Create HTML.
|
|
755
|
+
const result = s.toTwine2HTML();
|
|
756
|
+
// Expect the creator to be encoded.
|
|
757
|
+
expect(result.includes(`creator="${creatorName}"`)).toBe(true);
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
it('Should encode creatorVersion', () => {
|
|
761
|
+
// Add passage.
|
|
762
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
763
|
+
// Set start.
|
|
764
|
+
s.start = 'Start';
|
|
765
|
+
// Create HTML.
|
|
766
|
+
const result = s.toTwine2HTML();
|
|
767
|
+
// Expect the creatorVersion to be encoded.
|
|
768
|
+
expect(result.includes(`creator-version="${creatorVersion}"`)).toBe(true);
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
it('Should not encode creatorVersion if not set', () => {
|
|
772
|
+
// Add passage.
|
|
773
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
774
|
+
// Set start.
|
|
775
|
+
s.start = 'Start';
|
|
776
|
+
// Set creatorVersion to empty string.
|
|
777
|
+
s.creatorVersion = '';
|
|
778
|
+
// Create HTML.
|
|
779
|
+
const result = s.toTwine2HTML();
|
|
780
|
+
// Expect the creatorVersion to be encoded.
|
|
781
|
+
expect(result.includes(`creator-version="${creatorVersion}"`)).not.toBe(true);
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
it('Should not encode creator if not set', () => {
|
|
785
|
+
// Add passage.
|
|
786
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
787
|
+
// Set start.
|
|
788
|
+
s.start = 'Start';
|
|
789
|
+
// Set creator to empty string.
|
|
790
|
+
s.creator = '';
|
|
791
|
+
// Create HTML.
|
|
792
|
+
const result = s.toTwine2HTML();
|
|
793
|
+
// Expect the creator to be encoded.
|
|
794
|
+
expect(result.includes(`creator="${creatorName}"`)).not.toBe(true);
|
|
795
|
+
});
|
|
621
796
|
});
|
|
622
797
|
|
|
623
798
|
describe('toTwine1HTML()', function () {
|
|
@@ -652,7 +827,7 @@ describe('Story', () => {
|
|
|
652
827
|
// Expect correct name attribute for tw-passagedata.
|
|
653
828
|
expect(root.querySelector('tw-passagedata').getAttribute('name')).toBe('"Test"');
|
|
654
829
|
// Use Twine 2 result.
|
|
655
|
-
const s2 =
|
|
830
|
+
const s2 = '<tw-storydata name=""Abuse" &test" startnode="1" creator="Twine" creator-version="2.8.1" format="Harlowe" format-version="3.3.8" ifid="452A9D80-C759-42C5-B001-5B861A2410C5" options="" tags="" zoom="1" hidden><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style><script role="script" id="twine-user-script" type="text/twine-javascript"></script><tw-passagedata pid="1" name=""Test"" tags="&tag "bad"" position="300,100" size="100,100"></tw-passagedata></tw-storydata>';
|
|
656
831
|
// Parse HTML.
|
|
657
832
|
const root2 = HTMLParser(s2);
|
|
658
833
|
// Expect correct name attribute for tw-storydata.
|
|
@@ -674,4 +849,38 @@ describe('Story', () => {
|
|
|
674
849
|
expect(root.querySelector('div').getAttribute('tiddler')).toBe('"Test"');
|
|
675
850
|
});
|
|
676
851
|
});
|
|
852
|
+
|
|
853
|
+
describe('Warnings', function () {
|
|
854
|
+
beforeEach(() => {
|
|
855
|
+
// Mock console.warn.
|
|
856
|
+
jest.spyOn(console, 'warn').mockImplementation();
|
|
857
|
+
});
|
|
858
|
+
|
|
859
|
+
afterEach(() => {
|
|
860
|
+
// Restore all mocks.
|
|
861
|
+
jest.restoreAllMocks();
|
|
862
|
+
});
|
|
863
|
+
|
|
864
|
+
it('Should generate warning if a passage with the same name already exists', function () {
|
|
865
|
+
// Create a new Story.
|
|
866
|
+
const s = new Story();
|
|
867
|
+
// Add a passage.
|
|
868
|
+
s.addPassage(new Passage('Test'));
|
|
869
|
+
// Add a passage with the same name.
|
|
870
|
+
s.addPassage(new Passage('Test'));
|
|
871
|
+
// Expect warning.
|
|
872
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: A passage with the name "Test" already exists!');
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
it('Should generate a warning if story IFID is not in the correct format', function () {
|
|
876
|
+
// Create a new Story.
|
|
877
|
+
const s = new Story();
|
|
878
|
+
// Set IFID.
|
|
879
|
+
s.IFID = 'Test';
|
|
880
|
+
// Create Twee
|
|
881
|
+
s.toTwee();
|
|
882
|
+
// Expect warning.
|
|
883
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: IFID is not in UUIDv4 format! A new IFID was generated.');
|
|
884
|
+
});
|
|
885
|
+
});
|
|
677
886
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import StoryFormat from '
|
|
1
|
+
import StoryFormat from '../../src/StoryFormat.js';
|
|
2
2
|
|
|
3
3
|
describe('StoryFormat', () => {
|
|
4
|
-
describe('
|
|
5
|
-
it('Should
|
|
4
|
+
describe('Default values', () => {
|
|
5
|
+
it('Should have default values', () => {
|
|
6
6
|
const sf = new StoryFormat();
|
|
7
7
|
expect(sf.name).toBe('Untitled Story Format');
|
|
8
8
|
expect(sf.version).toBe('');
|
|
@@ -149,4 +149,11 @@ describe('StoryFormat', () => {
|
|
|
149
149
|
}).toThrow();
|
|
150
150
|
});
|
|
151
151
|
});
|
|
152
|
+
|
|
153
|
+
describe('toString', () => {
|
|
154
|
+
it('Should return string representation', () => {
|
|
155
|
+
const sf = new StoryFormat();
|
|
156
|
+
expect(sf.toString()).toBe(JSON.stringify(sf, null, '\t'));
|
|
157
|
+
});
|
|
158
|
+
});
|
|
152
159
|
});
|