forked from DonJayamanne/pythonVSCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvariableTestHelpers.ts
More file actions
155 lines (138 loc) · 6.59 KB
/
variableTestHelpers.ts
File metadata and controls
155 lines (138 loc) · 6.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
'use strict';
import { expect } from 'chai';
import { ReactWrapper } from 'enzyme';
import { parse } from 'node-html-parser';
import * as React from 'react';
import { Uri } from 'vscode';
import { IDocumentManager } from '../../client/common/application/types';
import { createDeferred } from '../../client/common/utils/async';
import { Identifiers } from '../../client/datascience/constants';
import {
IJupyterDebugService,
IJupyterVariable,
IJupyterVariables,
INotebookProvider
} from '../../client/datascience/types';
import { DataScienceIocContainer } from './dataScienceIocContainer';
import { getOrCreateInteractiveWindow } from './interactiveWindowTestHelpers';
import { MockDocumentManager } from './mockDocumentManager';
import { waitForVariablesUpdated } from './testHelpers';
// tslint:disable: no-var-requires no-require-imports no-any chai-vague-errors no-unused-expression
export async function verifyAfterStep(
ioc: DataScienceIocContainer,
wrapper: ReactWrapper<any, Readonly<{}>, React.Component>,
verify: (wrapper: ReactWrapper<any, Readonly<{}>, React.Component>) => Promise<void>
) {
const interactive = await getOrCreateInteractiveWindow(ioc);
const debuggerBroke = createDeferred();
const jupyterDebugger = ioc.get<IJupyterDebugService>(IJupyterDebugService, Identifiers.MULTIPLEXING_DEBUGSERVICE);
jupyterDebugger.onBreakpointHit(() => debuggerBroke.resolve());
const docManager = ioc.get<IDocumentManager>(IDocumentManager) as MockDocumentManager;
const file = Uri.file('foo.py');
docManager.addDocument('a=1\na', file.fsPath);
const debugPromise = interactive.debugCode('a=1\na', file.fsPath, 1, undefined, undefined);
await debuggerBroke.promise;
const variableRefresh = waitForVariablesUpdated(ioc);
await jupyterDebugger.requestVariables(); // This is necessary because not running inside of VS code. Normally it would do this.
await variableRefresh;
wrapper.update();
await verify(wrapper);
await jupyterDebugger.continue();
return debugPromise;
}
// Verify a set of rows versus a set of expected variables
export function verifyVariables(
wrapper: ReactWrapper<any, Readonly<{}>, React.Component>,
targetVariables: IJupyterVariable[]
) {
// Force an update so we render whatever the current state is
wrapper.update();
// Then search for results.
const foundRows = wrapper.find('div.react-grid-Row');
expect(foundRows.length).to.be.equal(
targetVariables.length,
'Different number of variable explorer rows and target variables'
);
foundRows.forEach((row, index) => {
verifyRow(row, targetVariables[index]);
});
}
// Verify a single row versus a single expected variable
function verifyRow(rowWrapper: ReactWrapper<any, Readonly<{}>, React.Component>, targetVariable: IJupyterVariable) {
const rowCells = rowWrapper.find('div.react-grid-Cell');
expect(rowCells.length).to.be.equal(5, 'Unexpected number of cells in variable explorer row');
verifyCell(rowCells.at(0), targetVariable.name, targetVariable.name);
verifyCell(rowCells.at(1), targetVariable.type, targetVariable.name);
if (targetVariable.shape && targetVariable.shape !== '') {
verifyCell(rowCells.at(2), targetVariable.shape, targetVariable.name);
} else if (targetVariable.count) {
verifyCell(rowCells.at(2), targetVariable.count.toString(), targetVariable.name);
}
if (targetVariable.value) {
verifyCell(rowCells.at(3), targetVariable.value, targetVariable.name);
}
verifyCell(rowCells.at(4), targetVariable.supportsDataExplorer, targetVariable.name);
}
// Verify a single cell value against a specific target value
function verifyCell(
cellWrapper: ReactWrapper<any, Readonly<{}>, React.Component>,
value: string | boolean,
targetName: string
) {
const cellHTML = parse(cellWrapper.html()) as any;
const innerHTML = cellHTML.innerHTML;
if (typeof value === 'string') {
// tslint:disable-next-line:no-string-literal
const match = /value="([\s\S]+?)"\s+/.exec(innerHTML);
expect(match).to.not.be.equal(null, `${targetName} does not have a value attribute`);
// Eliminate whitespace differences
const actualValueNormalized = match![1].replace(/^\s*|\s(?=\s)|\s*$/g, '').replace(/\r\n/g, '\n');
const expectedValueNormalized = value.replace(/^\s*|\s(?=\s)|\s*$/g, '').replace(/\r\n/g, '\n');
expect(actualValueNormalized).to.be.equal(
expectedValueNormalized,
`${targetName} has an unexpected value ${innerHTML} in variable explorer cell`
);
} else {
if (value) {
expect(innerHTML).to.include('image-button-image', `Image class not found in ${targetName}`);
} else {
expect(innerHTML).to.not.include('image-button-image', `Image class was found ${targetName}`);
}
}
}
export async function verifyCanFetchData<T>(
ioc: DataScienceIocContainer,
executionCount: number,
name: string,
rows: T[]
) {
const variableFetcher = ioc.get<IJupyterVariables>(IJupyterVariables, Identifiers.ALL_VARIABLES);
const notebookProvider = ioc.get<INotebookProvider>(INotebookProvider);
const notebook = await notebookProvider.getOrCreateNotebook({
getOnly: true,
identity: Uri.parse(Identifiers.InteractiveWindowIdentity)
});
expect(notebook).to.not.be.undefined;
const variableList = await variableFetcher.getVariables(notebook!, {
executionCount,
startIndex: 0,
pageSize: 100,
sortAscending: true,
sortColumn: 'INDEX'
});
expect(variableList.pageResponse.length).to.be.greaterThan(0, 'No variables returned');
const variable = variableList.pageResponse.find((v) => v.name === name);
expect(variable).to.not.be.undefined;
expect(variable?.supportsDataExplorer).to.eq(true, `Variable ${name} does not support data explorer`);
const withInfo = await variableFetcher.getDataFrameInfo(variable!, notebook!);
expect(withInfo.count).to.eq(rows.length, 'Wrong number of rows for variable');
const fetchedRows = await variableFetcher.getDataFrameRows(withInfo!, notebook!, 0, rows.length);
expect(fetchedRows.data).to.have.length(rows.length, 'Fetched rows data is not the correct size');
for (let i = 0; i < rows.length; i += 1) {
const fetchedRow = (fetchedRows.data as any)[i];
const val = fetchedRow['0']; // Column should default to zero for tests calling this.
expect(val).to.be.eq(rows[i], 'Invalid value found');
}
}