Skip to content

Commit df84257

Browse files
authored
feat: [1708] Add support for insertRow and deleteRow to HTMLTableSectionElement (#1709)
1 parent a72b016 commit df84257

File tree

3 files changed

+196
-1
lines changed

3 files changed

+196
-1
lines changed
Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,88 @@
1+
import QuerySelector from '../../query-selector/QuerySelector.js';
2+
import * as PropertySymbol from '../../PropertySymbol.js';
13
import HTMLElement from '../html-element/HTMLElement.js';
4+
import HTMLTableRowElement from '../html-table-row-element/HTMLTableRowElement.js';
5+
import DOMExceptionNameEnum from '../../exception/DOMExceptionNameEnum.js';
26
/**
37
* HTMLTableSectionElement
48
*
59
* @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableSectionElement
610
*/
7-
export default class HTMLTableSectionElement extends HTMLElement {}
11+
export default class HTMLTableSectionElement extends HTMLElement {
12+
/**
13+
* Returns an HTMLTableRowElement representing a new row of the table. It inserts it in the rows collection immediately before the <tr> element at the given index position. If the index is -1, the new row is appended to the collection. If the index is smaller than -1 or greater than the number of rows in the collection, a DOMException with the value IndexSizeError is raised.
14+
*
15+
* @param [index] Index.
16+
* @returns Row.
17+
*/
18+
public insertRow(index: number = -1): HTMLTableRowElement {
19+
if (typeof index !== 'number') {
20+
index = -1;
21+
}
22+
23+
const rows = QuerySelector.querySelectorAll(this, 'tr')[PropertySymbol.items];
24+
25+
if (index < -1) {
26+
throw new this[PropertySymbol.window].DOMException(
27+
`Failed to execute 'insertRow' on 'HTMLTableSectionElement': The index provided (${index}) is less than -1.`,
28+
DOMExceptionNameEnum.indexSizeError
29+
);
30+
}
31+
32+
if (index > rows.length) {
33+
throw new this[PropertySymbol.window].DOMException(
34+
`Failed to execute 'insertRow' on 'HTMLTableSectionElement': The index provided (${index}) is greater than the number of rows (${rows.length}).`,
35+
DOMExceptionNameEnum.indexSizeError
36+
);
37+
}
38+
39+
const row = this[PropertySymbol.ownerDocument].createElement('tr');
40+
41+
if (index === -1 || index === rows.length) {
42+
this.appendChild(row);
43+
} else {
44+
this.insertBefore(row, rows[index]);
45+
}
46+
47+
return row;
48+
}
49+
50+
/**
51+
* Removes the row corresponding to the index given in parameter. If the index value is -1 the last row is removed; if it is smaller than -1 or greater than the amount of rows in the collection, a DOMException with the value IndexSizeError is raised.
52+
*
53+
* @param index Index.
54+
*/
55+
public deleteRow(index: number): void {
56+
if (arguments.length === 0) {
57+
throw new this[PropertySymbol.window].TypeError(
58+
"Failed to execute 'deleteRow' on 'HTMLTableSectionElement': 1 argument required, but only 0 present."
59+
);
60+
}
61+
62+
if (typeof index !== 'number') {
63+
index = -1;
64+
}
65+
66+
if (index < -1) {
67+
throw new this[PropertySymbol.window].DOMException(
68+
`Failed to execute 'deleteRow' on 'HTMLTableSectionElement': The index provided (${index}) is less than -1.`,
69+
DOMExceptionNameEnum.indexSizeError
70+
);
71+
}
72+
73+
const rows = QuerySelector.querySelectorAll(this, 'tr')[PropertySymbol.items];
74+
75+
if (index >= rows.length) {
76+
throw new this[PropertySymbol.window].DOMException(
77+
`Failed to execute 'deleteRow' on 'HTMLTableSectionElement': The index provided (${index}) is greater than the number of rows in the table (${rows.length}).`,
78+
DOMExceptionNameEnum.indexSizeError
79+
);
80+
}
81+
82+
if (index === -1) {
83+
index = rows.length - 1;
84+
}
85+
86+
rows[index].remove();
87+
}
88+
}

packages/happy-dom/test/nodes/html-table-element/HTMLTableElement.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,15 @@ describe('HTMLTableElement', () => {
450450
);
451451
});
452452

