@@ -143,6 +143,58 @@ describe('assembleItem', () => {
143143 ) . toThrow ( 'mutually exclusive' ) ;
144144 } ) ;
145145 } ) ;
146+
147+ describe ( 'innerHTML — HTML5 void elements (TipTap regression)' , ( ) => {
148+ it ( 'handles a bare <br> without producing a parseerror in the XML output' , ( ) => {
149+ const node = buildXmlNode ( {
150+ tag : 'qti-prompt' ,
151+ innerHTML : '<p>Line one</p><br><p>Line two</p>' ,
152+ } ) ;
153+ // Serialized output must be valid XML
154+ const xml = serializer . serializeToString ( node ) ;
155+ const doc = new DOMParser ( ) . parseFromString ( xml , 'text/xml' ) ;
156+ expect ( doc . querySelector ( 'parsererror' ) ) . toBeNull ( ) ;
157+ } ) ;
158+
159+ it ( 'preserves text content when innerHTML contains a <br>' , ( ) => {
160+ const node = buildXmlNode ( {
161+ tag : 'qti-prompt' ,
162+ innerHTML : '<p>First</p><br><p>Second</p>' ,
163+ } ) ;
164+ expect ( node . textContent ) . toContain ( 'First' ) ;
165+ expect ( node . textContent ) . toContain ( 'Second' ) ;
166+ } ) ;
167+
168+ it ( 'handles an unclosed <img> without producing a parseerror' , ( ) => {
169+ const node = buildXmlNode ( {
170+ tag : 'qti-simple-choice' ,
171+ innerHTML : '<img src="cat.png" alt="cat"><span>A cat</span>' ,
172+ } ) ;
173+ const xml = serializer . serializeToString ( node ) ;
174+ const doc = new DOMParser ( ) . parseFromString ( xml , 'text/xml' ) ;
175+ expect ( doc . querySelector ( 'parsererror' ) ) . toBeNull ( ) ;
176+ expect ( node . textContent ) . toContain ( 'A cat' ) ;
177+ } ) ;
178+
179+ it ( 'self-closes void elements in the serialized XML output' , ( ) => {
180+ const node = buildXmlNode ( { tag : 'qti-prompt' , innerHTML : 'Hello<br>World' } ) ;
181+ const xml = serializer . serializeToString ( node ) ;
182+ // <br> must be self-closed in the output (br/ or br with no children)
183+ expect ( xml ) . toMatch ( / < b r [ \s / ] / ) ;
184+ // And the result must still parse without error
185+ expect (
186+ new DOMParser ( ) . parseFromString ( xml , 'text/xml' ) . querySelector ( 'parsererror' ) ,
187+ ) . toBeNull ( ) ;
188+ } ) ;
189+
190+ it ( 'preserves well-formed HTML markup correctly' , ( ) => {
191+ const node = buildXmlNode ( {
192+ tag : 'qti-simple-choice' ,
193+ innerHTML : '<p>Option <strong>A</strong></p>' ,
194+ } ) ;
195+ expect ( node . querySelector ( 'strong' ) . textContent ) . toBe ( 'A' ) ;
196+ } ) ;
197+ } ) ;
146198} ) ;
147199
148200describe ( 'assembleItemXml' , ( ) => {
0 commit comments