Skip to content

Commit bd28acc

Browse files
committed
update unit tests
1 parent c142156 commit bd28acc

File tree

11 files changed

+228
-36
lines changed

11 files changed

+228
-36
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"pretest": "pnpm run compile",
5656
"test": "pnpm run test-webview && pnpm run test-extension",
5757
"test-extension": "cross-env MDB_IS_TEST=true NODE_OPTIONS=--no-force-async-hooks-checks xvfb-maybe node ./out/test/runTest.js",
58-
"test-webview": "mocha -r ts-node/register --exit --grep=\"${MOCHA_GREP}\" --file ./src/test/setup-webview.ts src/test/suite/views/webview-app/**/*.test.tsx",
58+
"test-webview": "mocha -r ts-node/register --exit --grep=\"${MOCHA_GREP}\" --file ./src/test/setup-webview.ts \"src/test/suite/views/{webview-app,data-browsing-app}/**/*.test.tsx\"",
5959
"ai-accuracy-tests": "env TS_NODE_FILES=true mocha -r ts-node/register --grep=\"${MOCHA_GREP}\" --file ./src/test/ai-accuracy-tests/test-setup.ts ./src/test/ai-accuracy-tests/ai-accuracy-tests.ts",
6060
"analyze-bundle": "webpack --mode production --analyze",
6161
"vscode:prepublish": "pnpm run clean && pnpm run compile:constants && pnpm run compile:resources && webpack --mode production",

src/test/suite/explorer/collectionTreeItem.test.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@ suite('CollectionTreeItem Test Suite', function () {
5252

5353
const collectionChildren = await testCollectionTreeItem.getChildren();
5454

55-
assert.strictEqual(collectionChildren.length, 3);
55+
assert.strictEqual(collectionChildren.length, 4);
5656
assert.strictEqual(collectionChildren[0].label, 'Documents');
57-
assert.strictEqual(collectionChildren[1].label, 'Schema');
58-
assert.strictEqual(collectionChildren[2].label, 'Indexes');
57+
assert.strictEqual(collectionChildren[1].label, 'Documents');
58+
assert.strictEqual(collectionChildren[2].label, 'Schema');
59+
assert.strictEqual(collectionChildren[3].label, 'Indexes');
5960
});
6061

