Added Unit tests (#15)

* Added unit tests for Azure PowerShell

* Added unit tests

* changes in utils

* removed babel

* changed variable name of enable-PSSession

* refactor

* added ci.yml

* changes in utils test
This commit is contained in:
aksm-ms
2020-04-08 17:42:18 +05:30
committed by GitHub
parent 73efa776b5
commit 3ec3e73a1c
14 changed files with 5019 additions and 27 deletions

28
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
on:
pull_request:
branches:
- master
push:
branches:
- master
jobs:
build_test_job:
name: 'Build and test job'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v2
- name: 'Validate build'
run: |
npm install
npm run build
- name: 'Run L0 tests'
run: |
npm run test

View File

@@ -0,0 +1,39 @@
import { ServicePrincipalLogin } from '../../src/PowerShell/ServicePrincipalLogin';
jest.mock('../../src/PowerShell/Utilities/Utils');
jest.mock('../../src/PowerShell/Utilities/PowerShellToolRunner');
let spnlogin: ServicePrincipalLogin;
beforeAll(() => {
spnlogin = new ServicePrincipalLogin("servicePrincipalID", "servicePrinicipalkey", "tenantId", "subscriptionId");
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('Testing initialize', () => {
let initializeSpy;
beforeEach(() => {
initializeSpy = jest.spyOn(spnlogin, 'initialize');
});
test('ServicePrincipalLogin initialize should pass', async () => {
await spnlogin.initialize();
expect(initializeSpy).toHaveBeenCalled();
});
});
describe('Testing login', () => {
let loginSpy;
beforeEach(() => {
loginSpy = jest.spyOn(spnlogin, 'login');
});
test('ServicePrincipal login should pass', async () => {
loginSpy.mockImplementationOnce(() => Promise.resolve(
console.log('Azure PowerShell session successfully initialized')));
await spnlogin.login();
expect(loginSpy).toHaveBeenCalled();
});
});

View File

@@ -0,0 +1,48 @@
import Utils from '../../../src/PowerShell/Utilities/Utils';
const version: string = '9.0.0';
const moduleName: string = 'az';
afterEach(() => {
jest.restoreAllMocks();
});
describe('Testing isValidVersion', () => {
const validVersion: string = '1.2.4';
const invalidVersion: string = 'a.bcd';
test('isValidVersion should be true', () => {
expect(Utils.isValidVersion(validVersion)).toBeTruthy();
});
test('isValidVersion should be false', () => {
expect(Utils.isValidVersion(invalidVersion)).toBeFalsy();
});
});
describe('Testing setPSModulePath', () => {
test('PSModulepath with azPSVersion non-empty', () => {
if(!process.env.PSModulePath) {
process.env.PSModulePath = process.env.PSModulePath + "modulePath";
}
Utils.setPSModulePath(version);
expect(process.env.PSModulepath).toContain(version);
});
test('PSModulePath with azPSVersion empty', () => {
const currPSModulePath = process.env.PSModulepath;
Utils.setPSModulePath();
expect(process.env.PSModulePath).not.toEqual(currPSModulePath);
});
});
describe('Testing getLatestModule', () => {
let getLatestModuleSpy;
beforeEach(() => {
getLatestModuleSpy = jest.spyOn(Utils, 'getLatestModule');
});
test('getLatestModule should pass', async () => {
getLatestModuleSpy.mockImplementationOnce((_moduleName: string) => Promise.resolve(version));
await Utils.getLatestModule(moduleName);
expect(getLatestModuleSpy).toHaveBeenCalled();
});
});

View File

@@ -5,7 +5,7 @@ inputs:
creds: creds:
description: 'Paste output of `az ad sp create-for-rbac` as value of secret variable: AZURE_CREDENTIALS' description: 'Paste output of `az ad sp create-for-rbac` as value of secret variable: AZURE_CREDENTIALS'
required: true required: true
enable-PSSession: enable-AzPSSession:
description: 'SetthisvaluetotruetoenableAzurePowerShellLogininadditiontoAzCLIlogin' description: 'SetthisvaluetotruetoenableAzurePowerShellLogininadditiontoAzCLIlogin'
required: false required: false
default: false default: false

14
jest.config.js Normal file
View File

@@ -0,0 +1,14 @@
// For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.html
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
};

View File

@@ -31,10 +31,5 @@ class PowerShellToolRunner {
yield exec.exec(`${PowerShellToolRunner.psPath} -Command`, [scriptBlock], options); yield exec.exec(`${PowerShellToolRunner.psPath} -Command`, [scriptBlock], options);
}); });
} }
static executePowerShellCommand(command, options = {}) {
return __awaiter(this, void 0, void 0, function* () {
yield exec.exec(`"${PowerShellToolRunner.psPath}" -Command "${command}"`, [], options);
});
}
} }
exports.default = PowerShellToolRunner; exports.default = PowerShellToolRunner;

