44
55import type { SerializedVerseRef } from '@sillsdev/scripture' ;
66import { render , screen } from '@testing-library/react' ;
7- import userEvent from '@testing-library/user-event' ;
8- import type { Book } from 'interlinearizer' ;
7+ import type { Book , Segment } from 'interlinearizer' ;
98import Interlinearizer from '../../components/Interlinearizer' ;
109
11- // Store captured props so tests can simulate callbacks
10+ // Store captured props so tests can inspect what Interlinearizer passes down
1211let capturedContinuousViewProps : Record < string , unknown > = { } ;
1312
13+ type CapturedSegmentViewProps = {
14+ segment : Segment ;
15+ displayMode ?: string ;
16+ isActive ?: boolean ;
17+ onClick ?: ( ref : { book : string ; chapter : number ; verse : number } ) => void ;
18+ } ;
19+ let capturedSegmentViewPropsList : CapturedSegmentViewProps [ ] = [ ] ;
20+
1421jest . mock ( '../../components/ContinuousView' , ( ) => ( {
1522 __esModule : true ,
1623 default : ( props : Record < string , unknown > ) => {
@@ -19,6 +26,18 @@ jest.mock('../../components/ContinuousView', () => ({
1926 } ,
2027} ) ) ;
2128
29+ jest . mock ( '../../components/SegmentView' , ( ) => ( {
30+ __esModule : true ,
31+ SegmentView : ( { segment, ...rest } : CapturedSegmentViewProps ) => {
32+ capturedSegmentViewPropsList . push ( { segment, ...rest } ) ;
33+ return < div data-testid = "segment-view" data-segment-id = { segment . id } /> ;
34+ } ,
35+ default : ( { segment, ...rest } : CapturedSegmentViewProps ) => {
36+ capturedSegmentViewPropsList . push ( { segment, ...rest } ) ;
37+ return < div data-testid = "segment-view" data-segment-id = { segment . id } /> ;
38+ } ,
39+ } ) ) ;
40+
2241const defaultScrRef : SerializedVerseRef = { book : 'GEN' , chapterNum : 1 , verseNum : 1 } ;
2342
2443/** Pre-built Book with one GEN 1:1 segment. */
@@ -90,31 +109,6 @@ const GEN_1_MULTI_BOOK: Book = {
90109 ] ,
91110} ;
92111
93- /** Book with a non-word (punctuation) token — exercises the non-word chip branch. */
94- const GEN_1_1_PUNCTUATION_BOOK : Book = {
95- id : 'GEN' ,
96- bookRef : 'GEN' ,
97- textVersion : 'v1' ,
98- segments : [
99- {
100- id : 'GEN 1:1' ,
101- startRef : { book : 'GEN' , chapter : 1 , verse : 1 } ,
102- endRef : { book : 'GEN' , chapter : 1 , verse : 1 } ,
103- baselineText : '.' ,
104- tokens : [
105- {
106- id : 'GEN 1:1:0' ,
107- surfaceText : '.' ,
108- writingSystem : 'en' ,
109- type : 'punctuation' ,
110- charStart : 0 ,
111- charEnd : 1 ,
112- } ,
113- ] ,
114- } ,
115- ] ,
116- } ;
117-
118112function renderInterlinearizer ( {
119113 book = GEN_1_1_BOOK ,
120114 bookSegments = GEN_1_1_BOOK . segments ,
@@ -142,12 +136,13 @@ function renderInterlinearizer({
142136describe ( 'Interlinearizer' , ( ) => {
143137 beforeEach ( ( ) => {
144138 capturedContinuousViewProps = { } ;
139+ capturedSegmentViewPropsList = [ ] ;
145140 } ) ;
146141
147- it ( 'renders token chips when the tokenized book has a segment for the current reference' , ( ) => {
142+ it ( 'renders a SegmentView when the tokenized book has a segment for the current reference' , ( ) => {
148143 renderInterlinearizer ( ) ;
149144
150- expect ( screen . getByText ( 'In ') ) . toBeInTheDocument ( ) ;
145+ expect ( screen . getAllByTestId ( 'segment-view ') ) . toHaveLength ( 1 ) ;
151146 } ) ;
152147
153148 it ( 'shows a no-verse message when the tokenized book has no segments at all' , ( ) => {
@@ -156,56 +151,48 @@ describe('Interlinearizer', () => {
156151 expect ( screen . getByText ( / n o v e r s e d a t a f o r g e n 1 \. / i) ) . toBeInTheDocument ( ) ;
157152 } ) ;
158153
159- it ( 'renders all segments in the current chapter' , ( ) => {
154+ it ( 'renders a SegmentView for every segment in the current chapter' , ( ) => {
160155 renderInterlinearizer ( { bookSegments : GEN_1_MULTI_BOOK . segments } ) ;
161156
162- expect ( screen . getByText ( 'In' ) ) . toBeInTheDocument ( ) ;
163- expect ( screen . getByText ( 'And' ) ) . toBeInTheDocument ( ) ;
157+ expect ( screen . getAllByTestId ( 'segment-view' ) ) . toHaveLength ( 2 ) ;
158+ expect ( capturedSegmentViewPropsList [ 0 ] . segment . id ) . toBe ( 'GEN 1:1' ) ;
159+ expect ( capturedSegmentViewPropsList [ 1 ] . segment . id ) . toBe ( 'GEN 1:2' ) ;
164160 } ) ;
165161
166- it ( 'highlights only the segment matching the current verse' , ( ) => {
167- const { container } = renderInterlinearizer ( { bookSegments : GEN_1_MULTI_BOOK . segments } ) ;
162+ it ( 'passes isActive=true only to the segment matching the current verse' , ( ) => {
163+ renderInterlinearizer ( { bookSegments : GEN_1_MULTI_BOOK . segments } ) ;
168164
169- // defaultScrRef is GEN 1:1, so verse 1 is active
170- const activeSegments = container . querySelectorAll ( 'button[aria-current="true"]' ) ;
171- expect ( activeSegments ) . toHaveLength ( 1 ) ;
165+ // defaultScrRef is GEN 1:1
166+ expect ( capturedSegmentViewPropsList [ 0 ] . isActive ) . toBe ( true ) ;
167+ expect ( capturedSegmentViewPropsList [ 1 ] . isActive ) . toBeFalsy ( ) ;
172168 } ) ;
173169
174- it ( 'shows all chapter segments when navigating to a title reference (verse 0)' , ( ) => {
170+ it ( 'renders all segments when navigating to a title reference (verse 0)' , ( ) => {
175171 const titleRef : SerializedVerseRef = { book : 'GEN' , chapterNum : 1 , verseNum : 0 } ;
176172 renderInterlinearizer ( { bookSegments : GEN_1_MULTI_BOOK . segments , scrRef : titleRef } ) ;
177173
178- expect ( screen . getByText ( 'In' ) ) . toBeInTheDocument ( ) ;
179- expect ( screen . getByText ( 'And' ) ) . toBeInTheDocument ( ) ;
180- } ) ;
181-
182- it ( 'renders non-word tokens as muted chips' , ( ) => {
183- renderInterlinearizer ( { bookSegments : GEN_1_1_PUNCTUATION_BOOK . segments } ) ;
184-
185- expect ( screen . getByText ( '.' ) ) . toBeInTheDocument ( ) ;
174+ expect ( screen . getAllByTestId ( 'segment-view' ) ) . toHaveLength ( 2 ) ;
186175 } ) ;
187176
188- it ( 'calls setScrRef with the segment ref when a verse box is clicked' , async ( ) => {
177+ it ( 'calls setScrRef with the segment ref when a verse box is clicked' , ( ) => {
189178 const mockSetScrRef = jest . fn ( ) ;
190179 renderInterlinearizer ( { bookSegments : GEN_1_MULTI_BOOK . segments , setScrRef : mockSetScrRef } ) ;
191180
192- await userEvent . click ( screen . getByText ( 'And' ) ) ;
181+ capturedSegmentViewPropsList [ 1 ] . onClick ?. ( { book : 'GEN' , chapter : 1 , verse : 2 } ) ;
193182
194183 expect ( mockSetScrRef ) . toHaveBeenCalledWith ( { book : 'GEN' , chapterNum : 1 , verseNum : 2 } ) ;
195184 } ) ;
196185
197- it ( 'renders segments in baseline-text mode when continuousScroll is true' , ( ) => {
186+ it ( 'passes displayMode=" baseline-text" to SegmentView when continuousScroll is true' , ( ) => {
198187 renderInterlinearizer ( { continuousScroll : true } ) ;
199188
200- expect ( screen . getByText ( 'In the beginning.' ) ) . toBeInTheDocument ( ) ;
201- expect ( screen . queryByText ( 'In' ) ) . not . toBeInTheDocument ( ) ;
189+ expect ( capturedSegmentViewPropsList [ 0 ] . displayMode ) . toBe ( 'baseline-text' ) ;
202190 } ) ;
203191
204- it ( 'renders all chapter segments in baseline-text mode when continuousScroll is true' , ( ) => {
192+ it ( 'passes displayMode=" baseline-text" to all SegmentViews when continuousScroll is true' , ( ) => {
205193 renderInterlinearizer ( { bookSegments : GEN_1_MULTI_BOOK . segments , continuousScroll : true } ) ;
206194
207- expect ( screen . getByText ( 'In the beginning.' ) ) . toBeInTheDocument ( ) ;
208- expect ( screen . getByText ( 'And the earth.' ) ) . toBeInTheDocument ( ) ;
195+ capturedSegmentViewPropsList . forEach ( ( p ) => expect ( p . displayMode ) . toBe ( 'baseline-text' ) ) ;
209196 } ) ;
210197
211198 it ( 'renders ContinuousView when continuousScroll is true' , ( ) => {
@@ -228,7 +215,7 @@ describe('Interlinearizer', () => {
228215
229216 const continuousView = screen . getByTestId ( 'continuous-view' ) ;
230217 const allElements = Array . from (
231- container . querySelectorAll ( '[data-testid="continuous-view"], button[aria-current ]' ) ,
218+ container . querySelectorAll ( '[data-testid="continuous-view"], [data-testid="segment-view" ]' ) ,
232219 ) ;
233220 expect ( allElements [ 0 ] ) . toBe ( continuousView ) ;
234221 } ) ;
0 commit comments