6162
test('when expanded it shows the document count in the description of the document list', async function () {
@@ -71,8 +72,10 @@ suite('CollectionTreeItem Test Suite', function () {
7172

7273
assert.strictEqual(collectionChildren[0].label, 'Documents');
7374
assert.strictEqual(collectionChildren[0].description, '5K');
75+
assert.strictEqual(collectionChildren[1].label, 'Documents');
76+
assert.strictEqual(collectionChildren[1].description, '5K');
7477
assert.strictEqual(
75-
collectionChildren[0].tooltip,
78+
collectionChildren[1].tooltip,
7679
'Collection Documents - 5000',
7780
);
7881
});

src/test/suite/mdbExtensionController.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ suite('MDBExtensionController Test Suite', function () {
490490
await testTreeItem.onDidExpand();
491491

492492
const collectionChildren = await testTreeItem.getChildren();
493-
const docListTreeItem = collectionChildren[0];
493+
const docListTreeItem = collectionChildren[1];
494494
assert.strictEqual(docListTreeItem.description, '9K');
495495
count = 10000;
496496
docListTreeItem.isExpanded = true;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import { expect } from 'chai';
4+
5+
import App from '../../../../views/data-browsing-app/app';
6+
7+
describe('Data Browsing App Component Test Suite', function () {
8+
it('it renders the preview page', function () {
9+
render(<App />);
10+
expect(screen.getByLabelText('Insert Document')).to.exist;
11+
});
12+
});
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
import React from 'react';
2+
import { expect } from 'chai';
3+
import { render, screen, waitFor } from '@testing-library/react';
4+
import userEvent from '@testing-library/user-event';
5+
import Sinon from 'sinon';
6+
import PreviewPage from '../../../../views/data-browsing-app/preview-page';
7+
import vscode from '../../../../views/data-browsing-app/vscode-api';
8+
import { PreviewMessageType } from '../../../../views/data-browsing-app/extension-app-message-constants';
9+
10+
describe('PreviewPage test suite', function () {
11+
afterEach(function () {
12+
Sinon.restore();
13+
});
14+
15+
it('should render the preview page with toolbar', function () {
16+
render(<PreviewPage />);
17+
expect(screen.getByLabelText('Insert Document')).to.exist;
18+
expect(screen.getByLabelText(/Sort order/)).to.exist;
19+
expect(screen.getByLabelText(/Items per page/)).to.exist;
20+
});
21+
22+
it('should request documents on mount', function () {
23+
const postMessageStub = Sinon.stub(vscode, 'postMessage');
24+
render(<PreviewPage />);
25+
26+
expect(postMessageStub).to.have.been.calledWith({
27+
command: PreviewMessageType.getDocuments,
28+
});
29+
});
30+
31+
it('should display loading state initially', function () {
32+
render(<PreviewPage />);
33+
expect(screen.getByText('Loading documents...')).to.exist;
34+
});
35+
36+
it('should display documents when loaded', async function () {
37+
render(<PreviewPage />);
38+
39+
// Simulate receiving documents from extension
40+
window.dispatchEvent(
41+
new MessageEvent('message', {
42+
data: {
43+
command: PreviewMessageType.loadDocuments,
44+
documents: [
45+
{ _id: '1', name: 'Test Document 1' },
46+
{ _id: '2', name: 'Test Document 2' },
47+
],
48+
totalCount: 2,
49+
},
50+
}),
51+
);
52+
53+
await waitFor(() => {
54+
expect(screen.queryByText('Loading documents...')).to.not.exist;
55+
});
56+
});
57+
58+
it('should send refresh request when refresh button is clicked', async function () {
59+
const postMessageStub = Sinon.stub(vscode, 'postMessage');
60+
render(<PreviewPage />);
61+
62+
// Wait for initial load to complete
63+
window.dispatchEvent(
64+
new MessageEvent('message', {
65+
data: {
66+
command: PreviewMessageType.loadDocuments,
67+
documents: [],
68+
totalCount: 0,
69+
},
70+
}),
71+
);
72+
73+
await waitFor(() => {
74+
expect(screen.queryByText('Loading documents...')).to.not.exist;
75+
});
76+
77+
const refreshButton = screen.getByTitle('Refresh');
78+
await userEvent.click(refreshButton);
79+
80+
expect(postMessageStub).to.have.been.calledWith({
81+
command: PreviewMessageType.refreshDocuments,
82+
});
83+
});
84+
85+
it('should send sort request when sort option changes', async function () {
86+
const postMessageStub = Sinon.stub(vscode, 'postMessage');
87+
render(<PreviewPage />);
88+
89+
// Wait for initial load
90+
window.dispatchEvent(
91+
new MessageEvent('message', {
92+
data: {
93+
command: PreviewMessageType.loadDocuments,
94+
documents: [],
95+
totalCount: 0,
96+
},
97+
}),
98+
);
99+
100+
await waitFor(() => {
101+
expect(screen.queryByText('Loading documents...')).to.not.exist;
102+
});
103+
104+
const sortSelect = screen.getByLabelText(/Sort order/);
105+
await userEvent.click(sortSelect);
106+
107+
const ascOption = screen.getByText('Ascending');
108+
await userEvent.click(ascOption);
109+
110+
expect(postMessageStub).to.have.been.calledWith({
111+
command: PreviewMessageType.sortDocuments,
112+
sort: 'asc',
113+
});
114+
});
115+
116+
it('should display "No documents to display" when there are no documents', async function () {
117+
render(<PreviewPage />);
118+
119+
window.dispatchEvent(
120+
new MessageEvent('message', {
121+
data: {
122+
command: PreviewMessageType.loadDocuments,
123+
documents: [],
124+
totalCount: 0,
125+
},
126+
}),
127+
);
128+
129+
await waitFor(() => {
130+
expect(screen.getByText('No documents to display')).to.exist;
131+
});
132+
});
133+
134+
it('should handle pagination correctly', async function () {
135+
const documents = Array.from({ length: 25 }, (_, i) => ({
136+
_id: `${i + 1}`,
137+
name: `Document ${i + 1}`,
138+
}));
139+
140+
render(<PreviewPage />);
141+
142+
window.dispatchEvent(
143+
new MessageEvent('message', {
144+
data: {
145+
command: PreviewMessageType.loadDocuments,
146+
documents,
147+
totalCount: 25,
148+
},
149+
}),
150+
);
151+
152+
await waitFor(() => {
153+
expect(screen.queryByText('Loading documents...')).to.not.exist;
154+
});
155+
156+
// Should show first 10 documents by default
157+
expect(screen.getByText('1-10 of 25')).to.exist;
158+
159+
// Click next page
160+
const nextButton = screen.getByLabelText('Next page');
161+
await userEvent.click(nextButton);
162+
163+
expect(screen.getByText('11-20 of 25')).to.exist;
164+
});
165+
});

src/test/suite/views/dataBrowsingController.test.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,13 @@ suite('DataBrowsingController Test Suite', function () {
263263
sandbox.stub(vscode.window, 'createWebviewPanel').returns({
264264
webview: {
265265
html: '',
266-
postMessage: (message): void => {
266+
postMessage: (message): Promise<boolean> => {
267267
expect(message.command).to.equal(PreviewMessageType.themeChanged);
268268
expect(message.darkMode).to.be.true;
269269
if (++callsSoFar === totalExpectedPostMessageCalls) {
270270
done();
271271
}
272+
return Promise.resolve(true);
272273
},
273274
onDidReceiveMessage: (): void => {},
274275
asWebviewUri: sandbox.stub().returns(''),
@@ -294,18 +295,23 @@ suite('DataBrowsingController Test Suite', function () {
294295

295296
test('removes panel from active panels when disposed', function () {
296297
const onDisposeCallback: (() => void)[] = [];
297-
298-
sandbox.stub(vscode.window, 'createWebviewPanel').returns({
299-
webview: {
300-
html: '',
301-
postMessage: sandbox.stub(),
302-
onDidReceiveMessage: sandbox.stub(),
303-
asWebviewUri: sandbox.stub().returns(''),
304-
},
305-
onDidDispose: (callback): void => {
306-
onDisposeCallback.push(callback);
307-
},
308-
} as unknown as vscode.WebviewPanel);
298+
const panels: vscode.WebviewPanel[] = [];
299+
300+
sandbox.stub(vscode.window, 'createWebviewPanel').callsFake(() => {
301+
const panel = {
302+
webview: {
303+
html: '',
304+
postMessage: sandbox.stub().resolves(true),
305+
onDidReceiveMessage: sandbox.stub(),
306+
asWebviewUri: sandbox.stub().returns(''),
307+
},
308+
onDidDispose: (callback): void => {
309+
onDisposeCallback.push(callback);
310+
},
311+
} as unknown as vscode.WebviewPanel;
312+
panels.push(panel);
313+
return panel;
314+
});
309315

310316
void testDataBrowsingController.openDataBrowser(
311317
mdbTestExtension.extensionContextStub,
@@ -361,4 +367,3 @@ suite('DataBrowsingController Test Suite', function () {
361367
});
362368
});
363369
});
364-

src/views/data-browsing-app/document-tree-view.tsx

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
useDarkMode,
1212
} from '@mongodb-js/compass-components';
1313

14-
1514
const documentTreeViewContainerStyles = css({
1615
marginBottom: spacing[200],
1716
});
@@ -127,8 +126,14 @@ const DocumentTreeView: React.FC<DocumentTreeViewProps> = ({ document }) => {
127126
};
128127

129128
// Get dynamic styles based on dark mode
130-
const keyStyles = cx(keyStylesBase, darkMode ? keyStylesDark : keyStylesLight);
131-
const dividerStyles = cx(dividerStylesBase, darkMode ? dividerStylesDark : dividerStylesLight);
129+
const keyStyles = cx(
130+
keyStylesBase,
131+
darkMode ? keyStylesDark : keyStylesLight,
132+
);
133+
const dividerStyles = cx(
134+
dividerStylesBase,
135+
darkMode ? dividerStylesDark : dividerStylesLight,
136+
);
132137

133138
const toggleExpanded = (key: string): void => {
134139
setExpandedKeys((prev) => {
@@ -176,7 +181,7 @@ const DocumentTreeView: React.FC<DocumentTreeViewProps> = ({ document }) => {
176181
const formatValue = (
177182
value: unknown,
178183
type: TreeNode['type'],
179-
isExpanded = true
184+
isExpanded = true,
180185
): string => {
181186
if (type === 'null') return 'null';
182187
if (type === 'boolean') return String(value);
@@ -223,7 +228,7 @@ const DocumentTreeView: React.FC<DocumentTreeViewProps> = ({ document }) => {
223228

224229
const renderExpandButton = (
225230
isExpanded: boolean,
226-
itemKey: string
231+
itemKey: string,
227232
): JSX.Element => (
228233
<button
229234
type="button"
@@ -252,7 +257,8 @@ const DocumentTreeView: React.FC<DocumentTreeViewProps> = ({ document }) => {
252257
<div key={index}>
253258
<div className={nodeRowStyles}>
254259
<div className={caretStyles}>
255-
{hasExpandableContent && renderExpandButton(isExpanded, itemKey)}
260+
{hasExpandableContent &&
261+
renderExpandButton(isExpanded, itemKey)}
256262
</div>
257263
<div className={keyValueContainerStyles}>
258264
<span style={{ color: getValueColor(type) }}>
@@ -282,7 +288,8 @@ const DocumentTreeView: React.FC<DocumentTreeViewProps> = ({ document }) => {
282288
<div key={key}>
283289
<div className={nodeRowStyles}>
284290
<div className={caretStyles}>
285-
{hasExpandableContent && renderExpandButton(isExpanded, itemKey)}
291+
{hasExpandableContent &&
292+
renderExpandButton(isExpanded, itemKey)}
286293
</div>
287294
<div className={keyValueContainerStyles}>
288295
<span className={keyStyles}>{key}</span>
@@ -307,7 +314,7 @@ const DocumentTreeView: React.FC<DocumentTreeViewProps> = ({ document }) => {
307314

308315
const renderClosingBracket = (
309316
nodeType: TreeNode['type'],
310-
isLast: boolean
317+
isLast: boolean,
311318
): JSX.Element => (
312319
<div className={nodeRowStyles}>
313320
<div className={caretStyles} />
@@ -343,7 +350,7 @@ const DocumentTreeView: React.FC<DocumentTreeViewProps> = ({ document }) => {
343350
const getNodeDisplayValue = (
344351
node: TreeNode,
345352
isIdField: boolean,
346-
isExpanded: boolean
353+
isExpanded: boolean,
347354
): string => {
348355
if (isIdField) {
349356
return formatIdValue(node.value);
@@ -356,7 +363,7 @@ const DocumentTreeView: React.FC<DocumentTreeViewProps> = ({ document }) => {
356363

357364
const createRowClickHandler = (
358365
hasExpandableContent: boolean,
359-
nodeKey: string
366+
nodeKey: string,
360367
): (() => void) | undefined =>
361368
hasExpandableContent ? (): void => toggleExpanded(nodeKey) : undefined;
362369

@@ -404,7 +411,9 @@ const DocumentTreeView: React.FC<DocumentTreeViewProps> = ({ document }) => {
404411
{renderChildren(node.value, node.key)}
405412
</div>
406413
)}
407-
{hasExpandableContent && isExpanded && renderClosingBracket(node.type, isLast)}
414+
{hasExpandableContent &&
415+
isExpanded &&
416+
renderClosingBracket(node.type, isLast)}
408417
</div>
409418
);
410419
};
@@ -414,7 +423,9 @@ const DocumentTreeView: React.FC<DocumentTreeViewProps> = ({ document }) => {
414423
return (
415424
<div className={documentTreeViewContainerStyles}>
416425
<KeylineCard className={documentContentStyles}>
417-
{nodes.map((node, index) => renderNode(node, index === nodes.length - 1))}
426+
{nodes.map((node, index) =>
427+
renderNode(node, index === nodes.length - 1),
428+
)}
418429
</KeylineCard>
419430
</div>
420431
);

src/views/data-browsing-app/extension-app-message-constants.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,3 @@ export type MessageFromExtensionToWebview =
6060
| LoadDocumentsMessage
6161
| RefreshErrorMessage
6262
| ThemeChangedMessage;
63-

0 commit comments

Comments
 (0)