tests: Refine contentcollector tests

This commit is contained in:
Richard Hansen 2021-11-19 05:16:11 -05:00
parent 1f227200da
commit f40d285109

View file

@ -10,35 +10,64 @@
*/ */
const AttributePool = require('../../../static/js/AttributePool'); const AttributePool = require('../../../static/js/AttributePool');
const Changeset = require('../../../static/js/Changeset');
const assert = require('assert').strict; const assert = require('assert').strict;
const contentcollector = require('../../../static/js/contentcollector'); const contentcollector = require('../../../static/js/contentcollector');
const jsdom = require('jsdom'); const jsdom = require('jsdom');
const tests = { // All test case `wantAlines` values must only refer to attributes in this list so that the
nestedLi: { // attribute numbers do not change due to changes in pool insertion order.
const knownAttribs = [
['insertorder', 'first'],
['italic', 'true'],
['list', 'bullet1'],
['list', 'bullet2'],
['list', 'number1'],
['list', 'number2'],
['lmkr', '1'],
['start', '1'],
['start', '2'],
];
const testCases = [
{
description: 'Simple',
html: '<html><body><p>foo</p></body></html>',
wantAlines: ['+3'],
wantText: ['foo'],
},
{
description: 'Line starts with asterisk',
html: '<html><body><p>*foo</p></body></html>',
wantAlines: ['+4'],
wantText: ['*foo'],
},
{
description: 'Complex nested Li', description: 'Complex nested Li',
html: '<!doctype html><html><body><ol><li>one</li><li><ol><li>1.1</li></ol></li><li>two</li></ol></body></html>', html: '<!doctype html><html><body><ol><li>one</li><li><ol><li>1.1</li></ol></li><li>two</li></ol></body></html>',
wantLineAttribs: [ wantAlines: [
'*0*1*2*3+1+3', '*0*4*2*5+1+3', '*0*1*2*5+1+3', '*0*4*6*7+1+3',
'*0*5*6*8+1+3',
'*0*4*6*8+1+3',
], ],
wantText: [ wantText: [
'*one', '*1.1', '*two', '*one', '*1.1', '*two',
], ],
}, },
complexNest: { {
description: 'Complex list of different types', description: 'Complex list of different types',
html: '<!doctype html><html><body><ul class="bullet"><li>one</li><li>two</li><li>0</li><li>1</li><li>2<ul class="bullet"><li>3</li><li>4</li></ul></li></ul><ol class="number"><li>item<ol class="number"><li>item1</li><li>item2</li></ol></li></ol></body></html>', html: '<!doctype html><html><body><ul class="bullet"><li>one</li><li>two</li><li>0</li><li>1</li><li>2<ul class="bullet"><li>3</li><li>4</li></ul></li></ul><ol class="number"><li>item<ol class="number"><li>item1</li><li>item2</li></ol></li></ol></body></html>',
wantLineAttribs: [ wantAlines: [
'*0*1*2+1+3', '*0*2*6+1+3',
'*0*1*2+1+3', '*0*2*6+1+3',
'*0*1*2+1+1', '*0*2*6+1+1',
'*0*1*2+1+1', '*0*2*6+1+1',
'*0*1*2+1+1', '*0*2*6+1+1',
'*0*3*2+1+1', '*0*3*6+1+1',
'*0*3*2+1+1', '*0*3*6+1+1',
'*0*4*2*5+1+4', '*0*4*6*7+1+4',
'*0*6*2*7+1+5', '*0*5*6*8+1+5',
'*0*6*2*7+1+5', '*0*5*6*8+1+5',
], ],
wantText: [ wantText: [
'*one', '*one',
@ -53,147 +82,174 @@ const tests = {
'*item2', '*item2',
], ],
}, },
ul: { {
description: 'Tests if uls properly get attributes', description: 'Tests if uls properly get attributes',
html: '<html><body><ul><li>a</li><li>b</li></ul><div>div</div><p>foo</p></body></html>', html: '<html><body><ul><li>a</li><li>b</li></ul><div>div</div><p>foo</p></body></html>',
wantLineAttribs: ['*0*1*2+1+1', '*0*1*2+1+1', '+3', '+3'], wantAlines: [
'*0*2*6+1+1',
'*0*2*6+1+1',
'+3',
'+3',
],
wantText: ['*a', '*b', 'div', 'foo'], wantText: ['*a', '*b', 'div', 'foo'],
}, },
ulIndented: { {
description: 'Tests if indented uls properly get attributes', description: 'Tests if indented uls properly get attributes',
html: '<html><body><ul><li>a</li><ul><li>b</li></ul><li>a</li></ul><p>foo</p></body></html>', html: '<html><body><ul><li>a</li><ul><li>b</li></ul><li>a</li></ul><p>foo</p></body></html>',
wantLineAttribs: ['*0*1*2+1+1', '*0*3*2+1+1', '*0*1*2+1+1', '+3'], wantAlines: [
'*0*2*6+1+1',
'*0*3*6+1+1',
'*0*2*6+1+1',
'+3',
],
wantText: ['*a', '*b', '*a', 'foo'], wantText: ['*a', '*b', '*a', 'foo'],
}, },
ol: { {
description: 'Tests if ols properly get line numbers when in a normal OL', description: 'Tests if ols properly get line numbers when in a normal OL',
html: '<html><body><ol><li>a</li><li>b</li><li>c</li></ol><p>test</p></body></html>', html: '<html><body><ol><li>a</li><li>b</li><li>c</li></ol><p>test</p></body></html>',
wantLineAttribs: ['*0*1*2*3+1+1', '*0*1*2*3+1+1', '*0*1*2*3+1+1', '+4'], wantAlines: [
'*0*4*6*7+1+1',
'*0*4*6*7+1+1',
'*0*4*6*7+1+1',
'+4',
],
wantText: ['*a', '*b', '*c', 'test'], wantText: ['*a', '*b', '*c', 'test'],
noteToSelf: 'Ensure empty P does not induce line attribute marker, wont this break the editor?', noteToSelf: 'Ensure empty P does not induce line attribute marker, wont this break the editor?',
}, },
lineDoBreakInOl: { {
description: 'A single completely empty line break within an ol should reset count if OL is closed off..', description: 'A single completely empty line break within an ol should reset count if OL is closed off..',
html: '<html><body><ol><li>should be 1</li></ol><p>hello</p><ol><li>should be 1</li><li>should be 2</li></ol><p></p></body></html>', html: '<html><body><ol><li>should be 1</li></ol><p>hello</p><ol><li>should be 1</li><li>should be 2</li></ol><p></p></body></html>',
wantLineAttribs: ['*0*1*2*3+1+b', '+5', '*0*1*2*4+1+b', '*0*1*2*4+1+b', ''], wantAlines: [
'*0*4*6*7+1+b',
'+5',
'*0*4*6*8+1+b',
'*0*4*6*8+1+b',
'',
],
wantText: ['*should be 1', 'hello', '*should be 1', '*should be 2', ''], wantText: ['*should be 1', 'hello', '*should be 1', '*should be 2', ''],
noteToSelf: "Shouldn't include attribute marker in the <p> line", noteToSelf: "Shouldn't include attribute marker in the <p> line",
}, },
testP: { {
description: 'A single <p></p> should create a new line', description: 'A single <p></p> should create a new line',
html: '<html><body><p></p><p></p></body></html>', html: '<html><body><p></p><p></p></body></html>',
wantLineAttribs: ['', ''], wantAlines: ['', ''],
wantText: ['', ''], wantText: ['', ''],
noteToSelf: '<p></p>should create a line break but not break numbering', noteToSelf: '<p></p>should create a line break but not break numbering',
}, },
nestedOl: { {
description: 'Tests if ols properly get line numbers when in a normal OL', description: 'Tests if ols properly get line numbers when in a normal OL #2',
html: '<html><body>a<ol><li>b<ol><li>c</li></ol></ol>notlist<p>foo</p></body></html>', html: '<html><body>a<ol><li>b<ol><li>c</li></ol></ol>notlist<p>foo</p></body></html>',
wantLineAttribs: ['+1', '*0*1*2*3+1+1', '*0*4*2*5+1+1', '+7', '+3'], wantAlines: [
'+1',
'*0*4*6*7+1+1',
'*0*5*6*8+1+1',
'+7',
'+3',
],
wantText: ['a', '*b', '*c', 'notlist', 'foo'], wantText: ['a', '*b', '*c', 'notlist', 'foo'],
noteToSelf: 'Ensure empty P does not induce line attribute marker, wont this break the editor?', noteToSelf: 'Ensure empty P does not induce line attribute marker, wont this break the editor?',
}, },
nestedOl2: { {
description: 'First item being an UL then subsequent being OL will fail', description: 'First item being an UL then subsequent being OL will fail',
html: '<html><body><ul><li>a<ol><li>b</li><li>c</li></ol></li></ul></body></html>', html: '<html><body><ul><li>a<ol><li>b</li><li>c</li></ol></li></ul></body></html>',
wantLineAttribs: ['+1', '*0*1*2*3+1+1', '*0*4*2*5+1+1'], wantAlines: ['+1', '*0*1*2*3+1+1', '*0*4*2*5+1+1'],
wantText: ['a', '*b', '*c'], wantText: ['a', '*b', '*c'],
noteToSelf: 'Ensure empty P does not induce line attribute marker, wont this break the editor?', noteToSelf: 'Ensure empty P does not induce line attribute marker, wont this break the editor?',
disabled: true, disabled: true,
}, },
lineDontBreakOL: { {
description: 'A single completely empty line break within an ol should NOT reset count', description: 'A single completely empty line break within an ol should NOT reset count',
html: '<html><body><ol><li>should be 1</li><p></p><li>should be 2</li><li>should be 3</li></ol><p></p></body></html>', html: '<html><body><ol><li>should be 1</li><p></p><li>should be 2</li><li>should be 3</li></ol><p></p></body></html>',
wantLineAttribs: [], wantAlines: [],
wantText: ['*should be 1', '*should be 2', '*should be 3'], wantText: ['*should be 1', '*should be 2', '*should be 3'],
noteToSelf: "<p></p>should create a line break but not break numbering -- This is what I can't get working!", noteToSelf: "<p></p>should create a line break but not break numbering -- This is what I can't get working!",
disabled: true, disabled: true,
}, },
ignoreAnyTagsOutsideBody: { {
description: 'Content outside body should be ignored', description: 'Content outside body should be ignored',
html: '<html><head><title>title</title><style></style></head><body>empty<br></body></html>', html: '<html><head><title>title</title><style></style></head><body>empty<br></body></html>',
wantLineAttribs: ['+5'], wantAlines: ['+5'],
wantText: ['empty'], wantText: ['empty'],
}, },
lineWithMultipleSpaces: { {
description: 'Multiple spaces should be preserved', description: 'Multiple spaces should be preserved',
html: '<html><body>Text with more than one space.<br></body></html>', html: '<html><body>Text with more than one space.<br></body></html>',
wantLineAttribs: ['+10'], wantAlines: ['+10'],
wantText: ['Text with more than one space.'], wantText: ['Text with more than one space.'],
}, },
lineWithMultipleNonBreakingAndNormalSpaces: { {
description: 'non-breaking and normal space should be preserved', description: 'non-breaking and normal space should be preserved',
html: '<html><body>Text&nbsp;with&nbsp; more&nbsp;&nbsp;&nbsp;than &nbsp;one space.<br></body></html>', html: '<html><body>Text&nbsp;with&nbsp; more&nbsp;&nbsp;&nbsp;than &nbsp;one space.<br></body></html>',
wantLineAttribs: ['+10'], wantAlines: ['+10'],
wantText: ['Text with more than one space.'], wantText: ['Text with more than one space.'],
}, },
multiplenbsp: { {
description: 'Multiple nbsp should be preserved', description: 'Multiple nbsp should be preserved',
html: '<html><body>&nbsp;&nbsp;<br></body></html>', html: '<html><body>&nbsp;&nbsp;<br></body></html>',
wantLineAttribs: ['+2'], wantAlines: ['+2'],
wantText: [' '], wantText: [' '],
}, },
multipleNonBreakingSpaceBetweenWords: { {
description: 'Multiple nbsp between words ', description: 'Multiple nbsp between words ',
html: '<html><body>&nbsp;&nbsp;word1&nbsp;&nbsp;word2&nbsp;&nbsp;&nbsp;word3<br></body></html>', html: '<html><body>&nbsp;&nbsp;word1&nbsp;&nbsp;word2&nbsp;&nbsp;&nbsp;word3<br></body></html>',
wantLineAttribs: ['+m'], wantAlines: ['+m'],
wantText: [' word1 word2 word3'], wantText: [' word1 word2 word3'],
}, },
nonBreakingSpacePreceededBySpaceBetweenWords: { {
description: 'A non-breaking space preceded by a normal space', description: 'A non-breaking space preceded by a normal space',
html: '<html><body> &nbsp;word1 &nbsp;word2 &nbsp;word3<br></body></html>', html: '<html><body> &nbsp;word1 &nbsp;word2 &nbsp;word3<br></body></html>',
wantLineAttribs: ['+l'], wantAlines: ['+l'],
wantText: [' word1 word2 word3'], wantText: [' word1 word2 word3'],
}, },
nonBreakingSpaceFollowededBySpaceBetweenWords: { {
description: 'A non-breaking space followed by a normal space', description: 'A non-breaking space followed by a normal space',
html: '<html><body>&nbsp; word1&nbsp; word2&nbsp; word3<br></body></html>', html: '<html><body>&nbsp; word1&nbsp; word2&nbsp; word3<br></body></html>',
wantLineAttribs: ['+l'], wantAlines: ['+l'],
wantText: [' word1 word2 word3'], wantText: [' word1 word2 word3'],
}, },
spacesAfterNewline: { {
description: 'Don\'t collapse spaces that follow a newline', description: 'Don\'t collapse spaces that follow a newline',
html: '<!doctype html><html><body>something<br> something<br></body></html>', html: '<!doctype html><html><body>something<br> something<br></body></html>',
wantLineAttribs: ['+9', '+m'], wantAlines: ['+9', '+m'],
wantText: ['something', ' something'], wantText: ['something', ' something'],
}, },
spacesAfterNewlineP: { {
description: 'Don\'t collapse spaces that follow a empty paragraph', description: 'Don\'t collapse spaces that follow a empty paragraph',
html: '<!doctype html><html><body>something<p></p> something<br></body></html>', html: '<!doctype html><html><body>something<p></p> something<br></body></html>',
wantLineAttribs: ['+9', '', '+m'], wantAlines: ['+9', '', '+m'],
wantText: ['something', '', ' something'], wantText: ['something', '', ' something'],
}, },
spacesAtEndOfLine: { {
description: 'Don\'t collapse spaces that preceed/follow a newline', description: 'Don\'t collapse spaces that preceed/follow a newline',
html: '<html><body>something <br> something<br></body></html>', html: '<html><body>something <br> something<br></body></html>',
wantLineAttribs: ['+l', '+m'], wantAlines: ['+l', '+m'],
wantText: ['something ', ' something'], wantText: ['something ', ' something'],
}, },
spacesAtEndOfLineP: { {
description: 'Don\'t collapse spaces that preceed/follow a empty paragraph', description: 'Don\'t collapse spaces that preceed/follow a empty paragraph',
html: '<html><body>something <p></p> something<br></body></html>', html: '<html><body>something <p></p> something<br></body></html>',
wantLineAttribs: ['+l', '', '+m'], wantAlines: ['+l', '', '+m'],
wantText: ['something ', '', ' something'], wantText: ['something ', '', ' something'],
}, },
nonBreakingSpacesAfterNewlines: { {
description: 'Don\'t collapse non-breaking spaces that follow a newline', description: 'Don\'t collapse non-breaking spaces that follow a newline',
html: '<html><body>something<br>&nbsp;&nbsp;&nbsp;something<br></body></html>', html: '<html><body>something<br>&nbsp;&nbsp;&nbsp;something<br></body></html>',
wantLineAttribs: ['+9', '+c'], wantAlines: ['+9', '+c'],
wantText: ['something', ' something'], wantText: ['something', ' something'],
}, },
nonBreakingSpacesAfterNewlinesP: { {
description: 'Don\'t collapse non-breaking spaces that follow a paragraph', description: 'Don\'t collapse non-breaking spaces that follow a paragraph',
html: '<html><body>something<p></p>&nbsp;&nbsp;&nbsp;something<br></body></html>', html: '<html><body>something<p></p>&nbsp;&nbsp;&nbsp;something<br></body></html>',
wantLineAttribs: ['+9', '', '+c'], wantAlines: ['+9', '', '+c'],
wantText: ['something', '', ' something'], wantText: ['something', '', ' something'],
}, },
preserveSpacesInsideElements: { {
description: 'Preserve all spaces when multiple are present', description: 'Preserve all spaces when multiple are present',
html: '<html><body>Need <span> more </span> space<i> s </i> !<br></body></html>', html: '<html><body>Need <span> more </span> space<i> s </i> !<br></body></html>',
wantLineAttribs: ['+h*0+4+2'], wantAlines: ['+h*1+4+2'],
wantText: ['Need more space s !'], wantText: ['Need more space s !'],
}, },
preserveSpacesAcrossNewlines: { {
description: 'Newlines and multiple spaces across newlines should be preserved', description: 'Newlines and multiple spaces across newlines should be preserved',
html: ` html: `
<html><body>Need <html><body>Need
@ -201,25 +257,25 @@ const tests = {
space space
<i> s </i> <i> s </i>
!<br></body></html>`, !<br></body></html>`,
wantLineAttribs: ['+19*0+4+b'], wantAlines: ['+19*1+4+b'],
wantText: ['Need more space s !'], wantText: ['Need more space s !'],
}, },
multipleNewLinesAtBeginning: { {
description: 'Multiple new lines at the beginning should be preserved', description: 'Multiple new lines at the beginning should be preserved',
html: '<html><body><br><br><p></p><p></p>first line<br><br>second line<br></body></html>', html: '<html><body><br><br><p></p><p></p>first line<br><br>second line<br></body></html>',
wantLineAttribs: ['', '', '', '', '+a', '', '+b'], wantAlines: ['', '', '', '', '+a', '', '+b'],
wantText: ['', '', '', '', 'first line', '', 'second line'], wantText: ['', '', '', '', 'first line', '', 'second line'],
}, },
multiLineParagraph: { {
description: 'A paragraph with multiple lines should not loose spaces when lines are combined', description: 'A paragraph with multiple lines should not loose spaces when lines are combined',
html: `<html><body><p> html: `<html><body><p>
а б в г ґ д е є ж з и і ї й к л м н о а б в г ґ д е є ж з и і ї й к л м н о
п р с т у ф х ц ч ш щ ю я ь</p> п р с т у ф х ц ч ш щ ю я ь</p>
</body></html>`, </body></html>`,
wantLineAttribs: ['+1t'], wantAlines: ['+1t'],
wantText: ['а б в г ґ д е є ж з и і ї й к л м н о п р с т у ф х ц ч ш щ ю я ь'], wantText: ['а б в г ґ д е є ж з и і ї й к л м н о п р с т у ф х ц ч ш щ ю я ь'],
}, },
multiLineParagraphWithPre: { {
description: 'lines in preformatted text should be kept intact', description: 'lines in preformatted text should be kept intact',
html: `<html><body><p> html: `<html><body><p>
а б в г ґ д е є ж з и і ї й к л м н о</p><pre>multiple а б в г ґ д е є ж з и і ї й к л м н о</p><pre>multiple
@ -229,7 +285,7 @@ pre
</pre><p>п р с т у ф х ц ч ш щ ю я </pre><p>п р с т у ф х ц ч ш щ ю я
ь</p> ь</p>
</body></html>`, </body></html>`,
wantLineAttribs: ['+11', '+8', '+5', '+2', '+3', '+r'], wantAlines: ['+11', '+8', '+5', '+2', '+3', '+r'],
wantText: [ wantText: [
'а б в г ґ д е є ж з и і ї й к л м н о', 'а б в г ґ д е є ж з и і ї й к л м н о',
'multiple', 'multiple',
@ -239,85 +295,100 @@ pre
'п р с т у ф х ц ч ш щ ю я ь', 'п р с т у ф х ц ч ш щ ю я ь',
], ],
}, },
preIntroducesASpace: { {
description: 'pre should be on a new line not preceded by a space', description: 'pre should be on a new line not preceded by a space',
html: `<html><body><p> html: `<html><body><p>
1 1
</p><pre>preline </p><pre>preline
</pre></body></html>`, </pre></body></html>`,
wantLineAttribs: ['+6', '+7'], wantAlines: ['+6', '+7'],
wantText: [' 1 ', 'preline'], wantText: [' 1 ', 'preline'],
}, },
dontDeleteSpaceInsideElements: { {
description: 'Preserve spaces on the beginning and end of a element', description: 'Preserve spaces on the beginning and end of a element',
html: '<html><body>Need<span> more </span>space<i> s </i>!<br></body></html>', html: '<html><body>Need<span> more </span>space<i> s </i>!<br></body></html>',
wantLineAttribs: ['+f*0+3+1'], wantAlines: ['+f*1+3+1'],
wantText: ['Need more space s !'], wantText: ['Need more space s !'],
}, },
dontDeleteSpaceOutsideElements: { {
description: 'Preserve spaces outside elements', description: 'Preserve spaces outside elements',
html: '<html><body>Need <span>more</span> space <i>s</i> !<br></body></html>', html: '<html><body>Need <span>more</span> space <i>s</i> !<br></body></html>',
wantLineAttribs: ['+g*0+1+2'], wantAlines: ['+g*1+1+2'],
wantText: ['Need more space s !'], wantText: ['Need more space s !'],
}, },
dontDeleteSpaceAtEndOfElement: { {
description: 'Preserve spaces at the end of an element', description: 'Preserve spaces at the end of an element',
html: '<html><body>Need <span>more </span>space <i>s </i>!<br></body></html>', html: '<html><body>Need <span>more </span>space <i>s </i>!<br></body></html>',
wantLineAttribs: ['+g*0+2+1'], wantAlines: ['+g*1+2+1'],
wantText: ['Need more space s !'], wantText: ['Need more space s !'],
}, },
dontDeleteSpaceAtBeginOfElements: { {
description: 'Preserve spaces at the start of an element', description: 'Preserve spaces at the start of an element',
html: '<html><body>Need<span> more</span> space<i> s</i> !<br></body></html>', html: '<html><body>Need<span> more</span> space<i> s</i> !<br></body></html>',
wantLineAttribs: ['+f*0+2+2'], wantAlines: ['+f*1+2+2'],
wantText: ['Need more space s !'], wantText: ['Need more space s !'],
}, },
}; ];
describe(__filename, function () { describe(__filename, function () {
for (const test of Object.keys(tests)) { for (const tc of testCases) {
const testObj = tests[test]; describe(tc.description, function () {
describe(test, function () { let apool;
if (testObj.disabled) { let result;
return xit('DISABLED:', test, function (done) {
done();
});
}
it(testObj.description, async function () { before(async function () {
const {window: {document}} = new jsdom.JSDOM(testObj.html); if (tc.disabled) return this.skip();
// Create an empty attribute pool const {window: {document}} = new jsdom.JSDOM(tc.html);
const apool = new AttributePool(); apool = new AttributePool();
// Convert a dom tree into a list of lines and attribute liens // To reduce test fragility, the attribute pool is seeded with `knownAttribs`, and all
// using the content collector object // attributes in `tc.wantAlines` must be in `knownAttribs`. (This guarantees that attribute
// numbers do not change if the attribute processing code changes.)
for (const attrib of knownAttribs) apool.putAttrib(attrib);
for (const aline of tc.wantAlines) {
const opIter = Changeset.opIterator(aline);
while (opIter.hasNext()) {
const op = opIter.next();
Changeset.eachAttribNumber(op.attribs, (n) => assert(n < knownAttribs.length));
}
}
const cc = contentcollector.makeContentCollector(true, null, apool); const cc = contentcollector.makeContentCollector(true, null, apool);
cc.collectContent(document.body); cc.collectContent(document.body);
const result = cc.finish(); result = cc.finish();
const gotAttributes = result.lineAttribs; });
const wantAttributes = testObj.wantLineAttribs;
const gotText = new Array(result.lines);
const wantText = testObj.wantText;
assert.deepEqual(gotText[0], wantText); it('text matches', async function () {
assert.deepEqual(gotAttributes, wantAttributes); assert.deepEqual(result.lines, tc.wantText);
});
it('alines match', async function () {
assert.deepEqual(result.lineAttribs, tc.wantAlines);
});
it('attributes are sorted in canonical order', async function () {
const gotAttribs = [];
const wantAttribs = [];
for (const aline of result.lineAttribs) {
const gotAlineAttribs = [];
gotAttribs.push(gotAlineAttribs);
const wantAlineAttribs = [];
wantAttribs.push(wantAlineAttribs);
const opIter = Changeset.opIterator(aline);
while (opIter.hasNext()) {
const op = opIter.next();
const gotOpAttribs = [];
gotAlineAttribs.push(gotOpAttribs);
const wantOpAttribs = [];
wantAlineAttribs.push(wantOpAttribs);
Changeset.eachAttribNumber(op.attribs, (n) => {
const attrib = apool.getAttrib(n);
gotOpAttribs.push(attrib);
wantOpAttribs.push(attrib);
});
wantOpAttribs.sort(([keyA], [keyB]) => (keyA > keyB ? 1 : 0) - (keyA < keyB ? 1 : 0));
}
}
assert.deepEqual(gotAttribs, wantAttribs);
}); });
}); });
} }
}); });
function arraysEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length !== b.length) return false;
// If you don't care about the order of the elements inside
// the array, you should sort both arrays here.
// Please note that calling sort on an array will modify that array.
// you might want to clone your array first.
for (let i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}