@@ -4,7 +4,7 @@ import { describe, it, expect, beforeEach } from 'vitest';
44import { TestBed } from '@angular/core/testing' ;
55import { Component , signal } from '@angular/core' ;
66import { views } from '@threadplane/render' ;
7- import type { MarkdownTableNode } from '@cacheplane/partial-markdown' ;
7+ import type { MarkdownTableCellNode , MarkdownTableNode , MarkdownTableRowNode } from '@cacheplane/partial-markdown' ;
88import { MarkdownTableComponent } from './markdown-table.component' ;
99import { MarkdownTableRowComponent } from './markdown-table-row.component' ;
1010import { MarkdownTableCellComponent } from './markdown-table-cell.component' ;
@@ -20,6 +20,28 @@ function makeTableNode(overrides: Partial<MarkdownTableNode> = {}): MarkdownTabl
2020 } as MarkdownTableNode ;
2121}
2222
23+ function makeCellNode ( id : number , alignment : MarkdownTableCellNode [ 'alignment' ] = null ) : MarkdownTableCellNode {
24+ return {
25+ id, type : 'table-cell' , status : 'complete' ,
26+ parent : null , index : null ,
27+ alignment,
28+ children : [ ] ,
29+ } as MarkdownTableCellNode ;
30+ }
31+
32+ function makeRowNode (
33+ id : number ,
34+ isHeader : boolean ,
35+ children : MarkdownTableRowNode [ 'children' ] = [ makeCellNode ( id * 10 ) , makeCellNode ( id * 10 + 1 ) ] ,
36+ ) : MarkdownTableRowNode {
37+ return {
38+ id, type : 'table-row' , status : 'complete' ,
39+ parent : null , index : null ,
40+ isHeader,
41+ children,
42+ } as MarkdownTableRowNode ;
43+ }
44+
2345@Component ( {
2446 standalone : true ,
2547 imports : [ MarkdownTableComponent ] ,
@@ -62,28 +84,27 @@ describe('MarkdownTableComponent', () => {
6284 expect ( fixture . nativeElement . querySelector ( 'tbody' ) ) . toBeTruthy ( ) ;
6385 } ) ;
6486
65- it ( 'dispatches each row through chat-md-table-row component' , ( ) => {
66- // Regression: prior impl used <chat-md-children [parent]="row"> which
67- // walked row.children (cells) directly and skipped the row wrapper. Cells
68- // appeared bare under <thead>/<tbody>, no <chat-md-table-row> elements
69- // existed. Live browser smoke caught this; the test below pins the fix.
87+ it ( 'renders native table rows and cells directly under table sections' , ( ) => {
88+ // Keep the browser's table layout tree native. Custom element hosts between
89+ // <thead>/<tbody> and <tr>, or between <tr> and <td>/<th>, rely on
90+ // display: contents and can make a just-streamed row appear detached.
7091 const fixture = TestBed . createComponent ( HostComponent ) ;
7192 fixture . componentInstance . node . set ( makeTableNode ( {
7293 alignments : [ null , null ] ,
7394 children : [
74- { id : 2 , type : 'table-row' , status : 'complete' , parent : null , index : 0 ,
75- isHeader : true , children : [ ] } as never ,
76- { id : 3 , type : 'table-row' , status : 'complete' , parent : null , index : 1 ,
77- isHeader : false , children : [ ] } as never ,
78- { id : 4 , type : 'table-row' , status : 'complete' , parent : null , index : 2 ,
79- isHeader : false , children : [ ] } as never ,
95+ makeRowNode ( 2 , true ) ,
96+ makeRowNode ( 3 , false ) ,
97+ makeRowNode ( 4 , false ) ,
8098 ] ,
8199 } ) ) ;
82100 fixture . detectChanges ( ) ;
83- const rows = fixture . nativeElement . querySelectorAll ( 'chat-md-table-row' ) ;
84- expect ( rows . length ) . toBe ( 3 ) ;
85- // Header row goes in <thead>; body rows in <tbody>.
86- expect ( fixture . nativeElement . querySelectorAll ( 'thead chat-md-table-row' ) . length ) . toBe ( 1 ) ;
87- expect ( fixture . nativeElement . querySelectorAll ( 'tbody chat-md-table-row' ) . length ) . toBe ( 2 ) ;
101+ const table = fixture . nativeElement . querySelector ( 'table' ) as HTMLTableElement ;
102+
103+ expect ( table . querySelectorAll ( ':scope > thead > tr' ) . length ) . toBe ( 1 ) ;
104+ expect ( table . querySelectorAll ( ':scope > tbody > tr' ) . length ) . toBe ( 2 ) ;
105+ expect ( table . querySelectorAll ( 'chat-md-table-row' ) . length ) . toBe ( 0 ) ;
106+ expect ( table . querySelectorAll ( 'chat-md-table-cell' ) . length ) . toBe ( 0 ) ;
107+ expect ( table . querySelectorAll ( ':scope > thead > tr > th' ) . length ) . toBe ( 2 ) ;
108+ expect ( table . querySelectorAll ( ':scope > tbody > tr > td' ) . length ) . toBe ( 4 ) ;
88109 } ) ;
89110} ) ;
0 commit comments