@@ -11,6 +11,18 @@ const { HyperaudioLite } = require("../js/hyperaudio-lite");
1111let wordArr = [ ] ;
1212let ht = null ;
1313
14+
15+
16+ test ( "initialization with parameters" , ( ) => {
17+ const customHt = new HyperaudioLite ( "hypertranscript" , "hyperplayer" , true , true , true , true , true ) ;
18+
19+ expect ( customHt . minimizedMode ) . toBe ( true ) ;
20+ expect ( customHt . autoscroll ) . toBe ( true ) ;
21+ expect ( customHt . doubleClick ) . toBe ( true ) ;
22+ expect ( customHt . webMonetization ) . toBe ( true ) ;
23+ expect ( customHt . playOnClick ) . toBe ( true ) ;
24+ } ) ;
25+
1426function createWordArrayResult ( words ) {
1527 for ( let i = 0 ; i < words . length ; ++ i ) {
1628 const m = parseInt ( words [ i ] . getAttribute ( "data-m" ) ) ;
@@ -59,7 +71,8 @@ document.body.innerHTML =
5971
6072window . HTMLMediaElement . prototype . play = ( ) => {
6173 /* does nothing */
62- } ;
74+ }
75+
6376
6477test ( "instantiation - options false" , ( ) => {
6578 let minimizedMode = false ;
@@ -77,6 +90,8 @@ test("instantiation - options false", () => {
7790 ) ;
7891} ) ;
7992
93+
94+
8095test ( "createWordArray" , ( ) => {
8196 const words = document . querySelectorAll ( "[data-m]" ) ;
8297 const expectedResult = createWordArrayResult ( words ) ;
@@ -131,11 +146,6 @@ test("instantiation - doubleClick true", () => {
131146 ) ;
132147} ) ;
133148
134- test ( "transcript - doubleClick on word" , ( ) => {
135- simulateClick ( document . getElementsByTagName ( "span" ) [ 4 ] , "dblclick" ) ;
136- expect ( ht . player . currentTime ) . toStrictEqual ( 4.75 ) ;
137- } ) ;
138-
139149test ( "instantiation - webMonetization true" , ( ) => {
140150 let minimizedMode = false ;
141151 let autoScroll = false ;
@@ -152,6 +162,11 @@ test("instantiation - webMonetization true", () => {
152162 ) ;
153163} ) ;
154164
165+ test ( "transcript - doubleClick on word" , ( ) => {
166+ simulateClick ( document . getElementsByTagName ( "span" ) [ 4 ] , "dblclick" ) ;
167+ expect ( ht . player . currentTime ) . toStrictEqual ( 4.75 ) ;
168+ } ) ;
169+
155170// This test always passes - fix it
156171/*test("transcript - payment pointer inserted", () => {
157172 simulateClick(document.getElementsByTagName("span")[4], "click");
@@ -177,3 +192,120 @@ test("transcript - check that active is set on paragraph", () => {
177192 simulateClick ( document . getElementsByTagName ( "span" ) [ 4 ] , "dblclick" ) ;
178193 expect ( document . querySelector ( 'p.active' ) ) . toBe ( document . getElementsByTagName ( 'p' ) [ 0 ] ) ;
179194} ) ;
195+
196+ test ( "setupTranscriptHash with no hash" , ( ) => {
197+ window . location . hash = "" ;
198+ ht . setupTranscriptHash ( ) ;
199+ expect ( ht . hashArray ) . toEqual ( [ ] ) ;
200+ } ) ;
201+
202+ test ( "setupTranscriptHash with valid hash" , ( ) => {
203+ window . location . hash = "#hypertranscript=10,20" ;
204+ ht . setupTranscriptHash ( ) ;
205+ expect ( ht . hashArray ) . toEqual ( [ "10" , "20" ] ) ;
206+ } ) ;
207+
208+ test ( "getSelectionRange with no selection" , ( ) => {
209+ window . getSelection ( ) . removeAllRanges ( ) ;
210+ expect ( ht . getSelectionRange ( ) ) . toBeNull ( ) ;
211+ } ) ;
212+
213+ test ( "getSelectionRange with valid selection" , ( ) => {
214+ const firstSpan = document . querySelector ( 'span[data-m="880"]' ) ;
215+ const lastSpan = document . querySelector ( 'span[data-m="4750"]' ) ;
216+ const range = document . createRange ( ) ;
217+ range . setStartBefore ( firstSpan ) ;
218+ range . setEndAfter ( lastSpan ) ;
219+ window . getSelection ( ) . removeAllRanges ( ) ;
220+ window . getSelection ( ) . addRange ( range ) ;
221+
222+ expect ( ht . getSelectionRange ( ) ) . toBe ( "0.88,5.21" ) ;
223+ } ) ;
224+
225+ test ( "clearActiveClasses removes all active classes" , ( ) => {
226+ const spans = document . querySelectorAll ( 'span' ) ;
227+ spans . forEach ( span => span . classList . add ( 'active' ) ) ;
228+
229+ ht . clearActiveClasses ( ) ;
230+
231+ spans . forEach ( span => {
232+ expect ( span . classList . contains ( 'active' ) ) . toBe ( false ) ;
233+ } ) ;
234+ } ) ;
235+
236+ test ( "scrollToParagraph updates parentElementIndex" , ( ) => {
237+ ht . parentElementIndex = 0 ;
238+ ht . scrollToParagraph ( 1 , 6 ) ;
239+ expect ( ht . parentElementIndex ) . toBe ( 1 ) ;
240+ } ) ;
241+
242+ test ( "checkPaymentPointer returns correct payment pointer" , ( ) => {
243+ const p1 = document . getElementById ( 'p1' ) ;
244+ expect ( ht . checkPaymentPointer ( p1 ) ) . toBe ( "payment-pointer" ) ;
245+ } ) ;
246+
247+ test ( "checkPaymentPointer returns null for element without payment pointer" , ( ) => {
248+ const p2 = document . querySelectorAll ( 'p' ) [ 1 ] ;
249+ expect ( ht . checkPaymentPointer ( p2 ) ) . toBeNull ( ) ;
250+ } ) ;
251+
252+ test ( "updateTranscriptVisualState marks words as read" , ( ) => {
253+ ht . updateTranscriptVisualState ( 5 ) ;
254+ const spans = document . querySelectorAll ( 'span' ) ;
255+ expect ( spans [ 0 ] . classList . contains ( 'read' ) ) . toBe ( true ) ;
256+ expect ( spans [ 4 ] . classList . contains ( 'read' ) ) . toBe ( true ) ;
257+ expect ( spans [ 5 ] . classList . contains ( 'unread' ) ) . toBe ( true ) ;
258+ } ) ;
259+
260+ test ( "setPlayHead updates currentTime and plays if playOnClick is true" , ( ) => {
261+ ht . playOnClick = true ;
262+ ht . myPlayer = { setTime : jest . fn ( ) , play : jest . fn ( ) , paused : true } ;
263+
264+ const event = { target : document . querySelector ( 'span[data-m="3950"]' ) } ;
265+ ht . setPlayHead ( event ) ;
266+
267+ expect ( ht . myPlayer . setTime ) . toHaveBeenCalledWith ( 3.95 ) ;
268+ expect ( ht . myPlayer . play ) . toHaveBeenCalled ( ) ;
269+ } ) ;
270+
271+ test ( "preparePlayHead sets paused to false and calls checkPlayHead" , ( ) => {
272+ ht . checkPlayHead = jest . fn ( ) ;
273+ ht . preparePlayHead ( ) ;
274+
275+ expect ( ht . myPlayer . paused ) . toBe ( false ) ;
276+ expect ( ht . checkPlayHead ) . toHaveBeenCalled ( ) ;
277+ } ) ;
278+
279+ test ( "pausePlayHead clears timer and sets paused to true" , ( ) => {
280+ jest . useFakeTimers ( ) ;
281+ ht . timer = setTimeout ( ( ) => { } , 1000 ) ;
282+ ht . pausePlayHead ( ) ;
283+
284+ expect ( ht . myPlayer . paused ) . toBe ( true ) ;
285+ expect ( ht . timer ) . toBeFalsy ( ) ;
286+ jest . useRealTimers ( ) ;
287+ } ) ;
288+
289+ // This test requires jest.useFakeTimers() to work properly
290+ test ( "checkStatus schedules next check" , ( ) => {
291+ jest . useFakeTimers ( ) ;
292+ ht . myPlayer = {
293+ paused : false ,
294+ getTime : jest . fn ( ) . mockResolvedValue ( 5 )
295+ } ;
296+ ht . updateTranscriptVisualState = jest . fn ( ) . mockReturnValue ( { currentWordIndex : 4 , currentParentElementIndex : 0 } ) ;
297+ ht . scrollToParagraph = jest . fn ( ) ;
298+ ht . checkPlayHead = jest . fn ( ) ;
299+
300+ ht . checkStatus ( ) ;
301+
302+ jest . runAllTimers ( ) ;
303+
304+ expect ( ht . checkPlayHead ) . toHaveBeenCalled ( ) ;
305+
306+ jest . useRealTimers ( ) ;
307+ } ) ;
308+
309+
310+
311+
0 commit comments