1
0
mirror of synced 2025-12-10 16:27:57 +08:00
Files
Mergely/test/markup.spec.js

388 lines
16 KiB
JavaScript

const simple = require('simple-mock');
require('codemirror')
require('../src/mergely');
describe('markup', () => {
let editor;
let editorId = 0;
function init(options) {
editor = new window.Mergely(`#mergely-${editorId - 1}`, options);
return editor;
};
beforeEach(() => {
const div = document.createElement('div');
div.id = `mergely-${editorId++}`;
div.style.margin = '0px';
div.style.height = '275px';
document.querySelector('body').appendChild(div);
});
afterEach(() => {
if (editor._diffView.settings._debug) {
return;
}
editor && editor.unbind();
simple.restore();
editor.el.parentNode.removeChild(editor.el);
});
const LHS_LINE_START = '.mergely.lhs.d.CodeMirror-linebackground.start';
const LHS_LINE_END = '.mergely.lhs.d.CodeMirror-linebackground.end';
const LHS_LINE_NO_START = '.mergely.lhs.d.no-start.end.CodeMirror-linebackground';
const LHS_LINE_NO_END = '.mergely.lhs.d.CodeMirror-linebackground.start.no-end';
const LHS_LINE = 'span.mergely.d.lhs';
const RHS_LINE_NO_START = '.mergely.rhs.a.no-start.end.CodeMirror-linebackground';
const RHS_LINE_NO_END = '.mergely.rhs.a.CodeMirror-linebackground.start.no-end';
const RHS_LINE_START = '.mergely.rhs.a.CodeMirror-linebackground.start';
const RHS_LINE_END = '.mergely.rhs.a.CodeMirror-linebackground.end';
const RHS_LINE_TEXT = 'span.mergely.a.rhs';
const LHS_CHANGE_START = '.mergely.lhs.c.CodeMirror-linebackground.start';
const LHS_CHANGE_END = '.mergely.lhs.c.CodeMirror-linebackground.end';
const LHS_CHANGE_START_AND_END = '.mergely.lhs.c.CodeMirror-linebackground.start.end';
const RHS_CHANGE_START = '.mergely.rhs.c.CodeMirror-linebackground.start';
const RHS_CHANGE_END = '.mergely.rhs.c.CodeMirror-linebackground.end';
const LHS_INLINE_TEXT = '.mergely.lhs.ind';
const RHS_INLINE_TEXT = '.mergely.rhs.ina';
const opts = [
{
name: 'Added and removed from the start and end (lhs)',
lhs: 'the quick brown fox\njumped over the lazy dog\n',
rhs: '\nthe quick red fox\njumped over the hairy dog\n',
check: (editor) => {
expect(editor.querySelectorAll(LHS_LINE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE + '.cid-0')).to.have.length(2);
expect(editor.querySelectorAll(LHS_LINE_NO_START + '.cid-1')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_NO_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_START + '.cid-1')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_END + '.cid-1')).to.have.length(1);
}
},
{
name: 'Added and removed from the start and end (rhs)',
lhs: '\nthe quick red fox\njumped over the hairy dog\n',
rhs: 'the quick brown fox\njumped over the lazy dog\n',
check: (editor) => {
expect(editor.querySelectorAll(LHS_LINE_NO_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE_START + '.cid-1')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE_END + '.cid-1')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_NO_START + '.cid-1')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_TEXT + '.cid-0')).to.have.length(2);
}
},
{
name: 'Added and removed from the middle (lhs)',
lhs: '\nthe quick red fox\njumped over the hairy dog\n\n',
rhs: '\n\nthe quick brown fox\njumped over the lazy dog\n',
check: (editor) => {
expect(editor.querySelectorAll(LHS_LINE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE + '.cid-0')).to.have.length(2);
expect(editor.querySelectorAll(LHS_LINE_NO_START + '.cid-1')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_NO_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_START + '.cid-1')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_END + '.cid-1')).to.have.length(1);
}
},
{
name: 'Added and removed from the middle (rhs)',
lhs: '\n\nthe quick brown fox\njumped over the lazy dog\n',
rhs: '\nthe quick red fox\njumped over the hairy dog\n\n',
check: (editor) => {
expect(editor.querySelectorAll(LHS_LINE_NO_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE_START + '.cid-1')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE_END + '.cid-1')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_NO_START + '.cid-1')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_TEXT + '.cid-0')).to.have.length(2);
}
},
{
name: 'One line with the other empty (lhs)',
lhs: 'the quick brown fox\n',
rhs: '',
check: (editor) => {
expect(editor.querySelectorAll(LHS_LINE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_NO_END + '.cid-0')).to.have.length(1);
}
},
{
name: 'One line with the other empty (rhs)',
lhs: '',
rhs: 'the quick brown fox\n',
check: (editor) => {
expect(editor.querySelectorAll(LHS_LINE_NO_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_END + '.cid-0')).to.have.length(1);
}
},
{
name: 'Multiple lines with the other empty (lhs)',
lhs: 'the quick brown fox\njumped over the lazy dog\n',
rhs: '',
check: (editor) => {
expect(editor.querySelectorAll(LHS_LINE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_NO_END + '.cid-0')).to.have.length(1);
}
},
{
name: 'Multiple lines with the other empty (rhs)',
lhs: '',
rhs: 'the quick brown fox\njumped over the lazy dog\n',
check: (editor) => {
expect(editor.querySelectorAll(LHS_LINE_NO_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_END + '.cid-0')).to.have.length(1);
}
},
{
name: 'Added and removed from the end (lhs)',
lhs: 'the quick brown fox\njumped over the lazy dog',
rhs: 'the quick brown fox\njumped over the lazy dog\n\nand the fence',
check: (editor) => {
expect(editor.querySelectorAll(LHS_LINE_NO_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_END + '.cid-0')).to.have.length(1);
}
},
{
name: 'Added and removed from the end (rhs)',
lhs: 'the quick brown fox\njumped over the lazy dog\n\nand the fence',
rhs: 'the quick brown fox\njumped over the lazy dog',
check: (editor) => {
expect(editor.querySelectorAll(LHS_LINE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_LINE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_LINE_NO_START + '.cid-0')).to.have.length(1);
}
},
{
name: 'No changes (empty)',
lhs: '',
rhs: '',
check: (editor) => {
expect(editor.querySelectorAll('.mergely.lhs')).to.have.length(0);
expect(editor.querySelectorAll('.mergely.rhs')).to.have.length(0);
}
},
{
name: 'No changes (with text)',
lhs: 'the quick brown fox\njumped over the lazy dog',
rhs: 'the quick brown fox\njumped over the lazy dog',
check: (editor) => {
expect(editor.querySelectorAll('.mergely.lhs')).to.have.length(0);
expect(editor.querySelectorAll('.mergely.rhs')).to.have.length(0);
}
},
{
name: 'Changed lines (lhs)',
lhs: 'the quick red fox\njumped over the hairy dog',
rhs: 'the quick brown fox\njumped over the lazy dog',
check: (editor) => {
expect(editor.querySelectorAll(LHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_CHANGE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_END + '.cid-0')).to.have.length(1);
const lhs_spans = editor.querySelectorAll(LHS_INLINE_TEXT + '.cid-0');
expect(lhs_spans).to.have.length(3);
expect(lhs_spans[0].innerText).to.equal('ed');
expect(lhs_spans[1].innerText).to.equal('h');
expect(lhs_spans[2].innerText).to.equal('ir');
const rhs_spans = editor.querySelectorAll(RHS_INLINE_TEXT + '.cid-0');
expect(rhs_spans).to.have.length(4);
expect(rhs_spans[0].innerText).to.equal('b');
expect(rhs_spans[1].innerText).to.equal('own');
expect(rhs_spans[2].innerText).to.equal('l');
expect(rhs_spans[3].innerText).to.equal('z');
}
},
{
name: 'Changed lines (rhs)',
lhs: 'the quick brown fox\njumped over the lazy dog',
rhs: 'the quick red fox\njumped over the hairy dog',
check: (editor) => {
expect(editor.querySelectorAll(LHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_CHANGE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_END + '.cid-0')).to.have.length(1);
const lhs_spans = editor.querySelectorAll(LHS_INLINE_TEXT + '.cid-0');
expect(lhs_spans).to.have.length(4);
expect(lhs_spans[0].innerText).to.equal('b');
expect(lhs_spans[1].innerText).to.equal('own');
expect(lhs_spans[2].innerText).to.equal('l');
expect(lhs_spans[3].innerText).to.equal('z');
const rhs_spans = editor.querySelectorAll(RHS_INLINE_TEXT + '.cid-0');
expect(rhs_spans).to.have.length(3);
expect(rhs_spans[0].innerText).to.equal('ed');
expect(rhs_spans[1].innerText).to.equal('h');
expect(rhs_spans[2].innerText).to.equal('ir');
}
},
{
name: 'single word single diacritic non-spacing marks',
lhs: 'كلمة',
rhs: 'كَلمة',
check: (editor) => {
expect(editor.querySelectorAll(LHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_CHANGE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_END + '.cid-0')).to.have.length(1);
const lhs_spans = editor.querySelectorAll(LHS_INLINE_TEXT + '.cid-0');
expect(lhs_spans).to.have.length(1);
expect(lhs_spans[0].innerText).to.equal('ك');
const rhs_spans = editor.querySelectorAll(RHS_INLINE_TEXT + '.cid-0');
expect(rhs_spans).to.have.length(1);
expect(rhs_spans[0].innerText).to.equal('كَ');
}
},
{
name: 'single word multiple diacritic non-spacing marks',
lhs: ['\u006E', '\u0061', '\u0314', '\u0065'].join(''), // na̔e
rhs: ['\u006E', '\u0061', '\u0314', '\u034A', '\u0065'].join(''), // na̔͊e
check: (editor) => {
expect(editor.querySelectorAll(LHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_CHANGE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_END + '.cid-0')).to.have.length(1);
const lhs_spans = editor.querySelectorAll(LHS_INLINE_TEXT + '.cid-0');
expect(lhs_spans).to.have.length(1);
expect(lhs_spans[0].innerText).to.equal(['\u0061', '\u0314'].join(''));
const rhs_spans = editor.querySelectorAll(RHS_INLINE_TEXT + '.cid-0');
expect(rhs_spans).to.have.length(1);
expect(rhs_spans[0].innerText).to.equal('a̔͊');
}
},
{
name: 'multiple words diacritic non-spacing marks',
lhs: 'كلمة اخرى',
rhs: 'كْلمة اخرى',
check: (editor) => {
expect(editor.querySelectorAll(LHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_CHANGE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_END + '.cid-0')).to.have.length(1);
const lhs_spans = editor.querySelectorAll(LHS_INLINE_TEXT + '.cid-0');
expect(lhs_spans).to.have.length(1);
expect(lhs_spans[0].innerText).to.equal('ك');
const rhs_spans = editor.querySelectorAll(RHS_INLINE_TEXT + '.cid-0');
expect(rhs_spans).to.have.length(1);
expect(rhs_spans[0].innerText).to.equal('كْ');
}
},
{
name: 'nonnormalizable diacritic non-spacing marks',
lhs: 'naeg',
// there are 2 marks on 'e', tilde (0303) and x (0353)
rhs: ['\u006E', '\u0061', '\u0353', '\u0065', '\u0353', '\u0303', '\u0067'].join(''),
check: (editor) => {
expect(editor.querySelectorAll(LHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_CHANGE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_END + '.cid-0')).to.have.length(1);
const lhs_spans = editor.querySelectorAll(LHS_INLINE_TEXT + '.cid-0');
expect(lhs_spans).to.have.length(1);
expect(lhs_spans[0].innerText).to.equal('ae');
const rhs_spans = editor.querySelectorAll(RHS_INLINE_TEXT + '.cid-0');
expect(rhs_spans).to.have.length(1);
expect(rhs_spans[0].innerText).to.equal(
['\u0061', '\u0353', '\u0065', '\u0353', '\u0303'].join('')
);
}
},
{
name: 'nonnormalizable diacritic non-spacing marks',
lhs: [
'\u0065', '\u0353', '\u0303',
'\u0065', '\u0353', '\u0303',
'\u0065', '\u0353', '\u0303',
'x',
'\u0065', '\u0353', '\u0303',
].join(''),
// there are 2 marks on 'e', tilde (0303) and x (0353)
rhs: [
'\u0065', '\u0353', '\u0303',
'\u0065', '\u0353', '\u0303',
'\u0065', '\u0353', '\u0303',
'y',
'\u0065', '\u0353', '\u0303',
].join(''),
check: (editor) => {
expect(editor.querySelectorAll(LHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_CHANGE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_END + '.cid-0')).to.have.length(1);
const lhs_spans = editor.querySelectorAll(LHS_INLINE_TEXT + '.cid-0');
expect(lhs_spans).to.have.length(1);
expect(lhs_spans[0].innerText).to.equal('x');
const rhs_spans = editor.querySelectorAll(RHS_INLINE_TEXT + '.cid-0');
expect(rhs_spans).to.have.length(1);
expect(rhs_spans[0].innerText).to.equal('y');
}
},
{
name: 'Changes with non-letter chars',
lhs: '~# 00 == ! (dog) \n',
rhs: '~? 11 ++ ] (fox) .\n',
check: (editor) => {
expect(editor.querySelectorAll(LHS_CHANGE_START_AND_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_INLINE_TEXT + '.cid-0')).to.have.length(6);
expect(editor.querySelectorAll(RHS_INLINE_TEXT + '.cid-0')).to.have.length(7);
const lhs_changes = editor.querySelectorAll(LHS_INLINE_TEXT + '.cid-0');
const rhs_changes = editor.querySelectorAll(RHS_INLINE_TEXT + '.cid-0');
const lhs_values = [];
for (const value of lhs_changes.values()) {
lhs_values.push(value.innerText);
}
const rhs_values = [];
for (const value of rhs_changes.values()) {
rhs_values.push(value.innerText);
}
expect(lhs_values).to.deep.equal(['#', '00', '==', '!', 'd', 'g']);
expect(rhs_values).to.deep.equal(['?', '11', '++', ']', 'f', 'x', '.']);
}
},
];
// to debug, add `only: true` to the test `opts` above, and run `npm run debug`
opts.forEach((opt, i) => {
const itfn = opt.only ? it.only : it;
const debug = !!opt.only;
itfn(`markup-case-${i} should markup ${opt.name}`, function (done) {
const editor = init({
height: 100,
license: 'lgpl-separate-notice',
change_timeout: 0,
_debug: debug,
lhs: (setValue) => setValue(opt.lhs),
rhs: (setValue) => setValue(opt.rhs)
});
const test = () => {
try {
opt.check(editor.el);
done();
} catch (ex) {
done(ex);
}
};
editor.once('updated', test);
});
});
});