Skip to content

Commit 83b9821

Browse files
Dev/ianhu/variable functional tests (microsoft#5300)
Add functional tests for variable explorer
1 parent 4c4228b commit 83b9821

12 files changed

Lines changed: 706 additions & 397 deletions

news/3 Code Health/4803.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add functional testing for variable explorer

src/datascience-ui/history-react/variableExplorer.tsx

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,6 @@ export class VariableExplorer extends React.Component<IVariableExplorerProps, IV
132132

133133
// Update the value of a single variable already in our list
134134
public newVariableData(newVariable: IJupyterVariable) {
135-
// IANHU: This will eventually have to add in something like the execution count, can't just use the name
136-
// to match on
137135
const newGridRows = this.state.gridRows.slice();
138136
for (let i = 0; i < newGridRows.length; i = i + 1) {
139137
if (newGridRows[i].name === newVariable.name) {
@@ -145,6 +143,15 @@ export class VariableExplorer extends React.Component<IVariableExplorerProps, IV
145143
this.setState({ gridRows: newGridRows });
146144
}
147145

146+
public toggleInputBlock = () => {
147+
this.setState({open: !this.state.open});
148+
149+
// If we toggle open request a data refresh
150+
if (!this.state.open) {
151+
this.props.refreshVariables();
152+
}
153+
}
154+
148155
private updateHeight = () => {
149156
// Make sure we check for a new height so we don't get into an update loop
150157
const divElement = ReactDOM.findDOMNode(this) as HTMLDivElement;
@@ -165,13 +172,4 @@ export class VariableExplorer extends React.Component<IVariableExplorerProps, IV
165172
}
166173
return {buttons: '', name: '', type: '', size: '', value: ''};
167174
}
168-
169-
private toggleInputBlock = () => {
170-
this.setState({open: !this.state.open});
171-
172-
// If we toggle open request a data refresh
173-
if (!this.state.open) {
174-
this.props.refreshVariables();
175-
}
176-
}
177175
}

src/datascience-ui/react-common/settingsReactSide.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ function load() {
4949
sendSelectionToInteractiveWindow: false,
5050
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)',
5151
codeRegularExpression: '^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])',
52+
showJupyterVariableExplorer: true,
53+
variableExplorerExclude: 'module;builtin_function_or_method',
5254
extraSettings: {
5355
terminalCursor: 'block',
5456
theme: 'Default Dark+'

src/test/datascience/color.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ suite('Theme colors', () => {
6464
maxOutputSize: 400,
6565
errorBackgroundColor: '#FFFFFF',
6666
sendSelectionToInteractiveWindow: false,
67+
showJupyterVariableExplorer: true,
68+
variableExplorerExclude: 'module;builtin_function_or_method',
6769
codeRegularExpression: '^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])',
6870
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)'
6971
};

src/test/datascience/dataScienceIocContainer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ export class DataScienceIocContainer extends UnitTestIocContainer {
323323
sendSelectionToInteractiveWindow: false,
324324
codeRegularExpression: '^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])',
325325
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)',
326+
showJupyterVariableExplorer: true,
327+
variableExplorerExclude: 'module;builtin_function_or_method',
326328
liveShareConnectionTimeout: 100
327329
};
328330

src/test/datascience/editor-integration/codewatcher.unit.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ suite('DataScience Code Watcher Unit Tests', () => {
6767
maxOutputSize: 400,
6868
errorBackgroundColor: '#FFFFFF',
6969
sendSelectionToInteractiveWindow: false,
70+
showJupyterVariableExplorer: true,
71+
variableExplorerExclude: 'module;builtin_function_or_method',
7072
codeRegularExpression: '^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])',
7173
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)',
7274
enableCellCodeLens: true

src/test/datascience/execution.unit.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,8 @@ suite('Jupyter Execution', async () => {
530530
maxOutputSize: 400,
531531
errorBackgroundColor: '#FFFFFF',
532532
sendSelectionToInteractiveWindow: false,
533+
showJupyterVariableExplorer: true,
534+
variableExplorerExclude: 'module;builtin_function_or_method',
533535
codeRegularExpression: '^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])',
534536
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)',
535537
allowLiveShare: false

src/test/datascience/history.functional.test.tsx

Lines changed: 23 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
// Licensed under the MIT License.
33
'use strict';
44
import * as assert from 'assert';
5-
import { mount, ReactWrapper } from 'enzyme';
65
import * as fs from 'fs-extra';
76
import * as path from 'path';
8-
import * as React from 'react';
97
import * as TypeMoq from 'typemoq';
108
import { Disposable, TextDocument, TextEditor } from 'vscode';
119

@@ -15,7 +13,7 @@ import { noop } from '../../client/common/utils/misc';
1513
import { EditorContexts } from '../../client/datascience/constants';
1614
import { HistoryMessageListener } from '../../client/datascience/history/historyMessageListener';
1715
import { HistoryMessages } from '../../client/datascience/history/historyTypes';
18-
import { IHistory, IHistoryProvider, IJupyterExecution } from '../../client/datascience/types';
16+
import { IHistory, IHistoryProvider } from '../../client/datascience/types';
1917
import { CellButton } from '../../datascience-ui/history-react/cellButton';
2018
import { MainPanel } from '../../datascience-ui/history-react/MainPanel';
2119
import { sleep } from '../core';
@@ -33,55 +31,25 @@ import {
3331
getCellResults,
3432
getLastOutputCell,
3533
initialDataScienceSettings,
34+
runMountedTest,
3635
srcDirectory,
3736
toggleCellExpansion,
3837
updateDataScienceSettings,
3938
verifyHtmlOnCell,
4039
verifyLastCellInputState
4140
} from './historyTestHelpers';
42-
import { blurWindow, waitForUpdate } from './reactHelpers';
41+
import { waitForUpdate } from './reactHelpers';
4342

4443
// tslint:disable:max-func-body-length trailing-comma no-any no-multiline-string
4544
suite('History output tests', () => {
4645
const disposables: Disposable[] = [];
47-
let jupyterExecution: IJupyterExecution;
48-
let historyProvider: IHistoryProvider;
4946
let ioc: DataScienceIocContainer;
5047

5148
setup(() => {
5249
ioc = new DataScienceIocContainer();
5350
ioc.registerDataScienceTypes();
54-
jupyterExecution = ioc.get<IJupyterExecution>(IJupyterExecution);
5551
});
5652

57-
function mountWebView(): ReactWrapper<any, Readonly<{}>, React.Component> {
58-
59-
// Setup our webview panel
60-
ioc.createWebView(() => mount(<MainPanel baseTheme='vscode-light' codeTheme='light_vs' testMode={true} skipDefault={true} />));
61-
62-
// Make sure the history provider and execution factory in the container is created (the extension does this on startup in the extension)
63-
historyProvider = ioc.get<IHistoryProvider>(IHistoryProvider);
64-
65-
// The history provider create needs to be rewritten to make the history window think the mounted web panel is
66-
// ready.
67-
const origFunc = (historyProvider as any).create.bind(historyProvider);
68-
(historyProvider as any).create = async (): Promise<void> => {
69-
await origFunc();
70-
const history = historyProvider.getActive();
71-
72-
// During testing the MainPanel sends the init message before our history is created.
73-
// Pretend like it's happening now
74-
const listener = ((history as any).messageListener) as HistoryMessageListener;
75-
listener.onMessage(HistoryMessages.Started, {});
76-
};
77-
78-
return ioc.wrapper!;
79-
}
80-
81-
// suiteTeardown(() => {
82-
// asyncDump();
83-
// });
84-
8553
teardown(async () => {
8654
for (const disposable of disposables) {
8755
if (!disposable) {
@@ -96,7 +64,12 @@ suite('History output tests', () => {
9664
await ioc.dispose();
9765
});
9866

67+
// suiteTeardown(() => {
68+
// asyncDump();
69+
// });
70+
9971
async function getOrCreateHistory(): Promise<IHistory> {
72+
const historyProvider = ioc.get<IHistoryProvider>(IHistoryProvider);
10073
const result = await historyProvider.getOrCreateActive();
10174

10275
// During testing the MainPanel sends the init message before our history is created.
@@ -107,28 +80,6 @@ suite('History output tests', () => {
10780
return result;
10881
}
10982

110-
// tslint:disable-next-line:no-any
111-
function runMountedTest(name: string, testFunc: (wrapper: ReactWrapper<any, Readonly<{}>, React.Component>) => Promise<void>) {
112-
test(name, async () => {
113-
if (await jupyterExecution.isNotebookSupported()) {
114-
addMockData(ioc, 'a=1\na', 1);
115-
const wrapper = mountWebView();
116-
try {
117-
await testFunc(wrapper);
118-
} finally {
119-
// Blur window focus so we don't have editors polling
120-
blurWindow();
121-
122-
// Make sure to unmount the wrapper or it will interfere with other tests
123-
wrapper.unmount();
124-
}
125-
} else {
126-
// tslint:disable-next-line:no-console
127-
console.log(`${name} skipped, no Jupyter installed.`);
128-
}
129-
});
130-
}
131-
13283
async function waitForMessageResponse(action: () => void): Promise<void> {
13384
ioc.wrapperCreatedPromise = createDeferred<boolean>();
13485
action();
@@ -140,7 +91,7 @@ suite('History output tests', () => {
14091
await addCode(getOrCreateHistory, wrapper, 'a=1\na');
14192

14293
verifyHtmlOnCell(wrapper, '<span>1</span>', CellPosition.Last);
143-
});
94+
}, () => { return ioc; });
14495

14596
runMountedTest('Hide inputs', async (wrapper) => {
14697
initialDataScienceSettings({ ...defaultDataScienceSettings(), showCellInputCode: false });
@@ -155,7 +106,7 @@ suite('History output tests', () => {
155106

156107
verifyHtmlOnCell(wrapper, '<span>1</span>', CellPosition.First);
157108
verifyHtmlOnCell(wrapper, undefined, CellPosition.Last);
158-
});
109+
}, () => { return ioc; });
159110

160111
runMountedTest('Show inputs', async (wrapper) => {
161112
initialDataScienceSettings({ ...defaultDataScienceSettings() });
@@ -164,14 +115,14 @@ suite('History output tests', () => {
164115

165116
verifyLastCellInputState(wrapper, CellInputState.Visible);
166117
verifyLastCellInputState(wrapper, CellInputState.Collapsed);
167-
});
118+
}, () => { return ioc; });
168119

169120
runMountedTest('Expand inputs', async (wrapper) => {
170121
initialDataScienceSettings({ ...defaultDataScienceSettings(), collapseCellInputCodeByDefault: false });
171122
await addCode(getOrCreateHistory, wrapper, 'a=1\na');
172123

173124
verifyLastCellInputState(wrapper, CellInputState.Expanded);
174-
});
125+
}, () => { return ioc; });
175126

176127
runMountedTest('Collapse / expand cell', async (wrapper) => {
177128
initialDataScienceSettings({ ...defaultDataScienceSettings() });
@@ -189,7 +140,7 @@ suite('History output tests', () => {
189140

190141
verifyLastCellInputState(wrapper, CellInputState.Visible);
191142
verifyLastCellInputState(wrapper, CellInputState.Collapsed);
192-
});
143+
}, () => { return ioc; });
193144

194145
runMountedTest('Hide / show cell', async (wrapper) => {
195146
initialDataScienceSettings({ ...defaultDataScienceSettings() });
@@ -208,7 +159,7 @@ suite('History output tests', () => {
208159

209160
verifyLastCellInputState(wrapper, CellInputState.Visible);
210161
verifyLastCellInputState(wrapper, CellInputState.Collapsed);
211-
});
162+
}, () => { return ioc; });
212163

213164
runMountedTest('Mime Types', async (wrapper) => {
214165
const badPanda = `import pandas as pd
@@ -261,7 +212,7 @@ for _ in range(50):
261212

262213
await addCode(getOrCreateHistory, wrapper, spinningCursor, 4 + (ioc.mockJupyter ? (cursors.length * 3) : 0));
263214
verifyHtmlOnCell(wrapper, '<xmp>', CellPosition.Last);
264-
});
215+
}, () => { return ioc; });
265216

266217
runMountedTest('Undo/redo commands', async (wrapper) => {
267218
const history = await getOrCreateHistory();
@@ -302,7 +253,7 @@ for _ in range(50):
302253
});
303254

304255
assert.equal(afterUndo.length, 3, `Undo should put cells back`);
305-
});
256+
}, () => { return ioc; });
306257

307258
runMountedTest('Click buttons', async (wrapper) => {
308259
// Goto source should cause the visible editor to be picked as long as its filename matches
@@ -378,7 +329,7 @@ for _ in range(50):
378329
return Promise.resolve();
379330
});
380331
assert.equal(afterDelete.length, 2, `Delete should remove a cell`);
381-
});
332+
}, () => { return ioc; });
382333

383334
runMountedTest('Export', async (wrapper) => {
384335
// Export should cause the export dialog to come up. Remap appshell so we can check
@@ -422,7 +373,7 @@ for _ in range(50):
422373
await Promise.race([sleep(10), response]);
423374
assert.equal(exportCalled, false, 'Export should not be called when no cells visible');
424375

425-
});
376+
}, () => { return ioc; });
426377

427378
runMountedTest('Dispose test', async () => {
428379
// tslint:disable-next-line:no-any
@@ -435,7 +386,7 @@ for _ in range(50):
435386
const equal = Object.is(history, h2);
436387
await h2.show();
437388
assert.ok(!equal, 'Disposing is not removing the active history');
438-
});
389+
}, () => { return ioc; });
439390

440391
runMountedTest('Editor Context', async (wrapper) => {
441392
// Verify we can send different commands to the UI and it will respond
@@ -497,7 +448,7 @@ for _ in range(50):
497448
await Promise.race([deferred.promise, sleep(2000)]);
498449
assert.ok(deferred.resolved, 'Never got update to state');
499450
assert.equal(ioc.getContext(EditorContexts.HaveInteractiveCells), false, 'Should not have interactive cells after delete');
500-
});
451+
}, () => { return ioc; });
501452

502453
runMountedTest('Simple input', async (wrapper) => {
503454
// Create a history so that it listens to the results.
@@ -507,7 +458,7 @@ for _ in range(50):
507458
// Then enter some code.
508459
await enterInput(wrapper, 'a=1\na');
509460
verifyHtmlOnCell(wrapper, '<span>1</span>', CellPosition.Last);
510-
});
461+
}, () => { return ioc; });
511462

512463
runMountedTest('Multiple input', async (wrapper) => {
513464
// Create a history so that it listens to the results.
@@ -539,7 +490,7 @@ for _ in range(50):
539490
addMockData(ioc, 'print("hello")', 'hello');
540491
await enterInput(wrapper, 'print("hello")');
541492
verifyHtmlOnCell(wrapper, '>hello</', CellPosition.Last);
542-
});
493+
}, () => { return ioc; });
543494

544495
runMountedTest('Restart with session failure', async (wrapper) => {
545496
// Prime the pump
@@ -573,5 +524,5 @@ for _ in range(50):
573524
await history.addCode('a=1\na', 'foo', 0);
574525
verifyHtmlOnCell(wrapper, '<span>1</span>', CellPosition.Last);
575526

576-
});
527+
}, () => { return ioc; });
577528
});

src/test/datascience/historyCommandListener.unit.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ suite('History command listener', async () => {
141141
maxOutputSize: 400,
142142
errorBackgroundColor: '#FFFFFF',
143143
sendSelectionToInteractiveWindow: false,
144+
showJupyterVariableExplorer: true,
145+
variableExplorerExclude: 'module;builtin_function_or_method',
144146
codeRegularExpression: '^(#\\s*%%|#\\s*\\<codecell\\>|#\\s*In\\[\\d*?\\]|#\\s*In\\[ \\])',
145147
markdownRegularExpression: '^(#\\s*%%\\s*\\[markdown\\]|#\\s*\\<markdowncell\\>)'
146148
};

0 commit comments

Comments
 (0)