Skip to content

Commit ea5f182

Browse files
committed
feat: emit lint event
test: ensure we validate linting in real world setup (no mocking)
1 parent 8a307ae commit ea5f182

2 files changed

Lines changed: 99 additions & 21 deletions

File tree

src/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ export default function FeelEditor({
8080
return;
8181
}
8282

83-
const messages = diagnosticEffects.flatMap(effect => effect.value);
83+
const diagnostics = diagnosticEffects.flatMap(effect => effect.value);
8484

85-
onLint(messages);
85+
this._events.emit('lint', { diagnostics });
8686
});
8787

8888
const keyHandler = EditorView.domEventHandlers(
@@ -130,6 +130,8 @@ export default function FeelEditor({
130130
extensions.push(EditorView.editable.of(false));
131131
}
132132

133+
this.on('lint', ({ diagnostics }) => onLint(diagnostics));
134+
133135
this._cmEditor = new EditorView({
134136
state: EditorState.create({
135137
doc: value,

test/spec/CodeEditor.spec.js

Lines changed: 95 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ import FeelEditor from '../../src/index.js';
22
import TestContainer from 'mocha-test-container-support';
33
import { EditorSelection } from '@codemirror/state';
44
import { lineNumbers } from '@codemirror/view';
5-
import { diagnosticCount, forceLinting } from '@codemirror/lint';
65
import { currentCompletions, startCompletion } from '@codemirror/autocomplete';
76
import { domify } from 'min-dom';
87

98
import { expect } from 'chai';
10-
import { spy, match } from 'sinon';
9+
import { spy } from 'sinon';
1110

1211
const singleStart = window.__env__ && window.__env__.SINGLE_START;
1312

@@ -501,7 +500,7 @@ return
501500
const diagnostics = await lint(editor);
502501

503502
// then
504-
expect(diagnostics).to.eql(0);
503+
expect(diagnostics).to.be.empty;
505504
});
506505

507506

@@ -529,7 +528,7 @@ return
529528
const diagnostics = await lint(editor);
530529

531530
// then
532-
expect(diagnostics).to.eql(0);
531+
expect(diagnostics).to.be.empty;
533532
});
534533

535534
});
@@ -549,7 +548,7 @@ return
549548
const diagnostics = await lint(editor);
550549

551550
// then
552-
expect(diagnostics).to.eql(1);
551+
expect(diagnostics).to.have.length(1);
553552
});
554553

555554

@@ -565,7 +564,7 @@ return
565564
const diagnostics = await lint(editor);
566565

567566
// then
568-
expect(diagnostics).to.eql(1);
567+
expect(diagnostics).to.have.length(1);
569568
});
570569

571570

@@ -581,7 +580,7 @@ return
581580
const diagnostics = await lint(editor);
582581

583582
// then
584-
expect(diagnostics).to.eql(1);
583+
expect(diagnostics).to.have.length(1);
585584
});
586585

587586

@@ -610,7 +609,9 @@ return
610609

611610
it('without errors', async function() {
612611
const initialValue = '15';
613-
const onLint = spy();
612+
const onLint = spy((diagnostics) => {
613+
expect(diagnostics).to.be.empty;
614+
});
614615

615616
const editor = new FeelEditor({
616617
container,
@@ -622,10 +623,76 @@ return
622623
await lint(editor);
623624

624625
// then
625-
// update done async
626626
expect(onLint).to.have.been.calledOnce;
627-
expect(onLint).to.have.been.calledWith(match.array);
628-
expect(onLint.args[0][0]).to.have.length(0);
627+
});
628+
629+
});
630+
631+
632+
it('should emit as <lint> event', async function() {
633+
const initialValue = '"unclosed string';
634+
const lintSpy = spy(({ diagnostics }) => {
635+
expect(diagnostics).to.have.length(1);
636+
});
637+
638+
const editor = new FeelEditor({
639+
container,
640+
value: initialValue
641+
});
642+
643+
editor.on('lint', lintSpy);
644+
645+
// when
646+
await lint(editor);
647+
648+
// then
649+
expect(lintSpy).to.have.been.calledOnce;
650+
});
651+
652+
653+
describe('should trigger after update', function() {
654+
655+
it('recovering from errors', async function() {
656+
const initialValue = '^15';
657+
658+
// given
659+
const editor = new FeelEditor({
660+
container,
661+
value: initialValue
662+
});
663+
664+
await lint(editor);
665+
666+
// when
667+
editor.setValue('20');
668+
669+
const diagnostics = await lint(editor);
670+
671+
// then
672+
// no more errors
673+
expect(diagnostics).to.be.empty;
674+
});
675+
676+
677+
it('indicating new error', async function() {
678+
const initialValue = '15';
679+
680+
// given
681+
const editor = new FeelEditor({
682+
container,
683+
value: initialValue
684+
});
685+
686+
await lint(editor);
687+
688+
// when
689+
editor.setValue('^15');
690+
691+
const diagnostics = await lint(editor);
692+
693+
// then
694+
// no more errors
695+
expect(diagnostics).to.have.length(1);
629696
});
630697

631698
});
@@ -1022,22 +1089,31 @@ async function expectEventually(fn) {
10221089
throw e;
10231090
}
10241091

1025-
function wait(ms = 0) {
1026-
return new Promise(resolve => setTimeout(resolve, ms));
1092+
function timeout(ms = 0) {
1093+
return new Promise((_resolve, reject) => setTimeout(reject, ms));
10271094
}
10281095

10291096
/**
1097+
* Awaits editor linting.
1098+
*
10301099
* @param {FeelEditor} editor
10311100
*
1032-
* @return {Promise<number>}
1101+
* @return {Promise<import('@codemirror/lint').Diagnostic[]>}
10331102
*/
10341103
async function lint(editor) {
1035-
const cm = getCm(editor);
10361104

1037-
// when
1038-
forceLinting(cm);
1105+
const lintPromise = new Promise((resolve, reject) => {
1106+
const handleLinted = ({ diagnostics }) => {
1107+
editor.off('lint', handleLinted);
1108+
1109+
resolve(diagnostics);
1110+
};
10391111

1040-
await wait();
1112+
editor.on('lint', handleLinted);
1113+
});
10411114

1042-
return diagnosticCount(cm.state);
1115+
return Promise.race([
1116+
timeout(1000),
1117+
lintPromise
1118+
]);
10431119
}

0 commit comments

Comments
 (0)