Skip to content

Commit 210877d

Browse files
authored
chore(compass-editor, compass-query-bar): replace ace editor with codemirror in query bar (#4150)
* chore(compass-field-store, compass-editor): keep field type as field description in field store for completions * chore(compass-editor): add inline editor based on codemirror; contain editor reflows; add support for custom commands * chore(compass-query-bar): replace ace inline editor with codemirror one in query bar * chore(compass-fields-store): update fields store tests * chore(compass-editor): adjust autocopmleter styles * chore(e2e): update tests to expect codemirror instead of ace * chore(e2e): fix eslint check * chore(e2e): fix reset button disabled check * chore(query-bar): do not rely on query state state to disable the button * chore(e2e): fix flaky run find operation for macos * chore(compass-editor): insert tab instead of line indent on tab press * chore(compass-editor): fix 1px height added to the first line when placeholder is shown * chore(editor): tab size 2 * chore(e2e): reset preferences even if test failed; click apply until click is registered * chore(e2e): wait for modal to close; always reset maxtimems
1 parent ed8f90b commit 210877d

File tree

18 files changed

+437
-235
lines changed

18 files changed

+437
-235
lines changed

packages/compass-e2e-tests/helpers/commands/click-visible.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,11 @@ export async function clickVisible(
2626
if (options?.screenshot) {
2727
await browser.saveScreenshot(options.screenshot);
2828
}
29-
await clickElement.click();
29+
if (await clickElement.isEnabled()) {
30+
await clickElement.click();
31+
} else {
32+
throw new Error(
33+
`Trying to click ${selector}, but the element is not enabled`
34+
);
35+
}
3036
}

packages/compass-e2e-tests/helpers/commands/codemirror.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ export async function getCodemirrorEditorTextAll(
3535

3636
export async function setCodemirrorEditorValue(
3737
browser: CompassBrowser,
38-
text: string,
39-
selector: string = Selectors.DocumentJSONEntry
38+
selector: string,
39+
text: string
4040
) {
4141
await browser.execute(
4242
function (selector, text) {

packages/compass-e2e-tests/helpers/commands/get-query-id.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,9 @@ export async function getQueryId(
99
const queryBarSelectorElement = await browser.$(queryBarSelector);
1010
return queryBarSelectorElement.getAttribute('data-result-id');
1111
}
12+
13+
export async function getApplyId(browser: CompassBrowser, tabName: string) {
14+
const queryBarSelector = Selectors.queryBar(tabName);
15+
const queryBarSelectorElement = await browser.$(queryBarSelector);
16+
return queryBarSelectorElement.getAttribute('data-apply-id');
17+
}

packages/compass-e2e-tests/helpers/commands/run-find-operation.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ async function setFilter(
66
tabName: string,
77
value: string
88
) {
9-
await browser.setAceValue(
9+
await browser.setCodemirrorEditorValue(
1010
Selectors.queryBarOptionInputFilter(tabName),
1111
value
1212
);
@@ -17,7 +17,7 @@ async function setProject(
1717
tabName: string,
1818
value: string
1919
) {
20-
await browser.setAceValue(
20+
await browser.setCodemirrorEditorValue(
2121
Selectors.queryBarOptionInputProject(tabName),
2222
value
2323
);
@@ -28,15 +28,18 @@ export async function setSort(
2828
tabName: string,
2929
value: string
3030
) {
31-
await browser.setAceValue(Selectors.queryBarOptionInputSort(tabName), value);
31+
await browser.setCodemirrorEditorValue(
32+
Selectors.queryBarOptionInputSort(tabName),
33+
value
34+
);
3235
}
3336

3437
async function setCollation(
3538
browser: CompassBrowser,
3639
tabName: string,
3740
value: string
3841
) {
39-
await browser.setAceValue(
42+
await browser.setCodemirrorEditorValue(
4043
Selectors.queryBarOptionInputCollation(tabName),
4144
value
4245
);
@@ -102,14 +105,14 @@ async function maybeResetQuery(browser: CompassBrowser, tabName: string) {
102105
// look up the current resultId
103106
const initialResultId = await browser.getQueryId(tabName);
104107

105-
await resetButton.click();
106-
107-
// wait for the button to become disabled which should happen once it reset
108-
// all the filter fields
109108
await browser.waitUntil(async () => {
109+
// In some very rare cases on particularly slow machines in CI (looking at
110+
// you macos hosts) clicking doesn't register on the first try, to work
111+
// around that, we try to click with pause until the button is disabled
112+
await browser.clickVisible(Selectors.queryBarResetFilterButton(tabName));
113+
await browser.pause(50);
110114
return !(await resetButton.isEnabled());
111115
});
112-
113116
// now we can easily see if we get a new resultId
114117
// (which we should because resetting re-runs the query)
115118
await browser.waitUntil(async () => {
@@ -165,6 +168,7 @@ export async function runFindOperation(
165168
limit = '',
166169
// TODO(COMPASS-6606): allow for the same in other tabs with query bar
167170
waitForResult = true,
171+
expandOptions: keepOptionsExpanded = false,
168172
} = {}
169173
): Promise<void> {
170174
if (project || sort || maxTimeMS || collation || skip || limit) {
@@ -180,6 +184,10 @@ export async function runFindOperation(
180184
await collapseOptions(browser, tabName);
181185
}
182186

187+
if (keepOptionsExpanded) {
188+
await expandOptions(browser, tabName);
189+
}
190+
183191
await setFilter(browser, tabName, filter);
184192

185193
await browser.runFind(tabName, waitForResult);

packages/compass-e2e-tests/helpers/commands/run-find.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,19 @@ export async function runFind(
66
tabName: string,
77
waitForResult: boolean
88
): Promise<void> {
9-
// look up the current resultId
9+
// look up the current resultId and applyId
1010
const initialResultId = await browser.getQueryId(tabName);
11+
const initialApplyId = await browser.getApplyId(tabName);
1112

12-
await browser.clickVisible(Selectors.queryBarApplyFilterButton(tabName));
13+
// In some rare cases in ci (for example when clicking button in a query bar
14+
// right after closing a modal, clicks are not registering correctly on
15+
// certain machine types, in this case we continue clicking until we see that
16+
// applyId changed
17+
await browser.waitUntil(async () => {
18+
await browser.clickVisible(Selectors.queryBarApplyFilterButton(tabName));
19+
await browser.pause(50);
20+
return (await browser.getApplyId(tabName)) !== initialApplyId;
21+
});
1322

1423
if (waitForResult) {
1524
// now we can easily see if we get a new resultId

packages/compass-e2e-tests/tests/collection-documents-tab.test.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ describe('Collection documents tab', function () {
9191
let compass: Compass;
9292
let browser: CompassBrowser;
9393
let telemetry: Telemetry;
94+
let maxTimeMSBefore: string;
9495

9596
before(async function () {
9697
telemetry = await startTelemetryServer();
@@ -102,6 +103,7 @@ describe('Collection documents tab', function () {
102103
await createNumbersCollection();
103104
await browser.connectWithConnectionString();
104105
await browser.navigateToCollectionTab('test', 'numbers', 'Documents');
106+
maxTimeMSBefore = (await browser.getFeature('maxTimeMS')) as string;
105107
});
106108

107109
after(async function () {
@@ -110,6 +112,7 @@ describe('Collection documents tab', function () {
110112
});
111113

112114
afterEach(async function () {
115+
await browser.setFeature('maxTimeMS', maxTimeMSBefore);
113116
await afterTest(compass, this.currentTest);
114117
});
115118

@@ -220,10 +223,7 @@ describe('Collection documents tab', function () {
220223

221224
for (const maxTimeMSMode of ['ui', 'preference'] as const) {
222225
it(`supports maxTimeMS (set via ${maxTimeMSMode})`, async function () {
223-
let maxTimeMSBefore;
224226
if (maxTimeMSMode === 'preference') {
225-
maxTimeMSBefore = await browser.getFeature('maxTimeMS');
226-
227227
await browser.openSettingsModal();
228228
const settingsModal = await browser.$(Selectors.SettingsModal);
229229
await settingsModal.waitForDisplayed();
@@ -234,6 +234,7 @@ describe('Collection documents tab', function () {
234234
'1'
235235
);
236236
await browser.clickVisible(Selectors.SaveSettingsButton);
237+
await settingsModal.waitForDisplayed({ reverse: true });
237238
}
238239

239240
// execute a query that will take a long time, but set a maxTimeMS shorter than that
@@ -255,10 +256,6 @@ describe('Collection documents tab', function () {
255256
expect(errorText).to.include(
256257
'Operation exceeded time limit. Please try increasing the maxTimeMS for the query in the expanded filter options.'
257258
);
258-
259-
if (maxTimeMSMode === 'preference') {
260-
await browser.setFeature('maxTimeMS', maxTimeMSBefore);
261-
}
262259
});
263260
}
264261

@@ -400,8 +397,8 @@ FindIterable<Document> result = collection.find(filter);`);
400397
const newjson = JSON.stringify({ ...JSON.parse(json), j: 1234 });
401398

402399
await browser.setCodemirrorEditorValue(
403-
newjson,
404-
Selectors.DocumentJSONEntry
400+
Selectors.DocumentJSONEntry,
401+
newjson
405402
);
406403

407404
const footer = await document.$(Selectors.DocumentFooterMessage);
@@ -453,8 +450,8 @@ FindIterable<Document> result = collection.find(filter);`);
453450
});
454451

455452
await browser.setCodemirrorEditorValue(
456-
newjson,
457-
Selectors.DocumentJSONEntry
453+
Selectors.DocumentJSONEntry,
454+
newjson
458455
);
459456

460457
const footer = await document.$(Selectors.DocumentFooterMessage);
@@ -557,6 +554,7 @@ FindIterable<Document> result = collection.find(filter);`);
557554
const insertConfirm = await browser.$(Selectors.InsertConfirm);
558555
await insertConfirm.waitForEnabled();
559556
await browser.clickVisible(Selectors.InsertConfirm);
557+
await insertDialog.waitForDisplayed({ reverse: true });
560558

561559
await browser.runFindOperation('Documents', '{ i: 10042 }');
562560

packages/compass-e2e-tests/tests/in-use-encryption.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,8 +562,8 @@ describe('CSFLE / QE', function () {
562562
phoneNumber: '10101010',
563563
});
564564
await browser.setCodemirrorEditorValue(
565-
newjson,
566-
Selectors.DocumentJSONEntry
565+
Selectors.DocumentJSONEntry,
566+
newjson
567567
);
568568

569569
const footer = await document.$(Selectors.DocumentFooterMessage);

packages/compass-e2e-tests/tests/time-to-first-query.test.ts

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { expect } from 'chai';
22
import { beforeTests, afterTests, afterTest } from '../helpers/compass';
33
import type { Compass } from '../helpers/compass';
4-
import * as Selectors from '../helpers/selectors';
54
import { createNumbersCollection } from '../helpers/insert-data';
65

76
describe('Time to first query', function () {
@@ -32,23 +31,7 @@ describe('Time to first query', function () {
3231

3332
await browser.navigateToCollectionTab('test', 'numbers', 'Documents');
3433

35-
// search for the document with id == 42 and wait for just one result to appear
36-
const aceCommentElement = await browser.$(
37-
'[data-testid="query-bar-option-filter"] .ace_scroller'
38-
);
39-
await aceCommentElement.click();
40-
41-
await browser.keys('{ i: 42 }');
42-
const filterButtonElement = await browser.$(
43-
Selectors.queryBarApplyFilterButton('Documents')
44-
);
45-
await filterButtonElement.click();
46-
await browser.waitUntil(async () => {
47-
// we start off with 20 results (assuming no filter) and we expect to
48-
// have just one once the filter finishes
49-
const result = await browser.$$('.document-list .document');
50-
return result.length === 1;
51-
});
34+
await browser.runFindOperation('Documents', '{ i: 42 }');
5235

5336
const documentElementValue = await browser.$(
5437
'.document-list .document .element-value-is-int32'
@@ -68,23 +51,7 @@ describe('Time to first query', function () {
6851

6952
await browser.navigateToCollectionTab('test', 'numbers', 'Documents');
7053

71-
// search for the document with id == 42 and wait for just one result to appear
72-
const aceCommentElement = await browser.$(
73-
'[data-testid="query-bar-option-filter"] .ace_scroller'
74-
);
75-
await aceCommentElement.click();
76-
77-
await browser.keys('{ i: 42 }');
78-
const filterButtonElement = await browser.$(
79-
Selectors.queryBarApplyFilterButton('Documents')
80-
);
81-
await filterButtonElement.click();
82-
await browser.waitUntil(async () => {
83-
// we start off with 20 results (assuming no filter) and we expect to
84-
// have just one once the filter finishes
85-
const result = await browser.$$('.document-list .document');
86-
return result.length === 1;
87-
});
54+
await browser.runFindOperation('Documents', '{ i: 42 }');
8855

8956
const documentElementValue = await browser.$(
9057
'.document-list .document .element-value-is-int32'

packages/compass-editor/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ export { InlineEditor } from './inline-editor';
1111
export { prettify } from './prettify';
1212
export type { FormatOptions } from './prettify';
1313
export { Editor } from './multiline-editor';
14-
export { JSONEditor } from './json-editor';
15-
export type { EditorView } from './json-editor';
14+
export { JSONEditor, CodemirrorInlineEditor } from './json-editor';
15+
export type { EditorView, Command } from './json-editor';
1616
export { SyntaxHighlight } from './syntax-highlight';
1717
export { createDocumentAutocompleter } from './codemirror/document-autocompleter';
1818
export { createValidationAutocompleter } from './codemirror/validation-autocompleter';

0 commit comments

Comments
 (0)