453+
it('Throws an error if there are no arguments', () => {
454+
expect(() => {
455+
// @ts-expect-error -- We are intentionally calling this in an unsupported way (no arguments) for this test
456+
element.deleteRow();
457+
}).toThrow(
458+
"Failed to execute 'deleteRow' on 'HTMLTableElement': 1 argument required, but only 0 present."
459+
);
460+
});
461+
453462
it('Throws an error if the index is less than -1', () => {
454463
expect(() => {
455464
element.deleteRow(-2);

packages/happy-dom/test/nodes/html-table-section-element/HTMLTableSectionElement.test.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,109 @@ describe('HTMLTableSectionElement', () => {
1919
expect(element instanceof HTMLTableSectionElement).toBe(true);
2020
});
2121
});
22+
23+
describe('insertRow()', () => {
24+
it('Inserts a new row at the end', () => {
25+
const row = element.insertRow();
26+
expect(element.children[0]).toBe(row);
27+
expect(element.innerHTML).toBe('<tr></tr>');
28+
const row2 = element.insertRow();
29+
expect(element.children[1]).toBe(row2);
30+
expect(element.innerHTML).toBe('<tr></tr><tr></tr>');
31+
});
32+
33+
it('Inserts a new row at the given index', () => {
34+
element.innerHTML = '<tr><td>test</td></tr><tr><td>test</td></tr>';
35+
const row = element.insertRow(1);
36+
expect(element.children[1]).toBe(row);
37+
expect(element.innerHTML).toBe('<tr><td>test</td></tr><tr></tr><tr><td>test</td></tr>');
38+
});
39+
40+
it('Inserts a new row at the end if the index is -1', () => {
41+
element.innerHTML = '<tr><td>test</td></tr><tr><td>test</td></tr>';
42+
const row = element.insertRow(-1);
43+
expect(element.children[2]).toBe(row);
44+
expect(element.innerHTML).toBe('<tr><td>test</td></tr><tr><td>test</td></tr><tr></tr>');
45+
});
46+
47+
it('Inserts a new row at the end if the index is not a number', () => {
48+
element.innerHTML = '<tr><td>test</td></tr><tr><td>test</td></tr>';
49+
const row = element.insertRow(<number>(<unknown>'test'));
50+
expect(element.children[2]).toBe(row);
51+
expect(element.innerHTML).toBe('<tr><td>test</td></tr><tr><td>test</td></tr><tr></tr>');
52+
});
53+
54+
it('Inserts a new row at the end if the index is equal to the length of rows', () => {
55+
element.innerHTML = '<tr><td>test</td></tr><tr><td>test</td></tr>';
56+
const row = element.insertRow(2);
57+
expect(element.children[2]).toBe(row);
58+
expect(element.innerHTML).toBe('<tr><td>test</td></tr><tr><td>test</td></tr><tr></tr>');
59+
});
60+
61+
it('Throws an error if the index is less than -1', () => {
62+
expect(() => {
63+
element.insertRow(-2);
64+
}).toThrow(
65+
"Failed to execute 'insertRow' on 'HTMLTableSectionElement': The index provided (-2) is less than -1."
66+
);
67+
});
68+
69+
it('Throws an error if the index is greater than the number of rows', () => {
70+
element.innerHTML = '<tr><td>test</td></tr><tr><td>test</td></tr>';
71+
expect(() => {
72+
element.insertRow(3);
73+
}).toThrow(
74+
"Failed to execute 'insertRow' on 'HTMLTableSectionElement': The index provided (3) is greater than the number of rows (2)."
75+
);
76+
});
77+
});
78+
79+
describe('deleteRow()', () => {
80+
it('Removes the row at the given index', () => {
81+
element.innerHTML = '<tr><td>Row 1</td></tr><tr><td>Row 2</td></tr><tr><td>Row 3</td></tr>';
82+
element.deleteRow(1);
83+
expect(element.children.length).toBe(2);
84+
expect(element.innerHTML).toBe('<tr><td>Row 1</td></tr><tr><td>Row 3</td></tr>');
85+
});
86+
87+
it('Removes the last row if the index is -1', () => {
88+
element.innerHTML = '<tr><td>Row 1</td></tr><tr><td>Row 2</td></tr><tr><td>Row 3</td></tr>';
89+
element.deleteRow(-1);
90+
expect(element.children.length).toBe(2);
91+
expect(element.innerHTML).toBe('<tr><td>Row 1</td></tr><tr><td>Row 2</td></tr>');
92+
});
93+
94+
it('Removes the last row if the index is not a number', () => {
95+
element.innerHTML = '<tr><td>Row 1</td></tr><tr><td>Row 2</td></tr><tr><td>Row 3</td></tr>';
96+
element.deleteRow(<number>(<unknown>'test'));
97+
expect(element.children.length).toBe(2);
98+
expect(element.innerHTML).toBe('<tr><td>Row 1</td></tr><tr><td>Row 2</td></tr>');
99+
});
100+
101+
it('Throws an error if there are no arguments', () => {
102+
expect(() => {
103+
// @ts-expect-error -- We are intentionally calling this in an unsupported way (no arguments) for this test
104+
element.deleteRow();
105+
}).toThrow(
106+
"Failed to execute 'deleteRow' on 'HTMLTableSectionElement': 1 argument required, but only 0 present."
107+
);
108+
});
109+
110+
it('Throws an error if the index is less than -1', () => {
111+
expect(() => {
112+
element.deleteRow(-2);
113+
}).toThrow(
114+
"Failed to execute 'deleteRow' on 'HTMLTableSectionElement': The index provided (-2) is less than -1."
115+
);
116+
});
117+
118+
it('Throws an error if the index is greater than the number of rows', () => {
119+
element.innerHTML = '<tr><td>test</td></tr><tr><td>test</td></tr>';
120+
expect(() => {
121+
element.deleteRow(2);
122+
}).toThrow(
123+
"Failed to execute 'deleteRow' on 'HTMLTableSectionElement': The index provided (2) is greater than the number of rows in the table (2)."
124+
);
125+
});
126+
});
22127
});

0 commit comments

Comments
 (0)