View File

@@ -26,12 +26,9 @@ const PowerShellToolRunner_1 = __importDefault(require("./PowerShellToolRunner")
class Utils { class Utils {
/** /**
* Add the folder path where Az modules are present to PSModulePath based on runner * Add the folder path where Az modules are present to PSModulePath based on runner
*
* @param azPSVersion * @param azPSVersion
*
* If azPSVersion is empty, folder path in which all Az modules are present are set * If azPSVersion is empty, folder path in which all Az modules are present are set
* If azPSVersion is not empty, folder path of exact Az module version is set * If azPSVersion is not empty, folder path of exact Az module version is set
*
*/ */
static setPSModulePath(azPSVersion = "") { static setPSModulePath(azPSVersion = "") {
let modulePath = ""; let modulePath = "";

View File

@@ -44,7 +44,7 @@ function main() {
let servicePrincipalKey = secrets.getSecret("$.clientSecret", true); let servicePrincipalKey = secrets.getSecret("$.clientSecret", true);
let tenantId = secrets.getSecret("$.tenantId", false); let tenantId = secrets.getSecret("$.tenantId", false);
let subscriptionId = secrets.getSecret("$.subscriptionId", false); let subscriptionId = secrets.getSecret("$.subscriptionId", false);
const enablePSSession = core.getInput('enable-PSSession').toLowerCase() === "true"; const enableAzPSSession = core.getInput('enable-AzPSSession').toLowerCase() === "true";
if (!servicePrincipalId || !servicePrincipalKey || !tenantId || !subscriptionId) { if (!servicePrincipalId || !servicePrincipalKey || !tenantId || !subscriptionId) {
throw new Error("Not all values are present in the creds object. Ensure clientId, clientSecret, tenantId and subscriptionId are supplied."); throw new Error("Not all values are present in the creds object. Ensure clientId, clientSecret, tenantId and subscriptionId are supplied.");
} }
@@ -52,7 +52,7 @@ function main() {
yield executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`); yield executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`);
yield executeAzCliCommand(`account set --subscription "${subscriptionId}"`); yield executeAzCliCommand(`account set --subscription "${subscriptionId}"`);
isAzCLISuccess = true; isAzCLISuccess = true;
if (enablePSSession) { if (enableAzPSSession) {
// Attempting Az PS login // Attempting Az PS login
console.log(`Running Azure PS Login`); console.log(`Running Azure PS Login`);
const spnlogin = new ServicePrincipalLogin_1.ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId); const spnlogin = new ServicePrincipalLogin_1.ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId);

4876
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,12 +5,16 @@
"main": "lib/main.js", "main": "lib/main.js",
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"test": "echo \"Error: no test specified\" && exit 1" "test": "jest"
}, },
"author": "Sumiran Aggarwal", "author": "Sumiran Aggarwal",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@types/jest": "^25.1.4",
"@types/node": "^12.7.11", "@types/node": "^12.7.11",
"jest": "^25.2.4",
"jest-circus": "^25.2.7",
"ts-jest": "^25.3.0",
"typescript": "^3.6.3" "typescript": "^3.6.3"
}, },
"dependencies": { "dependencies": {

View File

@@ -13,9 +13,4 @@ export default class PowerShellToolRunner {
static async executePowerShellScriptBlock(scriptBlock: string, options: any = {}) { static async executePowerShellScriptBlock(scriptBlock: string, options: any = {}) {
await exec.exec(`${PowerShellToolRunner.psPath} -Command`, [scriptBlock], options) await exec.exec(`${PowerShellToolRunner.psPath} -Command`, [scriptBlock], options)
} }
static async executePowerShellCommand(command: string, options: any = {}) {
await exec.exec(`"${PowerShellToolRunner.psPath}" -Command "${command}"`, [], options);
}
} }

View File

@@ -7,12 +7,9 @@ import PowerShellToolRunner from './PowerShellToolRunner';
export default class Utils { export default class Utils {
/** /**
* Add the folder path where Az modules are present to PSModulePath based on runner * Add the folder path where Az modules are present to PSModulePath based on runner
*
* @param azPSVersion * @param azPSVersion
*
* If azPSVersion is empty, folder path in which all Az modules are present are set * If azPSVersion is empty, folder path in which all Az modules are present are set
* If azPSVersion is not empty, folder path of exact Az module version is set * If azPSVersion is not empty, folder path of exact Az module version is set
*
*/ */
static setPSModulePath(azPSVersion: string = "") { static setPSModulePath(azPSVersion: string = "") {
let modulePath: string = ""; let modulePath: string = "";
@@ -34,7 +31,7 @@ export default class Utils {
process.env.PSModulePath = `${modulePath}${process.env.PSModulePath}`; process.env.PSModulePath = `${modulePath}${process.env.PSModulePath}`;
} }
static async getLatestModule(moduleName: string): Promise<any> { static async getLatestModule(moduleName: string): Promise<string> {
let output: string = ""; let output: string = "";
const options: any = { const options: any = {
listeners: { listeners: {

View File

@@ -30,7 +30,7 @@ async function main() {
let servicePrincipalKey = secrets.getSecret("$.clientSecret", true); let servicePrincipalKey = secrets.getSecret("$.clientSecret", true);
let tenantId = secrets.getSecret("$.tenantId", false); let tenantId = secrets.getSecret("$.tenantId", false);
let subscriptionId = secrets.getSecret("$.subscriptionId", false); let subscriptionId = secrets.getSecret("$.subscriptionId", false);
const enablePSSession = core.getInput('enable-PSSession').toLowerCase() === "true"; const enableAzPSSession = core.getInput('enable-AzPSSession').toLowerCase() === "true";
if (!servicePrincipalId || !servicePrincipalKey || !tenantId || !subscriptionId) { if (!servicePrincipalId || !servicePrincipalKey || !tenantId || !subscriptionId) {
throw new Error("Not all values are present in the creds object. Ensure clientId, clientSecret, tenantId and subscriptionId are supplied."); throw new Error("Not all values are present in the creds object. Ensure clientId, clientSecret, tenantId and subscriptionId are supplied.");
} }
@@ -38,7 +38,7 @@ async function main() {
await executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`); await executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`);
await executeAzCliCommand(`account set --subscription "${subscriptionId}"`); await executeAzCliCommand(`account set --subscription "${subscriptionId}"`);
isAzCLISuccess = true; isAzCLISuccess = true;
if (enablePSSession) { if (enableAzPSSession) {
// Attempting Az PS login // Attempting Az PS login
console.log(`Running Azure PS Login`); console.log(`Running Azure PS Login`);
const spnlogin: ServicePrincipalLogin = new ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId); const spnlogin: ServicePrincipalLogin = new ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId);

View File

@@ -56,5 +56,8 @@
/* Experimental Options */ /* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
} },
"exclude" : [
"./__tests__"
]
} }