platformService tests and move tests from tdd to bdd (#13131)

This commit is contained in:
Arvind Ranasaria
2020-11-03 13:34:33 -08:00
committed by GitHub
parent 64510506e8
commit f10ac10f6d
12 changed files with 355 additions and 97 deletions

View File

@@ -53,3 +53,12 @@ export function throwUnless(condition: boolean, message?: string): asserts condi
throw new Error(message);
}
}
export async function tryExecuteAction<T>(action: () => T | PromiseLike<T>): Promise<{ result: T | undefined, error: any }> {
let error: any, result: T | undefined;
try {
result = await action();
} catch (e) {
error = e;
}
return { result, error };
}

View File

@@ -13,7 +13,7 @@ import { OsDistribution, OsRelease } from '../interfaces';
import { getErrorMessage } from '../common/utils';
const localize = nls.loadMessageBundle();
const extensionOutputChannel = localize('resourceDeployment.outputChannel', "Deployments");
export const extensionOutputChannel = localize('resourceDeployment.outputChannel', "Deployments");
const sudoPromptTitle = 'AzureDataStudio';
/**
* Abstract of platform dependencies
@@ -244,7 +244,6 @@ export class PlatformService implements IPlatformService {
windowsHide: true
};
const child = cp.spawn(command, [], spawnOptions);
// Add listeners to print stdout and stderr and exit code
child.on('exit', (code: number | null, signal: string | null) => {
if (code !== null) {
@@ -258,7 +257,6 @@ export class PlatformService implements IPlatformService {
this.outputDataChunk(data, outputChannel, localize('platformService.RunCommand.stdout', " stdout: "));
});
child.stderr!.on('data', (data: string | Buffer) => { this.outputDataChunk(data, outputChannel, localize('platformService.RunCommand.stderr', " stderr: ")); });
await child;
return stdoutData.join('');
}

View File

@@ -85,9 +85,9 @@ function validate(test: TestDefinition, semVerProxy: SymVerProxyTest) {
}
}
suite('SemVeryProxy Tests', function (): void {
describe('SemVeryProxy Tests', function (): void {
testDefinitions.forEach((semVerTest: TestDefinition) => {
test(semVerTest.testName, () => {
it(semVerTest.testName, () => {
const semVerProxy = new SymVerProxyTest(semVerTest.inputVersion);
validate(semVerTest, semVerProxy);
});

View File

@@ -9,7 +9,7 @@ const testRunner = require('vscodetestcover');
const suite = 'resource-deployment Extension Tests';
const mochaOptions: any = {
ui: 'tdd',
ui: 'bdd',
useColors: true,
timeout: 10000
};

View File

@@ -4,11 +4,11 @@
*--------------------------------------------------------------------------------------------*/
import 'mocha';
import { apiService } from '../../services/apiService';
import assert = require('assert');
import { apiService } from '../services/apiService';
suite('API Service Tests', function (): void {
test('getAzurecoreApi returns azure api', () => {
describe('API Service Tests', function (): void {
it('get azurecoreApi returns azure api', () => {
const api = apiService.azurecoreApi;
assert(api !== undefined);
});

View File

@@ -6,12 +6,12 @@
import 'mocha';
import * as TypeMoq from 'typemoq';
import * as should from 'should';
import { IPlatformService, CommandOptions } from '../services/platformService';
import { AzdataService } from '../services/azdataService';
import { BdcDeploymentType } from '../interfaces';
import { IPlatformService, CommandOptions } from '../../services/platformService';
import { AzdataService } from '../../services/azdataService';
import { BdcDeploymentType } from '../../interfaces';
suite('azdata service Tests', function (): void {
test('azdata service handles deployment types properly', async () => {
describe('azdata service Tests', function (): void {
it('azdata service handles deployment types properly', async () => {
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const azdataService = new AzdataService(mockPlatformService.object);
mockPlatformService.setup((service) => service.runCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns((command: string, options: CommandOptions | undefined) => {
@@ -30,7 +30,7 @@ suite('azdata service Tests', function (): void {
mockPlatformService.verify((service) => service.runCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.exactly(5));
});
test('azdata service returns correct deployment profiles', async () => {
it('azdata service returns correct deployment profiles', async () => {
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const azdataService = new AzdataService(mockPlatformService.object);
mockPlatformService.setup((service => service.storagePath())).returns(() => {

View File

@@ -5,14 +5,14 @@
import * as TypeMoq from 'typemoq';
import 'mocha';
import { NotebookService } from '../services/notebookService';
import { NotebookService } from '../../services/notebookService';
import assert = require('assert');
import { NotebookPathInfo } from '../interfaces';
import { IPlatformService } from '../services/platformService';
import { NotebookPathInfo } from '../../interfaces';
import { IPlatformService } from '../../services/platformService';
suite('Notebook Service Tests', function (): void {
describe('Notebook Service Tests', function (): void {
test('getNotebook with string parameter', () => {
it('getNotebook with string parameter', () => {
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const notebookService = new NotebookService(mockPlatformService.object, '');
const notebookInput = 'test-notebook.ipynb';
@@ -28,7 +28,7 @@ suite('Notebook Service Tests', function (): void {
mockPlatformService.verify((service) => service.platform(), TypeMoq.Times.never());
});
test('getNotebook with NotebookInfo parameter', () => {
it('getNotebook with NotebookInfo parameter', () => {
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const notebookService = new NotebookService(mockPlatformService.object, '');
const notebookWin32 = 'test-notebook-win32.ipynb';
@@ -58,7 +58,7 @@ suite('Notebook Service Tests', function (): void {
mockPlatformService.verify((service) => service.platform(), TypeMoq.Times.once());
});
test('findNextUntitledEditorName with no name conflict', () => {
it('findNextUntitledEditorName with no name conflict', () => {
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const notebookService = new NotebookService(mockPlatformService.object, '');
const notebookFileName = 'mynotebook.ipynb';
@@ -72,7 +72,7 @@ suite('Notebook Service Tests', function (): void {
assert.equal(actualFileName, expectedTargetFile, 'target file name is not correct');
});
test('findNextUntitledEditorName with name conflicts', () => {
it('findNextUntitledEditorName with name conflicts', () => {
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const notebookService = new NotebookService(mockPlatformService.object, '');
const notebookFileName = 'mynotebook.ipynb';

View File

@@ -0,0 +1,243 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as fs from 'fs';
import 'mocha';
import * as os from 'os';
import * as cp from 'promisify-child-process';
import * as should from 'should';
import * as sinon from 'sinon';
import * as sudo from 'sudo-prompt';
import * as TypeMoq from 'typemoq';
import * as vscode from 'vscode';
import { tryExecuteAction } from '../../common/utils';
import { OsDistribution } from '../../interfaces';
import { extensionOutputChannel, PlatformService } from '../../services/platformService';
import { TestChildProcessPromise } from '../stubs';
const globalStoragePath = os.tmpdir();
const platformService = new PlatformService(globalStoragePath);
describe('PlatformService', () => {
beforeEach('PlatformService setup', async () => {
await platformService.initialize();
});
afterEach('PlatformService cleanup', () => {
sinon.restore();
});
it('storagePath', () => {
const result = platformService.storagePath();
result.should.equal(globalStoragePath);
});
it('platform', () => {
const result = platformService.platform();
result.should.equal(process.platform);
});
it('outputChannelName', () => {
const result = platformService.outputChannelName();
result.should.equal(extensionOutputChannel);
});
describe('output channel', () => {
let outputChannelStub: TypeMoq.IMock<vscode.OutputChannel>;
beforeEach('output channel setup', () => {
outputChannelStub = TypeMoq.Mock.ofType<vscode.OutputChannel>();
});
it('showOutputChannel', () => {
outputChannelStub.setup(c => c.show(TypeMoq.It.isAny())).callback((preserveFocus => {
preserveFocus.should.be.true();
}));
platformService.showOutputChannel(true);
});
describe('logToOutputChannel', () => {
['', undefined, 'header'].forEach(header => {
it(`header = ${header}`, () => {
const data = 'data';
outputChannelStub.setup(c => c.appendLine(TypeMoq.It.isAny())).callback((line => {
line.should.equal(header + line);
}));
platformService.logToOutputChannel(data, header);
});
});
});
});
it('osDistribution', () => {
const result = platformService.osDistribution();
switch (process.platform) {
case 'darwin': result.should.equal(OsDistribution.darwin); break;
case 'win32': result.should.equal(OsDistribution.win32); break;
case 'linux': result.should.equal(OsDistribution.debian); break;
default: result.should.equal(OsDistribution.others); break;
}
});
describe('file/directory', () => {
const filePath = __filename;
const contents = __dirname; //a known value
[true, false, 'throws'].forEach((fileExists => {
it(`fileExists - ${fileExists}`, async () => {
switch (fileExists) {
case true: (await platformService.fileExists(filePath)).should.be.true(); break;
case false: {
sinon.stub(fs.promises, 'access').rejects({ code: 'ENOENT' });
(await platformService.fileExists(filePath)).should.be.false();
break;
}
case 'throws': {
sinon.stub(fs.promises, 'access').rejects({});
const { error } = await tryExecuteAction(() => platformService.fileExists(filePath));
should(error).not.be.undefined();
break;
}
default: throw new Error('unexpected error');
}
});
}));
describe('deleteFile', () => {
[true, false].forEach(fileExists => {
it(`fileExists - ${fileExists}`, async () => {
if (fileExists) {
const stub = sinon.stub(fs.promises, 'unlink').resolves();
await platformService.deleteFile(filePath);
stub.callCount.should.equal(1);
stub.getCall(0).args[0].should.equal(filePath);
} else {
sinon.stub(fs.promises, 'access').rejects({ code: 'ENOENT' }); // causes fileExists to return false
const stub = sinon.stub(fs.promises, 'unlink').resolves();
await platformService.deleteFile(filePath);
stub.callCount.should.equal(0); // verifies that unlink was not called
}
});
});
[true, false].forEach(async ignoreError => {
it(`throws with ignoreError: ${ignoreError}`, async () => {
const stub = sinon.stub(fs.promises, 'unlink').throws();
const { error } = await tryExecuteAction(() => platformService.deleteFile(filePath, ignoreError));
stub.callCount.should.equal(1);
stub.getCall(0).args[0].should.equal(filePath);
if (ignoreError) {
should(error).be.undefined();
} else {
should(error).not.be.undefined();
}
});
});
});
it('openFile', () => {
const stub = sinon.stub(vscode.commands, 'executeCommand').resolves(); //resolves with a known string
platformService.openFile(filePath);
stub.callCount.should.equal(1);
stub.getCall(0).args[0].should.equal('vscode.open');
stub.getCall(0).args[1].path.should.equal(filePath);
});
it('readTextFile', async () => {
sinon.stub(fs.promises, 'readFile').resolves(contents);
const result = await platformService.readTextFile(filePath);
result.should.equal(contents);
});
it('saveTextFile', async () => {
const stub = sinon.stub(fs.promises, 'writeFile').resolves(); //resolves with a known string
await platformService.saveTextFile(contents, filePath);
stub.callCount.should.equal(1);
stub.getCall(0).args[0].should.equal(filePath);
stub.getCall(0).args[1].should.equal(contents);
});
it('copyFile', async () => {
const target = __dirname; //arbitrary path
const stub = sinon.stub(fs.promises, 'copyFile').resolves();
await platformService.copyFile(filePath, target);
stub.callCount.should.equal(1);
stub.getCall(0).args[0].should.equal(filePath);
stub.getCall(0).args[1].should.equal(target);
});
it('makeDirectory ', async () => {
const target = __dirname; //arbitrary path
sinon.stub(fs.promises, 'access').rejects({ code: 'ENOENT' }); // this simulates the target directory to not Exist.
const stub = sinon.stub(fs.promises, 'mkdir').resolves();
await platformService.makeDirectory(target);
stub.callCount.should.equal(1);
stub.getCall(0).args[0].should.equal(target);
});
});
it('showErrorMessage', () => {
const error = __dirname; //arbitrary known string
const stub = sinon.stub(vscode.window, 'showErrorMessage').resolves(); //resolves with a known string
platformService.showErrorMessage(error);
stub.callCount.should.equal(1);
stub.getCall(0).args[0].should.equal(error);
});
describe('isNotebookNameUsed', () => {
[true, false].forEach((isUsed => {
it(`return value: ${isUsed}`, () => {
const title = __filename; //arbitrary known string
if (isUsed) {
sinon.stub(azdata.nb, 'notebookDocuments').get(() => [{ isUntitled: true, fileName: title }]);
sinon.stub(vscode.workspace, 'textDocuments').get(() => [{ isUntitled: true, fileName: title }]);
} else {
sinon.stub(azdata.nb, 'notebookDocuments').get(() => [{ isUntitled: true, fileName: '' }]);
sinon.stub(vscode.workspace, 'textDocuments').get(() => [{ isUntitled: true, fileName: '' }]);
}
const result = platformService.isNotebookNameUsed(title);
result.should.equal(isUsed);
});
}));
});
describe('runCommand', () => {
[
{ commandSucceeds: true },
{ commandSucceeds: false, ignoreError: true },
{ commandSucceeds: false, ignoreError: false },
].forEach(({ commandSucceeds, ignoreError }) => {
if (ignoreError && commandSucceeds) {
return; //exit out of the loop as we do not handle ignoreError when command is successful
}
it(`non-sudo, commandSucceeds: ${commandSucceeds}, ignoreError: ${ignoreError}`, async () => {
const command = __dirname; // arbitrary command string, and success string on successful execution and error string on error
const child = new TestChildProcessPromise<cp.Output>();
const stub = sinon.stub(cp, 'spawn').returns(child);
const runningCommand = platformService.runCommand(command, { commandTitle: 'title', ignoreError: ignoreError });
// fake runCommand to behave like echo, returning the command back as stdout/stderr/error.
// TestChildProcessPromise object shares the stdout/stderr stream for convenience with the child stream.
if (commandSucceeds) {
child.emit('data', command);
child.emit('exit', 0, null); //resolve with 0 exit code
child.resolve({ stdout: command });
} else {
child.emit('data', command);
child.emit('exit', 1, null); // resolve with non-zero exit code
child.reject({ stderr: command });
}
const { result, error } = await tryExecuteAction(() => runningCommand);
verifyCommandExecution(stub, result, error, command, commandSucceeds, ignoreError);
});
it(`sudo, commandSucceeds: ${commandSucceeds}, ignoreError: ${ignoreError}`, async () => {
const command = __dirname; // arbitrary command string, and success string on successful execution
const stub = sinon.stub(sudo, 'exec').callsFake((cmd, _options, cb) => {
// behaves like echo, returning the _cmd back as stdout/stderr/error.
if (commandSucceeds) {
cb(''/* error */, cmd/* stdout */, ''/* stderr */);
} else {
cb(cmd/* error */, ''/* stdout */, cmd/* stderr */);
}
});
const { error, result } = await tryExecuteAction(() => platformService.runCommand(command, { commandTitle: 'title', ignoreError: ignoreError, sudo: true, workingDirectory: __dirname }));
verifyCommandExecution(stub, result, error, command, commandSucceeds, ignoreError);
});
});
});
});
function verifyCommandExecution(stub: sinon.SinonStub, result: string | undefined, error: any, command: string, commandSucceeds: boolean | undefined, ignoreError: boolean | undefined) {
stub.callCount.should.equal(1);
if (commandSucceeds) {
result!.should.equal(command);
} else {
if (ignoreError) {
should(error).be.undefined();
(result === undefined || result.length === 0).should.be.true('result should be an empty string or be undefined when an error occurs');
} else {
should(error).not.be.undefined();
}
}
}

View File

@@ -8,14 +8,14 @@ import * as TypeMoq from 'typemoq';
import assert = require('assert');
import should = require('should');
import { EOL } from 'os';
import { ResourceTypeService, processWhenClause } from '../services/resourceTypeService';
import { IPlatformService } from '../services/platformService';
import { ToolsService } from '../services/toolsService';
import { NotebookService } from '../services/notebookService';
import { ResourceTypeService, processWhenClause } from '../../services/resourceTypeService';
import { IPlatformService } from '../../services/platformService';
import { ToolsService } from '../../services/toolsService';
import { NotebookService } from '../../services/notebookService';
suite('Resource Type Service Tests', function (): void {
describe('Resource Type Service Tests', function (): void {
test('test resource types', () => {
it('test resource types', () => {
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const toolsService = new ToolsService(mockPlatformService.object);
const notebookService = new NotebookService(mockPlatformService.object, '');
@@ -47,7 +47,7 @@ suite('Resource Type Service Tests', function (): void {
assert(validationErrors.length === 0, `Validation errors detected in the package.json: ${validationErrors.join(EOL)}.`);
});
test('Selected options containing all when clauses should return true', () => {
it('Selected options containing all when clauses should return true', () => {
const whenSelectedTrue: { when: string; selectedOptions: { option: string, value: string }[] }[] = [
{
when: 'resourceType=sql-bdc && newType=sql-windows-setup', selectedOptions: [{ option: 'resourceType', value: 'sql-image' }, { option: 'resourceType', value: 'sql-bdc' }, { option: 'newType', value: 'sql-windows-setup' }]
@@ -62,16 +62,16 @@ suite('Resource Type Service Tests', function (): void {
});
});
test('When clause that reads "true" (ignoring case) should always return true', () => {
it('When clause that reads "true" (ignoring case) should always return true', () => {
should(processWhenClause(undefined, [])).be.true('undefined when clause should always return true');
should(processWhenClause('TrUe', [])).be.true(`"true" when clause should always return true`);
});
test('No selected options returns false', () => {
it('No selected options returns false', () => {
should(processWhenClause('newType=empty', [])).be.false('No selected options should return false');
});
test('Unfulfilled or partially fulfilled when clauses return false', () => {
it('Unfulfilled or partially fulfilled when clauses return false', () => {
const whenSelectedFalse: { when: string; selectedOptions: { option: string, value: string }[] }[] = [
{
when: 'resourceType=sql-bdc && dneType=does-not-exist', selectedOptions: [{ option: 'resourceType', value: 'sql-image' }, { option: 'resourceType', value: 'sql-bdc' }, { option: 'newType', value: 'sql-windows-setup' }]
@@ -85,7 +85,7 @@ suite('Resource Type Service Tests', function (): void {
});
});
test('An invalid when clause should always return false', () => {
it('An invalid when clause should always return false', () => {
should(processWhenClause('badWhenClause', [{ option: 'bad', value: 'WhenClause' }])).be.false(`invalid when clause should return false`);
});
});

View File

@@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as TypeMoq from 'typemoq';
import { ITool, ToolType } from '../../interfaces';
import { IPlatformService } from '../../services/platformService';
import { ToolsService } from '../../services/toolsService';
const tools: { name: string; type: ToolType }[] = [
{ name: 'azure-cli', type: ToolType.AzCli },
{ name: 'docker', type: ToolType.Docker },
{ name: 'kubectl', type: ToolType.KubeCtl },
{ name: 'azdata', type: ToolType.Azdata }
];
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const toolsService = new ToolsService(mockPlatformService.object);
describe('Tools Service Tests', function (): void {
it('run getToolByName with all known values', () => {
const missingTypes: string[] = [];
// Make sure all the enum values are covered
for (const type in ToolType) {
if (typeof ToolType[type] === 'number') {
if (tools.findIndex(element => element.type === parseInt(ToolType[type])) === -1) {
missingTypes.push(type);
}
}
}
(missingTypes.length === 0).should.be.true(`the following enum values are not included in the test:${missingTypes.join(',')}`);
tools.forEach(toolInfo => {
const tool = toolsService.getToolByName(toolInfo.name);
(!!tool).should.be.true(`The tool: ${toolInfo.name} is not recognized`);
(tool!.type).should.equal(toolInfo.type, 'returned notebook name does not match expected value');
});
});
it('run getToolByName with a name that is not defined', () => {
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const toolsService = new ToolsService(mockPlatformService.object);
const tool = toolsService.getToolByName('no-such-tool');
(tool === undefined).should.be.true('for a not defined tool, expected value is undefined');
});
it('get/set tools for CurrentProvider', () => {
const iTools: ITool[] = tools.map(toolInfo => {
const tool = toolsService.getToolByName(toolInfo.name);
(!!tool).should.be.true(`The tool: ${toolInfo.name} is not recognized`);
tool!.type.should.equal(toolInfo.type, 'returned notebook name does not match expected value');
return tool!;
});
toolsService.toolsForCurrentProvider = iTools;
iTools.should.deepEqual(toolsService.toolsForCurrentProvider, 'toolsForCurrentProvider did not return the value we set');
});
});

View File

@@ -1,51 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'mocha';
import assert = require('assert');
import * as TypeMoq from 'typemoq';
import { ToolsService } from '../services/toolsService';
import { ToolType } from '../interfaces';
import { isNumber } from 'util';
import { IPlatformService } from '../services/platformService';
suite('Tools Service Tests', function (): void {
test('run getToolByName with all known values', () => {
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const toolsService = new ToolsService(mockPlatformService.object);
const tools: { name: string; type: ToolType }[] = [
{ name: 'azure-cli', type: ToolType.AzCli },
{ name: 'docker', type: ToolType.Docker },
{ name: 'kubectl', type: ToolType.KubeCtl },
{ name: 'azdata', type: ToolType.Azdata }];
const missingTypes: string[] = [];
// Make sure all the enum values are covered
for (const type in ToolType) {
if (isNumber(ToolType[type])) {
if (tools.findIndex(element => element.type === parseInt(ToolType[type])) === -1) {
missingTypes.push(type);
}
}
}
assert(missingTypes.length === 0, `the following enum values are not included in the test:${missingTypes.join(',')}`);
tools.forEach(toolInfo => {
const tool = toolsService.getToolByName(toolInfo.name);
assert(!!tool, `The tool: ${toolInfo.name} is not recognized`);
assert.equal(tool!.type, toolInfo.type, 'returned notebook name does not match expected value');
});
});
test('run getToolByName with a name that is not defined', () => {
const mockPlatformService = TypeMoq.Mock.ofType<IPlatformService>();
const toolsService = new ToolsService(mockPlatformService.object);
const tool = toolsService.getToolByName('no-such-tool');
assert(tool === undefined, 'for a not defined tool, expected value is undefined');
});
});

View File

@@ -35,14 +35,14 @@ const testValidations = [
}
];
suite('Validation', () => {
suite('createValidation and validate input Box', () => {
setup(() => {
describe('Validation', () => {
describe('createValidation and validate input Box', () => {
beforeEach(() => {
sinon.restore(); //cleanup all previously defined sinon mocks
inputBoxStub = sinon.stub(inputBox, 'updateProperty').resolves();
});
testValidations.forEach(testObj => {
test(`validationType: ${testObj.type}`, async () => {
it(`validationType: ${testObj.type}`, async () => {
const validation = createValidation(testObj, async () => undefined, async (_varName: string) => undefined);
switch (testObj.type) {
case ValidationType.IsInteger: should(validation).be.instanceOf(IntegerValidation); break;
@@ -59,7 +59,7 @@ suite('Validation', () => {
});
});
suite('IntegerValidation', () => {
describe('IntegerValidation', () => {
// all the below test values are arbitrary representative values or sentinel values for integer validation
[
{ value: '342520596781', expected: true },
@@ -72,7 +72,7 @@ suite('Validation', () => {
{ value: NaN, expected: false },
].forEach((testObj) => {
const displayTestValue = getDisplayString(testObj.value);
test(`testValue:${displayTestValue}`, async () => {
it(`testValue:${displayTestValue}`, async () => {
const validationDescription = `value: ${displayTestValue} was not an integer`;
const validation = new IntegerValidation(
{ type: ValidationType.IsInteger, description: validationDescription },
@@ -83,7 +83,7 @@ suite('Validation', () => {
});
});
suite('RegexValidation', () => {
describe('RegexValidation', () => {
const testRegex = '^[0-9]+$';
// tests
[
@@ -97,7 +97,7 @@ suite('Validation', () => {
{ value: undefined, expected: false },
].forEach(testOb => {
const displayTestValue = getDisplayString(testOb.value);
test(`regex: /${testRegex}/, testValue:${displayTestValue}, expect result: ${testOb.expected}`, async () => {
it(`regex: /${testRegex}/, testValue:${displayTestValue}, expect result: ${testOb.expected}`, async () => {
const validationDescription = `value:${displayTestValue} did not match the regex:/${testRegex}/`;
const validation = new RegexValidation(
{ type: ValidationType.IsInteger, description: validationDescription, regex: testRegex },
@@ -108,7 +108,7 @@ suite('Validation', () => {
});
});
suite('LessThanOrEqualsValidation', () => {
describe('LessThanOrEqualsValidation', () => {
const targetVariableName = 'comparisonTarget';
// tests - when operands are mix of string and number then number comparison is performed
[
@@ -147,7 +147,7 @@ suite('Validation', () => {
].forEach(testObj => {
const displayTestValue = getDisplayString(testObj.value);
const displayTargetValue = getDisplayString(testObj.targetValue);
test(`testValue:${displayTestValue}, targetValue:${displayTargetValue}`, async () => {
it(`testValue:${displayTestValue}, targetValue:${displayTargetValue}`, async () => {
const validationDescription = `${displayTestValue} did not test as <= ${displayTargetValue}`;
const validation = new LessThanOrEqualsValidation(
{ type: ValidationType.IsInteger, description: validationDescription, target: targetVariableName },
@@ -159,7 +159,7 @@ suite('Validation', () => {
});
});
suite('GreaterThanOrEqualsValidation', () => {
describe('GreaterThanOrEqualsValidation', () => {
const targetVariableName = 'comparisonTarget';
// tests - when operands are mix of string and number then number comparison is performed
[
@@ -190,7 +190,7 @@ suite('Validation', () => {
].forEach(testObj => {
const displayTestValue = getDisplayString(testObj.value);
const displayTargetValue = getDisplayString(testObj.targetValue);
test(`testValue:${displayTestValue}, targetValue:${displayTargetValue}`, async () => {
it(`testValue:${displayTestValue}, targetValue:${displayTargetValue}`, async () => {
const validationDescription = `${displayTestValue} did not test as >= ${displayTargetValue}`;
const validation = new GreaterThanOrEqualsValidation(
{ type: ValidationType.IsInteger, description: validationDescription, target: targetVariableName },