Moved to ts (#6593)

* Moved to ts

* Fixed type check

* Removed js suffixes

* Migrated to ts

* Fixed ts.

* Fixed type check

* Installed missing d ts
This commit is contained in:
SamTV12345 2024-08-17 20:14:36 +02:00 committed by GitHub
parent 5ee2c4e7f8
commit 7e3ad03e2f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
81 changed files with 961 additions and 830 deletions

View file

@ -1,17 +1,18 @@
'use strict';
const AttributeMap = require('../../../static/js/AttributeMap.js');
const AttributePool = require('../../../static/js/AttributePool');
const attributes = require('../../../static/js/attributes');
import AttributeMap from '../../../static/js/AttributeMap';
import AttributePool from '../../../static/js/AttributePool';
import attributes from '../../../static/js/attributes';
import {expect, describe, it, beforeEach} from 'vitest'
import {Attribute} from "../../../static/js/types/Attribute";
describe('AttributeMap', function () {
const attribs = [
const attribs: Attribute[] = [
['foo', 'bar'],
['baz', 'bif'],
['emptyValue', ''],
];
let pool: { eachAttrib: (arg0: () => number) => void; putAttrib: (arg0: string[]) => any; getAttrib: (arg0: number) => any; };
let pool: AttributePool;
const getPoolSize = () => {
let n = 0;
@ -70,12 +71,14 @@ describe('AttributeMap', function () {
describe(desc as string, function () {
it('key is coerced to string', async function () {
const m = new AttributeMap(pool);
// @ts-ignore
m.set(input, 'value');
expect(m.get(want)).to.equal('value');
});
it('value is coerced to string', async function () {
const m = new AttributeMap(pool);
// @ts-ignore
m.set('key', input);
expect(m.get('key')).to.equal(want);
});
@ -122,6 +125,7 @@ describe('AttributeMap', function () {
// @ts-ignore
args[0] = attributes.attribsToString(attributes.sort([...args[0]]), pool);
}
// @ts-ignore
return AttributeMap.prototype[funcName].call(m, ...args);
};

View file

@ -2,14 +2,15 @@
import {APool} from "../../../node/types/PadType";
const AttributePool = require('../../../static/js/AttributePool');
const attributes = require('../../../static/js/attributes');
import AttributePool from '../../../static/js/AttributePool';
import attributes from '../../../static/js/attributes';
import {expect, describe, it, beforeEach} from 'vitest';
import {Attribute} from "../../../static/js/types/Attribute";
describe('attributes', function () {
const attribs = [['foo', 'bar'], ['baz', 'bif']];
let pool: APool;
const attribs: Attribute[] = [['foo', 'bar'], ['baz', 'bif']];
let pool: AttributePool;
beforeEach(async function () {
pool = new AttributePool();
@ -45,6 +46,7 @@ describe('attributes', function () {
];
for (const [input, want] of testCases) {
it(`${JSON.stringify(input)} -> ${JSON.stringify(want)}`, async function () {
// @ts-ignore
const got = [...attributes.decodeAttribString(input)];
expect(JSON.stringify(got)).to.equal(JSON.stringify(want));
});
@ -61,6 +63,7 @@ describe('attributes', function () {
];
for (const [desc, input] of testCases) {
it(desc as string, async function () {
// @ts-ignore
expect(attributes.encodeAttribString(input)).to.equal('*0*1');
});
}
@ -78,6 +81,7 @@ describe('attributes', function () {
];
for (const [input, wantErr] of testCases) {
it(JSON.stringify(input), async function () {
// @ts-ignore
expect(() => attributes.encodeAttribString(input)).toThrowError(wantErr as RegExp);
});
}
@ -97,6 +101,7 @@ describe('attributes', function () {
];
for (const [input, want] of testCases) {
it(`${JSON.stringify(input)} -> ${JSON.stringify(want)}`, async function () {
// @ts-ignore
expect(attributes.encodeAttribString(input)).to.equal(want);
});
}
@ -117,6 +122,7 @@ describe('attributes', function () {
for (const [desc, input] of testCases) {
it(desc as string, async function () {
// @ts-ignore
const gotAttribs = [...attributes.attribsFromNums(input, pool)];
expect(JSON.stringify(gotAttribs)).to.equal(JSON.stringify(attribs));
});
@ -136,6 +142,7 @@ describe('attributes', function () {
];
for (const [input, wantErr] of testCases) {
it(JSON.stringify(input), async function () {
// @ts-ignore
expect(() => [...attributes.attribsFromNums(input, pool)]).toThrowError(wantErr as RegExp);
});
}
@ -151,6 +158,7 @@ describe('attributes', function () {
];
for (const [input, want] of testCases) {
it(`${JSON.stringify(input)} -> ${JSON.stringify(want)}`, async function () {
// @ts-ignore
const gotAttribs = [...attributes.attribsFromNums(input, pool)];
expect(JSON.stringify(gotAttribs)).to.equal(JSON.stringify(want));
});
@ -172,6 +180,7 @@ describe('attributes', function () {
for (const [desc, input] of testCases) {
it(desc as string, async function () {
// @ts-ignore
const gotNums = [...attributes.attribsToNums(input, pool)];
expect(JSON.stringify(gotNums)).to.equal(JSON.stringify([0, 1]));
});
@ -182,6 +191,7 @@ describe('attributes', function () {
const testCases = [null, [null]];
for (const input of testCases) {
it(JSON.stringify(input), async function () {
// @ts-ignore
expect(() => [...attributes.attribsToNums(input, pool)]).toThrowError();
});
}
@ -197,6 +207,7 @@ describe('attributes', function () {
];
for (const [input, want] of testCases) {
it(`${JSON.stringify(input)} -> ${JSON.stringify(want)}`, async function () {
// @ts-ignore
const got = [...attributes.attribsToNums(input, pool)];
expect(JSON.stringify(got)).to.equal(JSON.stringify(want));
});
@ -211,6 +222,7 @@ describe('attributes', function () {
];
for (const [input, want] of testCases) {
it(`${JSON.stringify(input)} -> ${JSON.stringify(want)}`, async function () {
// @ts-ignore
const got = [...attributes.attribsToNums(input, pool)];
expect(JSON.stringify(got)).to.equal(JSON.stringify(want));
expect(JSON.stringify(pool.getAttrib(attribs.length)))
@ -234,6 +246,7 @@ describe('attributes', function () {
['value is coerced to string', [['key', inputVal]], [['key', wantVal]]],
]) {
it(desc as string, async function () {
// @ts-ignore
const gotNums = [...attributes.attribsToNums(inputAttribs, pool)];
// Each attrib in inputAttribs is expected to be new to the pool.
const wantNums = [...Array(attribs.length + 1).keys()].slice(attribs.length);
@ -265,6 +278,7 @@ describe('attributes', function () {
];
for (const [input, wantErr] of testCases) {
it(JSON.stringify(input), async function () {
// @ts-ignore
expect(() => [...attributes.attribsFromString(input, pool)]).toThrowError(wantErr);
});
}
@ -280,6 +294,7 @@ describe('attributes', function () {
];
for (const [input, want] of testCases) {
it(`${JSON.stringify(input)} -> ${JSON.stringify(want)}`, async function () {
// @ts-ignore
const gotAttribs = [...attributes.attribsFromString(input, pool)];
expect(JSON.stringify(gotAttribs)).to.equal(JSON.stringify(want));
});
@ -297,6 +312,7 @@ describe('attributes', function () {
for (const [desc, input] of testCases) {
it(desc as string, async function () {
// @ts-ignore
const got = attributes.attribsToString(input, pool);
expect(got).to.equal('*0*1');
});
@ -307,6 +323,7 @@ describe('attributes', function () {
const testCases = [null, [null]];
for (const input of testCases) {
it(JSON.stringify(input), async function () {
// @ts-ignore
expect(() => attributes.attribsToString(input, pool)).toThrowError();
});
}
@ -322,6 +339,7 @@ describe('attributes', function () {
];
for (const [input, want] of testCases) {
it(`${JSON.stringify(input)} -> ${JSON.stringify(want)}`, async function () {
// @ts-ignore
const got = attributes.attribsToString(input, pool);
expect(got).to.equal(want);
});
@ -336,6 +354,7 @@ describe('attributes', function () {
];
for (const [input, want] of testCases) {
it(`${JSON.stringify(input)} -> ${JSON.stringify(want)}`, async function () {
// @ts-ignore
const got = attributes.attribsToString(input, pool);
expect(got).to.equal(want);
expect(JSON.stringify(pool.getAttrib(attribs.length)))

View file

@ -1,398 +0,0 @@
'use strict';
/*
* While importexport tests target the `setHTML` API endpoint, which is nearly identical to what
* happens when a user manually imports a document via the UI, the contentcollector tests here don't
* use rehype to process the document. Rehype removes spaces and newĺines were applicable, so the
* expected results here can differ from importexport.js.
*
* If you add tests here, please also add them to importexport.js
*/
import {APool} from "../../../node/types/PadType";
const AttributePool = require('../../../static/js/AttributePool');
const Changeset = require('../../../static/js/Changeset');
const assert = require('assert').strict;
const attributes = require('../../../static/js/attributes');
const contentcollector = require('../../../static/js/contentcollector');
const jsdom = require('jsdom');
import {describe, it, beforeAll, test} from 'vitest';
// All test case `wantAlines` values must only refer to attributes in this list so that the
// 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',
html: '<!doctype html><html><body><ol><li>one</li><li><ol><li>1.1</li></ol></li><li>two</li></ol></body></html>',
wantAlines: [
'*0*4*6*7+1+3',
'*0*5*6*8+1+3',
'*0*4*6*8+1+3',
],
wantText: [
'*one', '*1.1', '*two',
],
},
{
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>',
wantAlines: [
'*0*2*6+1+3',
'*0*2*6+1+3',
'*0*2*6+1+1',
'*0*2*6+1+1',
'*0*2*6+1+1',
'*0*3*6+1+1',
'*0*3*6+1+1',
'*0*4*6*7+1+4',
'*0*5*6*8+1+5',
'*0*5*6*8+1+5',
],
wantText: [
'*one',
'*two',
'*0',
'*1',
'*2',
'*3',
'*4',
'*item',
'*item1',
'*item2',
],
},
{
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>',
wantAlines: [
'*0*2*6+1+1',
'*0*2*6+1+1',
'+3',
'+3',
],
wantText: ['*a', '*b', 'div', 'foo'],
},
{
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>',
wantAlines: [
'*0*2*6+1+1',
'*0*3*6+1+1',
'*0*2*6+1+1',
'+3',
],
wantText: ['*a', '*b', '*a', 'foo'],
},
{
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>',
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'],
noteToSelf: 'Ensure empty P does not induce line attribute marker, wont this break the editor?',
},
{
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>',
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', ''],
noteToSelf: "Shouldn't include attribute marker in the <p> line",
},
{
description: 'A single <p></p> should create a new line',
html: '<html><body><p></p><p></p></body></html>',
wantAlines: ['', ''],
wantText: ['', ''],
noteToSelf: '<p></p>should create a line break but not break numbering',
},
{
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>',
wantAlines: [
'+1',
'*0*4*6*7+1+1',
'*0*5*6*8+1+1',
'+7',
'+3',
],
wantText: ['a', '*b', '*c', 'notlist', 'foo'],
noteToSelf: 'Ensure empty P does not induce line attribute marker, wont this break the editor?',
},
{
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>',
wantAlines: ['+1', '*0*1*2*3+1+1', '*0*4*2*5+1+1'],
wantText: ['a', '*b', '*c'],
noteToSelf: 'Ensure empty P does not induce line attribute marker, wont this break the editor?',
disabled: true,
},
{
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>',
wantAlines: [],
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!",
disabled: true,
},
{
description: 'Content outside body should be ignored',
html: '<html><head><title>title</title><style></style></head><body>empty<br></body></html>',
wantAlines: ['+5'],
wantText: ['empty'],
},
{
description: 'Multiple spaces should be preserved',
html: '<html><body>Text with more than one space.<br></body></html>',
wantAlines: ['+10'],
wantText: ['Text with more than one space.'],
},
{
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>',
wantAlines: ['+10'],
wantText: ['Text with more than one space.'],
},
{
description: 'Multiple nbsp should be preserved',
html: '<html><body>&nbsp;&nbsp;<br></body></html>',
wantAlines: ['+2'],
wantText: [' '],
},
{
description: 'Multiple nbsp between words ',
html: '<html><body>&nbsp;&nbsp;word1&nbsp;&nbsp;word2&nbsp;&nbsp;&nbsp;word3<br></body></html>',
wantAlines: ['+m'],
wantText: [' word1 word2 word3'],
},
{
description: 'A non-breaking space preceded by a normal space',
html: '<html><body> &nbsp;word1 &nbsp;word2 &nbsp;word3<br></body></html>',
wantAlines: ['+l'],
wantText: [' word1 word2 word3'],
},
{
description: 'A non-breaking space followed by a normal space',
html: '<html><body>&nbsp; word1&nbsp; word2&nbsp; word3<br></body></html>',
wantAlines: ['+l'],
wantText: [' word1 word2 word3'],
},
{
description: 'Don\'t collapse spaces that follow a newline',
html: '<!doctype html><html><body>something<br> something<br></body></html>',
wantAlines: ['+9', '+m'],
wantText: ['something', ' something'],
},
{
description: 'Don\'t collapse spaces that follow a empty paragraph',
html: '<!doctype html><html><body>something<p></p> something<br></body></html>',
wantAlines: ['+9', '', '+m'],
wantText: ['something', '', ' something'],
},
{
description: 'Don\'t collapse spaces that preceed/follow a newline',
html: '<html><body>something <br> something<br></body></html>',
wantAlines: ['+l', '+m'],
wantText: ['something ', ' something'],
},
{
description: 'Don\'t collapse spaces that preceed/follow a empty paragraph',
html: '<html><body>something <p></p> something<br></body></html>',
wantAlines: ['+l', '', '+m'],
wantText: ['something ', '', ' something'],
},
{
description: 'Don\'t collapse non-breaking spaces that follow a newline',
html: '<html><body>something<br>&nbsp;&nbsp;&nbsp;something<br></body></html>',
wantAlines: ['+9', '+c'],
wantText: ['something', ' something'],
},
{
description: 'Don\'t collapse non-breaking spaces that follow a paragraph',
html: '<html><body>something<p></p>&nbsp;&nbsp;&nbsp;something<br></body></html>',
wantAlines: ['+9', '', '+c'],
wantText: ['something', '', ' something'],
},
{
description: 'Preserve all spaces when multiple are present',
html: '<html><body>Need <span> more </span> space<i> s </i> !<br></body></html>',
wantAlines: ['+h*1+4+2'],
wantText: ['Need more space s !'],
},
{
description: 'Newlines and multiple spaces across newlines should be preserved',
html: `
<html><body>Need
<span> more </span>
space
<i> s </i>
!<br></body></html>`,
wantAlines: ['+19*1+4+b'],
wantText: ['Need more space s !'],
},
{
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>',
wantAlines: ['', '', '', '', '+a', '', '+b'],
wantText: ['', '', '', '', 'first line', '', 'second line'],
},
{
description: 'A paragraph with multiple lines should not loose spaces when lines are combined',
html: `<html><body><p>
а б в г ґ д е є ж з и і ї й к л м н о
п р с т у ф х ц ч ш щ ю я ь</p>
</body></html>`,
wantAlines: ['+1t'],
wantText: ['а б в г ґ д е є ж з и і ї й к л м н о п р с т у ф х ц ч ш щ ю я ь'],
},
{
description: 'lines in preformatted text should be kept intact',
html: `<html><body><p>
а б в г ґ д е є ж з и і ї й к л м н о</p><pre>multiple
lines
in
pre
</pre><p>п р с т у ф х ц ч ш щ ю я
ь</p>
</body></html>`,
wantAlines: ['+11', '+8', '+5', '+2', '+3', '+r'],
wantText: [
'а б в г ґ д е є ж з и і ї й к л м н о',
'multiple',
'lines',
'in',
'pre',
'п р с т у ф х ц ч ш щ ю я ь',
],
},
{
description: 'pre should be on a new line not preceded by a space',
html: `<html><body><p>
1
</p><pre>preline
</pre></body></html>`,
wantAlines: ['+6', '+7'],
wantText: [' 1 ', 'preline'],
},
{
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>',
wantAlines: ['+f*1+3+1'],
wantText: ['Need more space s !'],
},
{
description: 'Preserve spaces outside elements',
html: '<html><body>Need <span>more</span> space <i>s</i> !<br></body></html>',
wantAlines: ['+g*1+1+2'],
wantText: ['Need more space s !'],
},
{
description: 'Preserve spaces at the end of an element',
html: '<html><body>Need <span>more </span>space <i>s </i>!<br></body></html>',
wantAlines: ['+g*1+2+1'],
wantText: ['Need more space s !'],
},
{
description: 'Preserve spaces at the start of an element',
html: '<html><body>Need<span> more</span> space<i> s</i> !<br></body></html>',
wantAlines: ['+f*1+2+2'],
wantText: ['Need more space s !'],
},
];
describe(__filename, function () {
for (const tc of testCases) {
describe(tc.description, function () {
let apool: APool;
let result: {
lines: string[],
lineAttribs: string[],
};
if (tc.disabled) {
test.skip('If disabled we do not run the test');
return;
}
beforeAll(async function () {
const {window: {document}} = new jsdom.JSDOM(tc.html);
apool = new AttributePool();
// To reduce test fragility, the attribute pool is seeded with `knownAttribs`, and all
// 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) {
for (const op of Changeset.deserializeOps(aline)) {
for (const n of attributes.decodeAttribString(op.attribs)) {
assert(n < knownAttribs.length);
}
}
}
const cc = contentcollector.makeContentCollector(true, null, apool);
cc.collectContent(document.body);
result = cc.finish();
console.log(result);
});
it('text matches', async function () {
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:string[][][] = [];
const wantAttribs = [];
for (const aline of result.lineAttribs) {
const gotAlineAttribs:string[][] = [];
gotAttribs.push(gotAlineAttribs);
const wantAlineAttribs:string[] = [];
wantAttribs.push(wantAlineAttribs);
for (const op of Changeset.deserializeOps(aline)) {
const gotOpAttribs:string[] = [...attributes.attribsFromString(op.attribs, apool)];
gotAlineAttribs.push(gotOpAttribs);
wantAlineAttribs.push(attributes.sort([...gotOpAttribs]));
}
}
assert.deepEqual(gotAttribs, wantAttribs);
});
});
}
});

View file

@ -1,19 +1,19 @@
import {MapArrayType} from "../../../node/types/MapType";
const {padutils} = require('../../../static/js/pad_utils');
import padutils from '../../../static/js/pad_utils';
import {describe, it, expect, afterEach, beforeAll} from "vitest";
describe(__filename, function () {
describe('warnDeprecated', function () {
const {warnDeprecated} = padutils;
const {warnDeprecatedFlags, warnDeprecated} = padutils;
const backups:MapArrayType<any> = {};
beforeAll(async function () {
backups.logger = warnDeprecated.logger;
backups.logger = warnDeprecatedFlags.logger;
});
afterEach(async function () {
warnDeprecated.logger = backups.logger;
delete warnDeprecated._rl; // Reset internal rate limiter state.
warnDeprecatedFlags.logger = backups.logger;
delete warnDeprecatedFlags._rl; // Reset internal rate limiter state.
});
/*it('includes the stack', async function () {
@ -25,13 +25,13 @@ describe(__filename, function () {
it('rate limited', async function () {
let got = 0;
warnDeprecated.logger = {warn: () => ++got};
warnDeprecatedFlags.logger = {warn: () => ++got};
warnDeprecated(); // Initialize internal rate limiter state.
const {period} = warnDeprecated._rl;
const {period} = warnDeprecatedFlags._rl!;
got = 0;
const testCases = [[0, 1], [0, 1], [period - 1, 1], [period, 2]];
for (const [now, want] of testCases) { // In a loop so that the stack trace is the same.
warnDeprecated._rl.now = () => now;
warnDeprecatedFlags._rl!.now = () => now;
warnDeprecated();
expect(got).toEqual(want);
}

View file

@ -1,12 +1,13 @@
'use strict';
const SkipList = require('ep_etherpad-lite/static/js/skiplist');
import SkipList from 'ep_etherpad-lite/static/js/skiplist';
import {expect, describe, it} from 'vitest';
describe('skiplist.js', function () {
it('rejects null keys', async function () {
const skiplist = new SkipList();
for (const key of [undefined, null]) {
// @ts-ignore
expect(() => skiplist.push({key})).toThrowError();
}
});

View file

@ -2,12 +2,11 @@
import {MapArrayType} from "../../node/types/MapType";
const AttributePool = require('../../static/js/AttributePool');
const apiHandler = require('../../node/handler/APIHandler');
import AttributePool from '../../static/js/AttributePool';
const assert = require('assert').strict;
const io = require('socket.io-client');
const log4js = require('log4js');
const {padutils} = require('../../static/js/pad_utils');
import padutils from '../../static/js/pad_utils';
const process = require('process');
const server = require('../../node/server');
const setCookieParser = require('set-cookie-parser');

View file

@ -8,7 +8,7 @@ const db = require('../../../node/db/DB');
const importEtherpad = require('../../../node/utils/ImportEtherpad');
const padManager = require('../../../node/db/PadManager');
const plugins = require('../../../static/js/pluginfw/plugin_defs');
const {randomString} = require('../../../static/js/pad_utils');
import {randomString} from '../../../static/js/pad_utils';
describe(__filename, function () {
let padId: string;

View file

@ -3,7 +3,7 @@
import {MapArrayType} from "../../../node/types/MapType";
import {PluginDef} from "../../../node/types/PartType";
const ChatMessage = require('../../../static/js/ChatMessage');
import ChatMessage from '../../../static/js/ChatMessage';
const {Pad} = require('../../../node/db/Pad');
const assert = require('assert').strict;
const common = require('../common');
@ -103,10 +103,14 @@ describe(__filename, function () {
checkHook('chatNewMessage', ({message}) => {
assert(message != null);
assert(message instanceof ChatMessage);
assert.equal(message.authorId, authorId);
assert.equal(message.text, this.test!.title);
assert(message.time >= start);
assert(message.time <= Date.now());
// @ts-ignore
assert.equal(message!.authorId, authorId);
// @ts-ignore
assert.equal(message!.text, this.test!.title);
// @ts-ignore
assert(message!.time >= start);
// @ts-ignore
assert(message!.time <= Date.now());
}),
sendChat(socket, {text: this.test!.title}),
]);
@ -153,7 +157,9 @@ describe(__filename, function () {
const customMetadata = {foo: this.test!.title};
await Promise.all([
checkHook('chatNewMessage', ({message}) => {
// @ts-ignore
message.text = modifiedText;
// @ts-ignore
message.customMetadata = customMetadata;
}),
(async () => {

View file

@ -11,16 +11,17 @@
import {APool} from "../../../node/types/PadType";
const AttributePool = require('../../../static/js/AttributePool');
import AttributePool from '../../../static/js/AttributePool';
const Changeset = require('../../../static/js/Changeset');
const assert = require('assert').strict;
const attributes = require('../../../static/js/attributes');
import attributes from '../../../static/js/attributes';
const contentcollector = require('../../../static/js/contentcollector');
const jsdom = require('jsdom');
import jsdom from 'jsdom';
import {Attribute} from "../../../static/js/types/Attribute";
// All test case `wantAlines` values must only refer to attributes in this list so that the
// attribute numbers do not change due to changes in pool insertion order.
const knownAttribs = [
const knownAttribs: Attribute[] = [
['insertorder', 'first'],
['italic', 'true'],
['list', 'bullet1'],
@ -336,7 +337,7 @@ pre
describe(__filename, function () {
for (const tc of testCases) {
describe(tc.description, function () {
let apool: APool;
let apool: AttributePool;
let result: {
lines: string[],
lineAttribs: string[],
@ -376,11 +377,12 @@ describe(__filename, function () {
for (const aline of result.lineAttribs) {
const gotAlineAttribs:string[][] = [];
gotAttribs.push(gotAlineAttribs);
const wantAlineAttribs:string[] = [];
const wantAlineAttribs:Attribute[] = [];
wantAttribs.push(wantAlineAttribs);
for (const op of Changeset.deserializeOps(aline)) {
const gotOpAttribs:string[] = [...attributes.attribsFromString(op.attribs, apool)];
const gotOpAttribs = [...attributes.attribsFromString(op.attribs, apool)] as unknown as Attribute;
gotAlineAttribs.push(gotOpAttribs);
// @ts-ignore
wantAlineAttribs.push(attributes.sort([...gotOpAttribs]));
}
}