From 890c922a865d70e42a0132744e9d58e48ed1cb3b Mon Sep 17 00:00:00 2001 From: Krishna Acondy Date: Tue, 8 Dec 2020 07:52:07 +0000 Subject: [PATCH] fix(sasjs-add): fix tests and restructure code --- src/commands/{ => add}/add-credential.ts | 9 +- src/commands/add/add-target.ts | 102 ++++++++++++++ src/commands/add/config.ts | 12 ++ src/commands/{add-target.ts => add/input.ts} | 118 ++-------------- src/commands/index.js | 4 +- src/types/TargetScope.ts | 4 + test/commands/add-target.spec.ts | 98 +++++++++++++ test/commands/add.spec.js | 137 ------------------- 8 files changed, 232 insertions(+), 252 deletions(-) rename src/commands/{ => add}/add-credential.ts (96%) create mode 100644 src/commands/add/add-target.ts create mode 100644 src/commands/add/config.ts rename src/commands/{add-target.ts => add/input.ts} (64%) create mode 100644 src/types/TargetScope.ts create mode 100644 test/commands/add-target.spec.ts delete mode 100644 test/commands/add.spec.js diff --git a/src/commands/add-credential.ts b/src/commands/add/add-credential.ts similarity index 96% rename from src/commands/add-credential.ts rename to src/commands/add/add-credential.ts index 604ca9b51..62374e9d6 100644 --- a/src/commands/add-credential.ts +++ b/src/commands/add/add-credential.ts @@ -3,13 +3,14 @@ import dotenv from 'dotenv' import { Logger, LogLevel } from '@sasjs/utils/logger' import { getString } from '@sasjs/utils/input' import { SasAuthResponse, Target } from '@sasjs/utils/types' + +import SASjs from '@sasjs/adapter/node' +import { getNewAccessToken } from '../../utils/auth-utils' import { findTargetInConfiguration, saveToGlobalConfig -} from '../utils/config-utils' -import { getNewAccessToken } from '../utils/auth-utils' -import SASjs from '@sasjs/adapter/node' -import { createFile } from '../utils/file-utils' +} from '../../utils/config-utils' +import { createFile } from '../../utils/file-utils' /** * Creates a .env file for the specified target. diff --git a/src/commands/add/add-target.ts b/src/commands/add/add-target.ts new file mode 100644 index 000000000..5776575bc --- /dev/null +++ b/src/commands/add/add-target.ts @@ -0,0 +1,102 @@ +import { Logger, LogLevel } from '@sasjs/utils/logger' +import { Target, ServerType } from '@sasjs/utils/types' + +import path from 'path' + +import { + findTargetInConfiguration, + saveToGlobalConfig +} from '../../utils/config-utils' +import { createFile } from '../../utils/file-utils' +import { TargetScope } from '../../types/TargetScope' +import { + getCommonFields, + getAndValidateSasViyaFields, + getAndValidateSas9Fields +} from './input' +import { getLocalConfig } from './config' + +export async function addTarget(): Promise { + const logLevel = (process.env.LOG_LEVEL || LogLevel.Error) as LogLevel + const logger = new Logger(logLevel) + const { scope, serverType, name, appLoc, serverUrl } = await getCommonFields() + + let target: Partial | Target = { + name, + serverType: serverType, + serverUrl, + appLoc + } + + let filePath = await saveConfig(scope, target as Target) + logger.info(`Target configuration has been saved to ${filePath}.`) + + if (serverType === ServerType.Sas9) { + const sas9FieldValues = await getAndValidateSas9Fields() + target = { + ...target, + tgtBuildVars: sas9FieldValues, + tgtDeployVars: sas9FieldValues + } + } else { + const { contextName } = await getAndValidateSasViyaFields( + name, + scope, + serverUrl, + logger + ) + + target = { + ...target, + tgtBuildVars: { contextName }, + tgtDeployVars: { contextName }, + deployServicePack: true, + tgtDeployScripts: [] + } + + const { target: currentTarget } = await findTargetInConfiguration(name) + target = { ...currentTarget, ...target } + } + + filePath = await saveConfig(scope, target as Target) + logger.info(`Target configuration has been saved to ${filePath}.`) + return true +} + +async function saveConfig(scope: TargetScope, target: Target) { + let filePath = '' + if (scope === TargetScope.Local) { + filePath = await saveToLocalConfig(target as Target) + } else if (scope === TargetScope.Global) { + filePath = await saveToGlobalConfig(target as Target) + } + + return filePath +} + +async function saveToLocalConfig(buildTarget: Target) { + const buildSourceFolder = require('../../constants').get().buildSourceFolder + let config = await getLocalConfig() + if (config) { + if (config.targets && config.targets.length) { + const existingTargetIndex = config.targets.findIndex( + (t: Target) => t.name === buildTarget.name + ) + if (existingTargetIndex > -1) { + config.targets[existingTargetIndex] = buildTarget + } else { + config.targets.push(buildTarget) + } + } else { + config.targets = [buildTarget] + } + } else { + config = { targets: [buildTarget] } + } + + const configPath = path.join(buildSourceFolder, 'sasjsconfig.json') + + await createFile(configPath, JSON.stringify(config, null, 2)) + + return configPath +} diff --git a/src/commands/add/config.ts b/src/commands/add/config.ts new file mode 100644 index 000000000..c3e25f535 --- /dev/null +++ b/src/commands/add/config.ts @@ -0,0 +1,12 @@ +import { create } from '../create' +import path from 'path' +import { getConfiguration } from '../../utils/config-utils' + +export async function getLocalConfig() { + const buildSourceFolder = require('../../constants').get().buildSourceFolder + const config = await getConfiguration( + path.join(buildSourceFolder, 'sasjsconfig.json') + ) + if (!config) await create('.', 'sasonly') + return config +} diff --git a/src/commands/add-target.ts b/src/commands/add/input.ts similarity index 64% rename from src/commands/add-target.ts rename to src/commands/add/input.ts index 7b3db3889..d80daa005 100644 --- a/src/commands/add-target.ts +++ b/src/commands/add/input.ts @@ -1,6 +1,3 @@ -import { create } from './create' -import { Logger, LogLevel } from '@sasjs/utils/logger' -import { Target, ServerType } from '@sasjs/utils/types' import { getNumber, getString, @@ -8,91 +5,21 @@ import { getChoice, getUrl } from '@sasjs/utils/input' +import { Target, ServerType } from '@sasjs/utils/types' +import { Logger, LogLevel } from '@sasjs/utils/logger' import chalk from 'chalk' import path from 'path' import dotenv from 'dotenv' import SASjs from '@sasjs/adapter/node' +import { TargetScope } from '../../types/TargetScope' import { - getGlobalRcFile, - getConfiguration, findTargetInConfiguration, - saveToGlobalConfig -} from '../utils/config-utils' -import { createFile } from '../utils/file-utils' + getGlobalRcFile +} from '../../utils/config-utils' import { addCredential } from './add-credential' +import { getLocalConfig } from './config' -export enum TargetScope { - Global = 'Global', - Local = 'Local' -} - -export async function addTarget() { - const logLevel = (process.env.LOG_LEVEL || LogLevel.Error) as LogLevel - const logger = new Logger(logLevel) - const { scope, serverType, name, appLoc, serverUrl } = await getCommonFields() - - let target: Partial | Target = { - name, - serverType: serverType, - serverUrl, - appLoc - } - - let filePath = await saveConfig(scope, target as Target) - logger.info(`Target configuration has been saved to ${filePath}.`) - - if (serverType === ServerType.Sas9) { - const sas9FieldValues = await getAndValidateSas9Fields() - target = { - ...target, - tgtBuildVars: sas9FieldValues, - tgtDeployVars: sas9FieldValues - } - } else { - const { contextName } = await getAndValidateSasViyaFields( - name, - scope, - serverUrl, - logger - ) - - target = { - ...target, - tgtBuildVars: { contextName }, - tgtDeployVars: { contextName }, - deployServicePack: true, - tgtDeployScripts: [] - } - - const { target: currentTarget } = await findTargetInConfiguration(name) - target = { ...currentTarget, ...target } - } - - filePath = await saveConfig(scope, target as Target) - logger.info(`Target configuration has been saved to ${filePath}.`) -} - -async function saveConfig(scope: TargetScope, target: Target) { - let filePath = '' - if (scope === TargetScope.Local) { - filePath = await saveToLocalConfig(target as Target) - } else if (scope === TargetScope.Global) { - filePath = await saveToGlobalConfig(target as Target) - } - - return filePath -} - -async function getLocalConfig() { - const buildSourceFolder = require('../constants').get().buildSourceFolder - const config = await getConfiguration( - path.join(buildSourceFolder, 'sasjsconfig.json') - ) - if (!config) await create('.', 'sasonly') - return config -} - -async function getCommonFields() { +export async function getCommonFields() { const scope = await getAndValidateScope() const serverType = await getAndValidateServerType() const name = await getAndValidateTargetName(scope, serverType) @@ -104,33 +31,6 @@ async function getCommonFields() { return { scope, serverType, name, appLoc, serverUrl } } -async function saveToLocalConfig(buildTarget: Target) { - const buildSourceFolder = require('../constants').get().buildSourceFolder - let config = await getLocalConfig() - if (config) { - if (config.targets && config.targets.length) { - const existingTargetIndex = config.targets.findIndex( - (t: Target) => t.name === buildTarget.name - ) - if (existingTargetIndex > -1) { - config.targets[existingTargetIndex] = buildTarget - } else { - config.targets.push(buildTarget) - } - } else { - config.targets = [buildTarget] - } - } else { - config = { targets: [buildTarget] } - } - - const configPath = path.join(buildSourceFolder, 'sasjsconfig.json') - - await createFile(configPath, JSON.stringify(config, null, 2)) - - return configPath -} - async function getAndValidateScope(): Promise { const { scope } = await getChoice( 'scope', @@ -217,7 +117,7 @@ async function getAndValidateTargetName( return targetName } -async function getAndValidateSas9Fields() { +export async function getAndValidateSas9Fields() { const { serverName } = await getString( 'serverName', 'Please enter a server name (default is SASApp): ', @@ -234,7 +134,7 @@ async function getAndValidateSas9Fields() { return { serverName, repositoryName } } -async function getAndValidateSasViyaFields( +export async function getAndValidateSasViyaFields( targetName: string, scope: TargetScope, serverUrl: string, diff --git a/src/commands/index.js b/src/commands/index.js index 8509342ef..72abac1cc 100644 --- a/src/commands/index.js +++ b/src/commands/index.js @@ -1,5 +1,5 @@ -export { addTarget } from './add-target' -export { addCredential } from './add-credential' +export { addTarget } from './add/add-target' +export { addCredential } from './add/add-credential' export { build, diff --git a/src/types/TargetScope.ts b/src/types/TargetScope.ts new file mode 100644 index 000000000..32cd68e27 --- /dev/null +++ b/src/types/TargetScope.ts @@ -0,0 +1,4 @@ +export enum TargetScope { + Global = 'Global', + Local = 'Local' +} diff --git a/test/commands/add-target.spec.ts b/test/commands/add-target.spec.ts new file mode 100644 index 000000000..f8f023ab9 --- /dev/null +++ b/test/commands/add-target.spec.ts @@ -0,0 +1,98 @@ +import { ServerType, Target } from '@sasjs/utils/types' +import dotenv from 'dotenv' +import path from 'path' +import * as inputModule from '../../src/commands/add/input' +import { addTarget } from '../../src/commands/add/add-target' +import { TargetScope } from '../../src/types/TargetScope' +import { getConfiguration, getGlobalRcFile } from '../../src/utils/config-utils' +import { deleteFolder, createFolder } from '../../src/utils/file-utils' +import { generateTimestamp } from '../../src/utils/utils' + +describe('mocked addTarget', () => { + const testingAppFolder = `cli-tests-add-${generateTimestamp()}` + const targetName = `test-viya-${generateTimestamp()}` + + beforeAll(async () => { + process.projectDir = path.join(process.cwd(), testingAppFolder) + await createFolder(process.projectDir) + dotenv.config() + }) + + afterAll(async () => { + const projectDirPath = path.join(process.projectDir) + await deleteFolder(projectDirPath) + }, 60 * 1000) + + afterEach(async () => { + const sasjsDirPath = path.join(process.projectDir, 'sasjs') + await deleteFolder(sasjsDirPath) + }, 60 * 1000) + it('should create a target in the local sasjsconfig.json file', async (done) => { + const commonFields = { + scope: TargetScope.Local, + serverType: ServerType.SasViya, + name: targetName, + appLoc: '/Public/app', + serverUrl: process.env.SERVER_URL as string + } + jest + .spyOn(inputModule, 'getCommonFields') + .mockImplementation(() => Promise.resolve(commonFields)) + jest + .spyOn(inputModule, 'getAndValidateSasViyaFields') + .mockImplementation(() => + Promise.resolve({ contextName: 'Test Context' }) + ) + + await expect(addTarget()).resolves.toEqual(true) + + const buildSourceFolder = require('../../src/constants').get() + .buildSourceFolder + const config = await getConfiguration( + path.join(buildSourceFolder, 'sasjsconfig.json') + ) + expect(config).toBeTruthy() + expect(config.targets).toBeTruthy() + const target: Target = config.targets.find( + (t: Target) => t.name === targetName + ) + expect(target.name).toEqual(targetName) + expect(target.serverType).toEqual(ServerType.SasViya) + expect(target.appLoc).toEqual('/Public/app') + expect(target.serverUrl).toEqual(process.env.SERVER_URL) + done() + }) + + it('should create a target in the global .sasjsrc file', async (done) => { + const targetName = `test-viya-${generateTimestamp()}` + const commonFields = { + scope: TargetScope.Global, + serverType: ServerType.SasViya, + name: targetName, + appLoc: '/Public/app', + serverUrl: process.env.SERVER_URL as string + } + jest + .spyOn(inputModule, 'getCommonFields') + .mockImplementation(() => Promise.resolve(commonFields)) + jest + .spyOn(inputModule, 'getAndValidateSasViyaFields') + .mockImplementation(() => + Promise.resolve({ contextName: 'Test Context' }) + ) + + await expect(addTarget()).resolves.toEqual(true) + + const config = await getGlobalRcFile() + expect(config).toBeTruthy() + expect(config.targets).toBeTruthy() + const target: Target = config.targets.find( + (t: Target) => t.name === targetName + ) + expect(target.name).toEqual(targetName) + expect(target.serverType).toEqual(ServerType.SasViya) + expect(target.appLoc).toEqual('/Public/app') + expect(target.serverUrl).toEqual(process.env.SERVER_URL) + done() + }) +}) diff --git a/test/commands/add.spec.js b/test/commands/add.spec.js deleted file mode 100644 index 425221843..000000000 --- a/test/commands/add.spec.js +++ /dev/null @@ -1,137 +0,0 @@ -import dotenv from 'dotenv' -import path from 'path' -import { add } from '../../src/main' -import { getConfiguration, getGlobalRcFile } from '../../src/utils/config-utils' -import { deleteFolder, createFolder } from '../../src/utils/file-utils' -import { generateTimestamp } from '../../src/utils/utils' - -describe('sasjs add', () => { - const testingAppFolder = 'cli-tests-add' - let stdin - - beforeAll(async () => { - process.projectDir = path.join(process.cwd(), testingAppFolder) - await createFolder(process.projectDir) - dotenv.config() - stdin = require('mock-stdin').stdin() - }) - - describe('add', () => { - it( - 'should let user add build target to localConfig', - async () => { - const timestamp = generateTimestamp() - - const serverUrl = process.env.SERVER_URL - const tgtName = `test-viya-${timestamp}` - const username = process.env.SAS_USERNAME - const password = process.env.SAS_PASSWORD - const clientId = process.env.CLIENT - const secretId = process.env.SECRET - - setTimeout(async () => { - stdin.send(['\r']) - stdin.send(['\r']) - stdin.send([`${tgtName}\r`]) - stdin.send(['\r']) - stdin.send([`${serverUrl}\r`]) - stdin.send([`${clientId}\r`]) - stdin.send([`${secretId}\r`]) - - const authCodeContent = await browserGetAuthorizationCode({ - serverUrl, - clientId, - username, - password - }) - - stdin.send([`${authCodeContent}\r`]) - stdin.send([`1\r`]) - }, 1000) - - await expect(add('add')).resolves.toEqual(true) - - const buildSourceFolder = require('../../src/constants').get() - .buildSourceFolder - const config = await getConfiguration( - path.join(buildSourceFolder, 'sasjsconfig.json') - ) - - expect(config).toEqual(expect.anything()) - expect(config.targets).toEqual(expect.anything()) - - const target = config.targets.find((t) => t.name === tgtName) - - expect(target).toEqual(expect.anything()) - expect(target.tgtBuildVars.client).toEqual(clientId) - expect(target.tgtBuildVars.secret).toEqual(secretId) - expect(target.tgtDeployVars.client).toEqual(clientId) - expect(target.tgtDeployVars.secret).toEqual(secretId) - }, - 60 * 1000 - ) - - it( - 'should let user add build target to globalConfig', - async () => { - const timestamp = generateTimestamp() - - const serverUrl = process.env.SERVER_URL - const tgtName = `test-viya-${timestamp}` - const username = process.env.SAS_USERNAME - const password = process.env.SAS_PASSWORD - const clientId = process.env.CLIENT - const secretId = process.env.SECRET - - setTimeout(async () => { - stdin.send(['2\r']) - stdin.send(['\r']) - stdin.send([`${tgtName}\r`]) - stdin.send(['\r']) - stdin.send([`${serverUrl}\r`]) - stdin.send([`${clientId}\r`]) - stdin.send([`${secretId}\r`]) - - const authCodeContent = await browserGetAuthorizationCode({ - serverUrl, - clientId, - username, - password - }) - - stdin.send([`${authCodeContent}\r`]) - stdin.send([`1\r`]) - }, 1000) - - await expect(add('add')).resolves.toEqual(true) - - const config = await getGlobalRcFile() - - expect(config).toEqual(expect.anything()) - expect(config.targets).toEqual(expect.anything()) - - const target = config.targets.find((t) => t.name === tgtName) - - expect(target).toEqual(expect.anything()) - expect(target.tgtBuildVars.client).toEqual(clientId) - expect(target.tgtBuildVars.secret).toEqual(secretId) - expect(target.tgtDeployVars.client).toEqual(clientId) - expect(target.tgtDeployVars.secret).toEqual(secretId) - - await removeFromGlobalConfigs(tgtName) - }, - 60 * 1000 - ) - }) - - afterEach(async () => { - const sasjsDirPath = path.join(process.projectDir, 'sasjs') - - await deleteFolder(sasjsDirPath) - }, 60 * 1000) - afterAll(async () => { - const projectDirPath = path.join(process.projectDir) - - await deleteFolder(projectDirPath) - }, 60 * 1000) -})