From dea95ff9fa5289e282b30702e34459d2acd7db7f Mon Sep 17 00:00:00 2001 From: Himavanth Date: Mon, 5 Oct 2020 13:15:59 +0530 Subject: [PATCH 1/3] New manifest and action level logs with new strip and tail options --- src/commands/app/logs.js | 41 ++++++- src/lib/app-helper.js | 38 ------ src/lib/runDev.js | 6 +- test/__mocks__/@adobe/aio-lib-runtime.js | 3 +- test/commands/app/logs.test.js | 64 ++++++++-- test/commands/lib/app-helper.test.js | 142 ----------------------- test/commands/lib/poller.test.js | 13 +-- 7 files changed, 99 insertions(+), 208 deletions(-) diff --git a/src/commands/app/logs.js b/src/commands/app/logs.js index c1534481..cf871624 100644 --- a/src/commands/app/logs.js +++ b/src/commands/app/logs.js @@ -13,11 +13,13 @@ governing permissions and limitations under the License. const { flags } = require('@oclif/command') // const { cli } = require('cli-ux') const BaseCommand = require('../../BaseCommand') -const { wrapError, getLogs } = require('../../lib/app-helper') +const { wrapError } = require('../../lib/app-helper') +const rtLib = require('@adobe/aio-lib-runtime') class Logs extends BaseCommand { async run () { const { flags } = this.parse(Logs) + const config = this.getAppConfig() if (flags.limit < 1) { this.log('--limit should be > 0, using --limit=1') @@ -27,10 +29,26 @@ class Logs extends BaseCommand { flags.limit = 50 } + let filterActions = [] + if (flags.action) { + let actionName = flags.action + if (!actionName.includes('/')) { + actionName = config.ow.package + '/' + actionName + } + filterActions = [actionName] + } else { + Object.entries(config.manifest.full.packages).forEach((packageTuple) => { + Object.keys(packageTuple[1].actions).forEach((actionName) => { + packageTuple[0] = packageTuple[0].replace(/__APP_PACKAGE__/g, config.ow.package) + filterActions.push(packageTuple[0] + '/' + actionName) + }) + }) + } + try { const config = this.getAppConfig() - await getLogs(config, flags.limit, this.log) + await rtLib.printActionLogs(config, this.log, flags.limit, filterActions, flags.strip, flags.tail) } catch (error) { this.error(wrapError(error)) } @@ -46,11 +64,22 @@ Logs.flags = { description: 'Limit number of activations to fetch logs from ( 1-50 )', default: 1, char: 'l' + }), + action: flags.string({ + description: 'Fetch logs for a specific action', + default: '', + char: 'a' + }), + strip: flags.boolean({ + char: 'r', + description: 'strip timestamp information and output first line only', + default: false + }), + tail: flags.boolean({ + description: 'Fetch logs continuously', + char: 't', + default: false }) } -// Logs.args = [ -// ...BaseCommand.args -// ] - module.exports = Logs diff --git a/src/lib/app-helper.js b/src/lib/app-helper.js index e9353716..77b2e79d 100644 --- a/src/lib/app-helper.js +++ b/src/lib/app-helper.js @@ -17,7 +17,6 @@ const dotenv = require('dotenv') const aioLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin-app:lib-app-helper', { provider: 'debug' }) const { getToken, context } = require('@adobe/aio-lib-ims') const { CLI } = require('@adobe/aio-lib-ims/src/context') -const RuntimeLib = require('@adobe/aio-lib-runtime') const fetch = require('node-fetch') /** @private */ @@ -86,42 +85,6 @@ async function getCliInfo () { return { accessToken, env } } -async function getLogs (config, limit, logger, startTime = 0) { - // check for runtime credentials - RuntimeLib.utils.checkOpenWhiskCredentials(config) - const runtime = await RuntimeLib.init({ - // todo make this.config.ow compatible with Openwhisk config - apihost: config.ow.apihost, - apiversion: config.ow.apiversion, - api_key: config.ow.auth, - namespace: config.ow.namespace - }) - - // get activations - const listOptions = { limit: limit, skip: 0 } - const logFunc = logger || console.log - const activations = await runtime.activations.list(listOptions) - let lastActivationTime = 0 - // console.log('activations = ', activations) - for (let i = (activations.length - 1); i >= 0; i--) { - const activation = activations[i] - lastActivationTime = activation.start - if (lastActivationTime > startTime) { - const results = await runtime.activations.logs({ activationId: activation.activationId }) - // console.log('results = ', results) - // send fetched logs to console - if (results.logs.length > 0) { - logFunc(activation.name + ':' + activation.activationId) - results.logs.forEach(function (log) { - logFunc(log) - }) - logFunc() - } - } - } - return { lastActivationTime } -} - function getActionUrls (config, isRemoteDev = false, isLocalDev = false) { // set action urls // action urls {name: url}, if !LocalDev subdomain uses namespace @@ -349,7 +312,6 @@ module.exports = { wrapError, getCliInfo, getActionUrls, - getLogs, removeProtocolFromURL, urlJoin, checkFile, diff --git a/src/lib/runDev.js b/src/lib/runDev.js index 4a7c2030..f0ce1a10 100644 --- a/src/lib/runDev.js +++ b/src/lib/runDev.js @@ -11,7 +11,8 @@ governing permissions and limitations under the License. */ /* eslint-disable no-template-curly-in-string */ const aioLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin-app:runDev', { provider: 'debug' }) -const rtLibUtils = require('@adobe/aio-lib-runtime').utils +const rtLib = require('@adobe/aio-lib-runtime') +const rtLibUtils = rtLib.utils const path = require('path') const fs = require('fs-extra') @@ -232,7 +233,8 @@ async function runDev (args = [], config, options = {}, log) { async function logListener (args) { if (!args.resources.stopFetchLogs) { try { - const ret = await utils.getLogs(args.config, logOptions.limit || 1, console.log, logOptions.startTime) + // TODO : Is is better to just tail ? + const ret = await rtLib.printActionLogs(args.config, console.log, logOptions.limit || 1, [], false, false, undefined, logOptions.startTime) logOptions.limit = 30 logOptions.startTime = ret.lastActivationTime } catch (e) { diff --git a/test/__mocks__/@adobe/aio-lib-runtime.js b/test/__mocks__/@adobe/aio-lib-runtime.js index 5570936f..4bed8f3b 100644 --- a/test/__mocks__/@adobe/aio-lib-runtime.js +++ b/test/__mocks__/@adobe/aio-lib-runtime.js @@ -86,7 +86,8 @@ const init = jest.fn().mockReturnValue(mockRtLibInstance) const mockActionMethods = { buildActions: jest.fn(), deployActions: jest.fn(), - undeployActions: jest.fn() + undeployActions: jest.fn(), + printActionLogs: jest.fn() } module.exports = { utils: { diff --git a/test/commands/app/logs.test.js b/test/commands/app/logs.test.js index 8770b2b3..26a161d3 100644 --- a/test/commands/app/logs.test.js +++ b/test/commands/app/logs.test.js @@ -15,7 +15,25 @@ const BaseCommand = require('../../../src/BaseCommand') jest.mock('../../../src/lib/app-helper.js') const helpers = require('../../../src/lib/app-helper.js') - +const mockRuntimeLib = require('@adobe/aio-lib-runtime') +const printActionLogs = mockRuntimeLib.printActionLogs + +const fakeAppConfig = { + manifest: { + full: { + packages: { + jesttestpackage: { + actions: { + hello: {} + } + } + } + } + }, + ow: { + package: 'jesttestpackage' + } +} describe('interface', () => { test('exports', async () => { expect(typeof TheCommand).toEqual('function') @@ -40,63 +58,85 @@ describe('interface', () => { describe('run', () => { beforeEach(() => { - helpers.getLogs.mockReset() + printActionLogs.mockReset() helpers.wrapError.mockReset() }) test('no flags, sets limit to 1', async () => { const command = new TheCommand([]) - command.appConfig = { fake: 'config' } + command.appConfig = fakeAppConfig command.error = jest.fn() command.log = jest.fn() await command.run() - expect(helpers.getLogs).toHaveBeenCalledWith({ fake: 'config' }, 1, command.log) + expect(printActionLogs).toHaveBeenCalledWith(command.appConfig, command.log, 1, ['jesttestpackage/hello'], false, false) expect(command.error).not.toHaveBeenCalled() }) test('--limit < 1, sets limit to 1', async () => { const command = new TheCommand(['--limit', '-1']) - command.appConfig = { fake: 'config' } + command.appConfig = fakeAppConfig command.error = jest.fn() command.log = jest.fn() await command.run() expect(command.log).toHaveBeenCalledWith(expect.stringContaining('using --limit=1')) - expect(helpers.getLogs).toHaveBeenCalledWith({ fake: 'config' }, 1, command.log) + expect(printActionLogs).toHaveBeenCalledWith(fakeAppConfig, command.log, 1, ['jesttestpackage/hello'], false, false) expect(command.error).not.toHaveBeenCalled() }) test('--limit > 50, sets limit to 50', async () => { const command = new TheCommand(['--limit', '51']) - command.appConfig = { fake: 'config' } + command.appConfig = fakeAppConfig command.error = jest.fn() command.log = jest.fn() await command.run() expect(command.log).toHaveBeenCalledWith(expect.stringContaining('using --limit=50')) - expect(helpers.getLogs).toHaveBeenCalledWith({ fake: 'config' }, 50, command.log) + expect(printActionLogs).toHaveBeenCalledWith(fakeAppConfig, command.log, 50, ['jesttestpackage/hello'], false, false) expect(command.error).not.toHaveBeenCalled() }) test('--limit 32', async () => { const command = new TheCommand(['--limit', '32']) - command.appConfig = { fake: 'config' } + command.appConfig = fakeAppConfig + command.error = jest.fn() + command.log = jest.fn() + + await command.run() + expect(printActionLogs).toHaveBeenCalledWith(fakeAppConfig, command.log, 32, ['jesttestpackage/hello'], false, false) + expect(command.error).not.toHaveBeenCalled() + }) + + test('--action without including package name', async () => { + const command = new TheCommand(['--action', 'hello']) + command.appConfig = fakeAppConfig + command.error = jest.fn() + command.log = jest.fn() + + await command.run() + expect(printActionLogs).toHaveBeenCalledWith(fakeAppConfig, command.log, 1, ['jesttestpackage/hello'], false, false) + expect(command.error).not.toHaveBeenCalled() + }) + + test('--action including package name', async () => { + const command = new TheCommand(['--action', 'pkg1/hello']) + command.appConfig = fakeAppConfig command.error = jest.fn() command.log = jest.fn() await command.run() - expect(helpers.getLogs).toHaveBeenCalledWith({ fake: 'config' }, 32, command.log) + expect(printActionLogs).toHaveBeenCalledWith(fakeAppConfig, command.log, 1, ['pkg1/hello'], false, false) expect(command.error).not.toHaveBeenCalled() }) test('error while getting logs', async () => { const command = new TheCommand([]) - command.appConfig = { fake: 'config' } + command.appConfig = fakeAppConfig command.error = jest.fn() command.log = jest.fn() const theerror = new Error('I do not like logs') - helpers.getLogs.mockRejectedValue(theerror) + printActionLogs.mockRejectedValue(theerror) helpers.wrapError.mockReturnValue('wrapped error') await command.run() expect(command.error).toHaveBeenCalledWith('wrapped error') diff --git a/test/commands/lib/app-helper.test.js b/test/commands/lib/app-helper.test.js index 6bec4ee1..5000fe4d 100644 --- a/test/commands/lib/app-helper.test.js +++ b/test/commands/lib/app-helper.test.js @@ -13,7 +13,6 @@ const which = require('which') const fs = require('fs-extra') const execa = require('execa') const appHelper = require('../../../src/lib/app-helper') -const RuntimeLib = require('@adobe/aio-lib-runtime') describe('exports helper methods', () => { test('isNpmInstalled', () => { @@ -116,147 +115,6 @@ describe('exports helper methods', () => { expect(error.stack).toBeDefined() }) - describe('getLogs', () => { - const fakeConfig = { - ow: { - apihost: 'https://fake.com', - apiversion: 'v0', - auth: 'abcde', - namespace: 'dude' - } - } - const logger = jest.fn() - let rtLib - beforeEach(async () => { - RuntimeLib.mockReset() - rtLib = await RuntimeLib.init({ fake: 'credentials' }) - logger.mockReset() - }) - - test('inits the runtime lib instance', async () => { - rtLib.mockResolved('activations.list', []) - rtLib.mockResolved('activations.logs', { logs: [] }) - await appHelper.getLogs(fakeConfig, 1, logger) - expect(RuntimeLib.init).toHaveBeenCalledWith({ - namespace: fakeConfig.ow.namespace, - apihost: fakeConfig.ow.apihost, - api_key: fakeConfig.ow.auth, - apiversion: fakeConfig.ow.apiversion - }) - }) - test('(config, limit=1, logger) and no activations', async () => { - rtLib.mockResolved('activations.list', []) - rtLib.mockResolved('activations.logs', { logs: [] }) - await appHelper.getLogs(fakeConfig, 1, logger) - expect(RuntimeLib.init).toHaveBeenCalled() - expect(rtLib.activations.list).toHaveBeenCalledWith({ limit: 1, skip: 0 }) - expect(rtLib.activations.logs).not.toHaveBeenCalled() - expect(logger).not.toHaveBeenCalled() - }) - test('(config, limit=3, logger) and 3 activations and no logs', async () => { - rtLib.mockResolved('activations.list', [ - { activationId: 123, start: 555555, name: 'one' }, - { activationId: 456, start: 555666, name: 'two' }, - { activationId: 100, start: 666666, name: 'three' } - ]) - rtLib.mockResolved('activations.logs', { logs: [] }) - await appHelper.getLogs(fakeConfig, 3, logger) - expect(rtLib.activations.list).toHaveBeenCalledWith({ limit: 3, skip: 0 }) - expect(rtLib.activations.logs).toHaveBeenCalledTimes(3) - // reverse order - expect(rtLib.activations.logs).toHaveBeenNthCalledWith(1, { activationId: 100 }) - expect(rtLib.activations.logs).toHaveBeenNthCalledWith(2, { activationId: 456 }) - expect(rtLib.activations.logs).toHaveBeenNthCalledWith(3, { activationId: 123 }) - expect(logger).not.toHaveBeenCalled() - }) - test('(config, limit=45, logger) and 3 activations and logs for 2 of them', async () => { - rtLib.mockResolved('activations.list', [ - { activationId: 123, start: 555555, name: 'one' }, - { activationId: 456, start: 555666, name: 'two' }, - { activationId: 100, start: 666666, name: 'three' } - ]) - rtLib.mockFn('activations.logs').mockImplementation(a => { - if (a.activationId === 100) { - return { logs: ['three A', 'three B', 'three C'] } - } else if (a.activationId === 456) { - return { logs: ['two A \n two B'] } - } - return { logs: [] } - }) - - await appHelper.getLogs(fakeConfig, 45, logger) - expect(rtLib.activations.list).toHaveBeenCalledWith({ limit: 45, skip: 0 }) - expect(rtLib.activations.logs).toHaveBeenCalledTimes(3) - // reverse order - expect(rtLib.activations.logs).toHaveBeenNthCalledWith(1, { activationId: 100 }) - expect(rtLib.activations.logs).toHaveBeenNthCalledWith(2, { activationId: 456 }) - expect(rtLib.activations.logs).toHaveBeenNthCalledWith(3, { activationId: 123 }) - expect(logger).toHaveBeenCalledTimes(8) - expect(logger).toHaveBeenNthCalledWith(1, 'three:100') - expect(logger).toHaveBeenNthCalledWith(2, 'three A') - expect(logger).toHaveBeenNthCalledWith(3, 'three B') - expect(logger).toHaveBeenNthCalledWith(4, 'three C') - expect(logger).toHaveBeenNthCalledWith(5) // new line - expect(logger).toHaveBeenNthCalledWith(6, 'two:456') - expect(logger).toHaveBeenNthCalledWith(7, 'two A \n two B') - }) - - test('(config, limit=45, logger, startTime=bigger than first 2) and 3 activations and logs for 2 of them', async () => { - rtLib.mockResolved('activations.list', [ - { activationId: 123, start: 555555, name: 'one' }, - { activationId: 456, start: 555666, name: 'two' }, - { activationId: 100, start: 666666, name: 'three' } - ]) - rtLib.mockFn('activations.logs').mockImplementation(a => { - if (a.activationId === 100) { - return { logs: ['three A', 'three B', 'three C'] } - } else if (a.activationId === 456) { - return { logs: ['two A \n two B'] } - } - return { logs: [] } - }) - - await appHelper.getLogs(fakeConfig, 45, logger, 666665) - expect(rtLib.activations.list).toHaveBeenCalledWith({ limit: 45, skip: 0 }) - expect(rtLib.activations.logs).toHaveBeenCalledTimes(1) - // reverse order - expect(rtLib.activations.logs).toHaveBeenNthCalledWith(1, { activationId: 100 }) - expect(logger).toHaveBeenCalledTimes(5) - expect(logger).toHaveBeenNthCalledWith(1, 'three:100') - expect(logger).toHaveBeenNthCalledWith(2, 'three A') - expect(logger).toHaveBeenNthCalledWith(3, 'three B') - expect(logger).toHaveBeenNthCalledWith(4, 'three C') - expect(logger).toHaveBeenNthCalledWith(5) // new line - }) - - test('(config, limit=45, no logger) and 1 activation and 1 log', async () => { - const spy = jest.spyOn(console, 'log') - spy.mockImplementation(() => {}) - - rtLib.mockResolved('activations.list', [ - { activationId: 123, start: 555555, name: 'one' } - ]) - rtLib.mockFn('activations.logs').mockImplementation(a => { - if (a.activationId === 123) { - return { logs: ['one A'] } - } - return { logs: [] } - }) - - await appHelper.getLogs(fakeConfig, 45) - expect(rtLib.activations.list).toHaveBeenCalledWith({ limit: 45, skip: 0 }) - expect(rtLib.activations.logs).toHaveBeenCalledTimes(1) - // reverse order - expect(rtLib.activations.logs).toHaveBeenNthCalledWith(1, { activationId: 123 }) - expect(spy).toHaveBeenCalledTimes(3) - expect(spy).toHaveBeenNthCalledWith(1, 'one:123') - expect(spy).toHaveBeenNthCalledWith(2, 'one A') - expect(spy).toHaveBeenNthCalledWith(3) // new line - - spy.mockRestore() - }) - }) - describe('getActionUrls', () => { let fakeConfig beforeEach(() => { diff --git a/test/commands/lib/poller.test.js b/test/commands/lib/poller.test.js index fcb6b061..4cd63d81 100644 --- a/test/commands/lib/poller.test.js +++ b/test/commands/lib/poller.test.js @@ -28,7 +28,6 @@ const mockRuntimeLib = require('@adobe/aio-lib-runtime') const DeployActions = mockRuntimeLib.deployActions jest.mock('../../../src/lib/app-helper.js') -const mockHelpers = require('../../../src/lib/app-helper.js') describe('runDev logListener', () => { const ref = {} @@ -61,23 +60,23 @@ describe('runDev logListener', () => { global.fakeFileSystem.reset() fetch.mockReset() execa.mockReset() - mockHelpers.getLogs.mockReset() + mockRuntimeLib.printActionLogs.mockReset() }) test('should throw error on error from getLogs', async () => { - mockHelpers.getLogs.mockReset() - mockHelpers.getLogs.mockRejectedValue('error') + mockRuntimeLib.printActionLogs.mockReset() + mockRuntimeLib.printActionLogs.mockRejectedValue('error') await runDev([], ref.config, { fetchLogs: true }) jest.runAllTimers() - expect(mockHelpers.getLogs).toHaveBeenCalled() + expect(mockRuntimeLib.printActionLogs).toHaveBeenCalled() process.emit('SIGINT') }) test('should get action logs', async () => { - mockHelpers.getLogs.mockResolvedValueOnce({ lastActivationTime: 0 }) + mockRuntimeLib.printActionLogs.mockResolvedValueOnce({ lastActivationTime: 0 }) await runDev([], ref.config, { fetchLogs: true }) jest.runAllTimers() - expect(mockHelpers.getLogs).toHaveBeenCalled() + expect(mockRuntimeLib.printActionLogs).toHaveBeenCalled() process.emit('SIGINT') }) From 2ef9f3cde0c46683b5248be3e477557d1f6375ad Mon Sep 17 00:00:00 2001 From: Himavanth Date: Thu, 8 Oct 2020 16:56:03 +0530 Subject: [PATCH 2/3] cleanup and test fix --- src/commands/app/logs.js | 7 +++---- test/commands/app/init.test.js | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/commands/app/logs.js b/src/commands/app/logs.js index cf871624..4a3aebd2 100644 --- a/src/commands/app/logs.js +++ b/src/commands/app/logs.js @@ -38,16 +38,15 @@ class Logs extends BaseCommand { filterActions = [actionName] } else { Object.entries(config.manifest.full.packages).forEach((packageTuple) => { + packageTuple[0] = packageTuple[0].replace(/__APP_PACKAGE__/g, config.ow.package) + Object.keys(packageTuple[1].actions).forEach((actionName) => { - packageTuple[0] = packageTuple[0].replace(/__APP_PACKAGE__/g, config.ow.package) filterActions.push(packageTuple[0] + '/' + actionName) }) }) } - - try { - const config = this.getAppConfig() + try { await rtLib.printActionLogs(config, this.log, flags.limit, filterActions, flags.strip, flags.tail) } catch (error) { this.error(wrapError(error)) diff --git a/test/commands/app/init.test.js b/test/commands/app/init.test.js index 32c9a8c1..ac69d27e 100644 --- a/test/commands/app/init.test.js +++ b/test/commands/app/init.test.js @@ -14,6 +14,7 @@ const path = require('path') const TheCommand = require('../../../src/commands/app/init') const BaseCommand = require('../../../src/BaseCommand') +const runtimeLib = require('@adobe/aio-lib-runtime') // eslint-disable-line no-unused-vars const importLib = require('../../../src/lib/import') jest.mock('../../../src/lib/import') From a08f72d6b2287f0a36aab5a2ca275787b64648cd Mon Sep 17 00:00:00 2001 From: Himavanth Date: Fri, 16 Oct 2020 12:06:36 +0530 Subject: [PATCH 3/3] aliases and more error handling --- src/commands/app/logs.js | 22 +++++++++++++++++++--- test/commands/app/logs.test.js | 23 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/commands/app/logs.js b/src/commands/app/logs.js index 4a3aebd2..fdb8959d 100644 --- a/src/commands/app/logs.js +++ b/src/commands/app/logs.js @@ -15,11 +15,15 @@ const { flags } = require('@oclif/command') const BaseCommand = require('../../BaseCommand') const { wrapError } = require('../../lib/app-helper') const rtLib = require('@adobe/aio-lib-runtime') +const fs = require('fs-extra') class Logs extends BaseCommand { async run () { const { flags } = this.parse(Logs) const config = this.getAppConfig() + if (!fs.existsSync('manifest.yml')) { + this.error(wrapError(new Error('no manifest.yml'))) + } if (flags.limit < 1) { this.log('--limit should be > 0, using --limit=1') @@ -47,7 +51,7 @@ class Logs extends BaseCommand { } try { - await rtLib.printActionLogs(config, this.log, flags.limit, filterActions, flags.strip, flags.tail) + await rtLib.printActionLogs(config, this.log, flags.limit, filterActions, flags.strip, flags.poll || flags.tail || flags.watch) } catch (error) { this.error(wrapError(error)) } @@ -66,7 +70,6 @@ Logs.flags = { }), action: flags.string({ description: 'Fetch logs for a specific action', - default: '', char: 'a' }), strip: flags.boolean({ @@ -77,7 +80,20 @@ Logs.flags = { tail: flags.boolean({ description: 'Fetch logs continuously', char: 't', - default: false + default: false, + exclusive: ['watch', 'poll'] + }), + watch: flags.boolean({ + description: 'Fetch logs continuously', + default: false, + char: 'w', + exclusive: ['tail', 'poll'] + }), + poll: flags.boolean({ + description: 'Fetch logs continuously', + default: false, + char: 'o', + exclusive: ['watch', 'tail'] }) } diff --git a/test/commands/app/logs.test.js b/test/commands/app/logs.test.js index 26a161d3..a340c6ab 100644 --- a/test/commands/app/logs.test.js +++ b/test/commands/app/logs.test.js @@ -13,8 +13,11 @@ governing permissions and limitations under the License. const TheCommand = require('../../../src/commands/app/logs') const BaseCommand = require('../../../src/BaseCommand') +const mockFS = require('fs-extra') + jest.mock('../../../src/lib/app-helper.js') const helpers = require('../../../src/lib/app-helper.js') + const mockRuntimeLib = require('@adobe/aio-lib-runtime') const printActionLogs = mockRuntimeLib.printActionLogs @@ -60,9 +63,11 @@ describe('run', () => { beforeEach(() => { printActionLogs.mockReset() helpers.wrapError.mockReset() + mockFS.existsSync.mockReset() }) test('no flags, sets limit to 1', async () => { + mockFS.existsSync.mockReturnValue(true) const command = new TheCommand([]) command.appConfig = fakeAppConfig command.error = jest.fn() @@ -74,6 +79,7 @@ describe('run', () => { }) test('--limit < 1, sets limit to 1', async () => { + mockFS.existsSync.mockReturnValue(true) const command = new TheCommand(['--limit', '-1']) command.appConfig = fakeAppConfig command.error = jest.fn() @@ -86,6 +92,7 @@ describe('run', () => { }) test('--limit > 50, sets limit to 50', async () => { + mockFS.existsSync.mockReturnValue(true) const command = new TheCommand(['--limit', '51']) command.appConfig = fakeAppConfig command.error = jest.fn() @@ -98,6 +105,7 @@ describe('run', () => { }) test('--limit 32', async () => { + mockFS.existsSync.mockReturnValue(true) const command = new TheCommand(['--limit', '32']) command.appConfig = fakeAppConfig command.error = jest.fn() @@ -109,6 +117,7 @@ describe('run', () => { }) test('--action without including package name', async () => { + mockFS.existsSync.mockReturnValue(true) const command = new TheCommand(['--action', 'hello']) command.appConfig = fakeAppConfig command.error = jest.fn() @@ -120,6 +129,7 @@ describe('run', () => { }) test('--action including package name', async () => { + mockFS.existsSync.mockReturnValue(true) const command = new TheCommand(['--action', 'pkg1/hello']) command.appConfig = fakeAppConfig command.error = jest.fn() @@ -131,6 +141,7 @@ describe('run', () => { }) test('error while getting logs', async () => { + mockFS.existsSync.mockReturnValue(true) const command = new TheCommand([]) command.appConfig = fakeAppConfig command.error = jest.fn() @@ -142,4 +153,16 @@ describe('run', () => { expect(command.error).toHaveBeenCalledWith('wrapped error') expect(helpers.wrapError).toHaveBeenCalledWith(theerror) }) + + test('error no manifest', async () => { + mockFS.existsSync.mockReturnValue(false) + const command = new TheCommand([]) + command.appConfig = fakeAppConfig + command.error = jest.fn() + command.log = jest.fn() + helpers.wrapError.mockReturnValue('wrapped error') + await command.run() + expect(command.error).toHaveBeenCalledWith('wrapped error') + expect(helpers.wrapError).toHaveBeenCalledWith(new Error('no manifest.yml')) + }) })