Recently Written · git

scan-subread

PDF reader that follows an audiobook with the SubRead suite

git clone https://github.com/equwal/scan-subread

Log | Files | Refs


test/book-subtitles.test.ts (5954 bytes)

1 import fc from 'fast-check';
2 import { describe, expect, it } from 'vitest';
3 import {
4   keepMakeStatus,
5   resultName,
6   srtName,
7   subreadConcerns,
8   subtitlesOnOpen,
9 } from '../src/book-subtitles';
10 
11 describe('keepMakeStatus', () => {
12   it('removes the SubRead result of the book before', () => {
13     // The finding: "15 cues, language en, 97% ..." of book A stayed in the
14     // menu when book B opened.
15     expect(keepMakeStatus('B', null, null)).toBe(false);
16   });
17 
18   it('removes the wait of the book before: its job does not start', () => {
19     expect(keepMakeStatus('B', null, 'A')).toBe(false);
20   });
21 
22   it('keeps the status of the job that runs: it tells why the button is off', () => {
23     expect(keepMakeStatus('B', 'A', null)).toBe(true);
24     expect(keepMakeStatus('A', 'A', null)).toBe(true);
25   });
26 
27   it('keeps the wait of the book that opens again', () => {
28     expect(keepMakeStatus('A', null, 'A')).toBe(true);
29   });
30 });
31 
32 describe('srtName', () => {
33   it('puts .srt in place of .pdf', () => {
34     expect(srtName('sample-eng-2p.pdf')).toBe('sample-eng-2p.srt');
35     expect(srtName('Neko.PDF')).toBe('Neko.srt');
36     expect(srtName('吾輩は猫である.pdf')).toBe('吾輩は猫である.srt');
37   });
38 
39   it('adds .srt to a name without .pdf at the end', () => {
40     expect(srtName('book')).toBe('book.srt');
41     expect(srtName('a.pdf.txt')).toBe('a.pdf.txt.srt');
42   });
43 });
44 
45 describe('subtitlesOnOpen', () => {
46   const eng = 'sample-eng-2p.pdf|4053';
47   const jpn = 'sample-jpn.pdf|20410';
48 
49   it('loads the saved subtitles of the book, else clears', () => {
50     expect(subtitlesOnOpen(undefined, jpn, true)).toBe('load');
51     expect(subtitlesOnOpen(undefined, jpn, false)).toBe('clear');
52   });
53 
54   it('does not keep the subtitles of another book', () => {
55     // The web finding: the cues of the English book stayed on the Japanese book.
56     expect(subtitlesOnOpen(eng, jpn, false)).toBe('clear');
57     expect(subtitlesOnOpen(eng, jpn, true)).toBe('load');
58   });
59 
60   it('keeps subtitles that were loaded while no book was open, for the book that opens', () => {
61     expect(subtitlesOnOpen(null, jpn, false)).toBe('keep');
62     expect(subtitlesOnOpen(null, jpn, true)).toBe('keep');
63   });
64 
65   it('keeps the subtitles of the same book', () => {
66     expect(subtitlesOnOpen(jpn, jpn, true)).toBe('keep');
67     expect(subtitlesOnOpen(jpn, jpn, false)).toBe('keep');
68   });
69 });
70 
71 describe('resultName', () => {
72   it('is the FNV-1a hash of the book key', () => {
73     // The test vectors of FNV-1a (32 bit).
74     expect(resultName('')).toBe('subread-811c9dc5.srt');
75     expect(resultName('a')).toBe('subread-e40c292c.srt');
76     expect(resultName('foobar')).toBe('subread-bf9cf968.srt');
77   });
78 
79   it('tells apart two Japanese books that the plugin would both call "_"', () => {
80     const neko = resultName('吾輩は猫である.pdf|204800');
81     const botchan = resultName('坊っちゃん.pdf|204800');
82     expect(neko).not.toBe(botchan);
83     expect(resultName('吾輩は猫である.pdf|204801')).not.toBe(neko);
84   });
85 
86   it('gives a name that the plugin keeps as it is, the same for the same key', () => {
87     fc.assert(
88       fc.property(fc.string({ unit: 'binary' }), (key) => {
89         const name = resultName(key);
90         expect(name).toMatch(/^subread-[0-9a-f]{8}\.srt$/);
91         expect(resultName(key)).toBe(name);
92       }),
93     );
94   });
95 });
96 
97 describe('subreadConcerns', () => {
98   const file = { name: 'sample-eng-2p.srt', source: 'file' as const };
99 
100   it('asks for the phone case: no speech, language km, match rate 1, over a loaded file', () => {
101     expect(
102       subreadConcerns({
103         requested: 'auto',
104         ocrLang: 'eng',
105         language: 'km',
106         matchRate: 1,
107         loaded: file,
108       }),
109     ).toEqual([
110       'They replace sample-eng-2p.srt, the subtitles that you loaded.',
111       'SubRead found the language "km", not "en".',
112     ]);
113   });
114 
115   it('loads at once a good result over no subtitles or over an earlier SubRead result', () => {
116     const good = { requested: 'auto', ocrLang: 'jpn', language: 'ja', matchRate: 0.97 };
117     expect(subreadConcerns(good)).toEqual([]);
118     const earlier = { name: 'neko.srt', source: 'subread' as const };
119     expect(subreadConcerns({ ...good, loaded: earlier })).toEqual([]);
120   });
121 
122   it('compares the found language with the requested one', () => {
123     expect(subreadConcerns({ requested: 'ja', ocrLang: 'eng', language: 'ja' })).toEqual([]);
124     expect(subreadConcerns({ requested: 'ja', ocrLang: 'jpn', language: 'en' })).toEqual([
125       'SubRead found the language "en", not "ja".',
126     ]);
127   });
128 
129   it('takes the language of the book from the OCR language when the request is auto', () => {
130     const both = { requested: 'auto', ocrLang: 'jpn+eng' };
131     expect(subreadConcerns({ ...both, language: 'en' })).toEqual([]);
132     expect(subreadConcerns({ ...both, language: 'ja' })).toEqual([]);
133     expect(subreadConcerns({ ...both, language: 'km' })).toEqual([
134       'SubRead found the language "km", not "ja" or "en".',
135     ]);
136     const vertical = { requested: 'auto', ocrLang: 'jpn_vert', language: 'ja' };
137     expect(subreadConcerns(vertical)).toEqual([]);
138     expect(subreadConcerns({ requested: 'auto', ocrLang: 'eng', language: 'en-US' })).toEqual([]);
139   });
140 
141   it('does not ask about a language or a match rate that SubRead does not tell', () => {
142     expect(subreadConcerns({ requested: 'ja', ocrLang: 'jpn', language: null })).toEqual([]);
143     expect(subreadConcerns({ requested: 'ja', ocrLang: 'jpn', language: '' })).toEqual([]);
144     expect(subreadConcerns({ requested: 'ja', ocrLang: 'jpn', matchRate: -1 })).toEqual([]);
145   });
146 
147   it('asks when less than 80% of the lines are found in the book', () => {
148     expect(subreadConcerns({ requested: 'en', ocrLang: 'eng', matchRate: 0.42 })).toEqual([
149       'SubRead found only 42% of the lines in the book.',
150     ]);
151     expect(subreadConcerns({ requested: 'en', ocrLang: 'eng', matchRate: 0.8 })).toEqual([]);
152   });
153 });