UNPKG

ask-cli

Version:

Alexa Skills Kit (ASK) Command Line Interfaces

763 lines (701 loc) 33.9 kB
const { expect } = require('chai'); const sinon = require('sinon'); const fs = require('fs'); const fse = require('fs-extra'); const path = require('path'); const httpClient = require('@src/clients/http-client'); const SmapiClient = require('@src/clients/smapi-client'); const ResourcesConfig = require('@src/model/resources-config'); const Manifest = require('@src/model/manifest'); const SkillInfrastructureController = require('@src/controllers/skill-infrastructure-controller'); const DeployDelegate = require('@src/controllers/skill-infrastructure-controller/deploy-delegate'); const MultiTasksView = require('@src/view/multi-tasks-view'); const jsonView = require('@src/view/json-view'); const AuthorizationController = require('@src/controllers/authorization-controller'); const hashUtils = require('@src/utils/hash-utils'); const CONSTANTS = require('@src/utils/constants'); describe('Controller test - skill infrastructure controller test', () => { const FIXTURE_RESOURCES_CONFIG_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'regular-proj', 'ask-resources.json'); const FIXTURE_MANIFEST_FILE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model', 'manifest.json'); const TEST_PROFILE = 'default'; // test file uses 'default' profile const TEST_WORKSPACE = 'workspace'; const TEST_SKILL_ID = 'skillId'; const TEST_CONFIGURATION = { profile: TEST_PROFILE, doDebug: false }; const TEST_USER_CONFIG = { user: 'config' }; describe('# inspect correctness for constructor', () => { it('| initiate as a SkillInfrastructureController class', () => { const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); expect(skillInfraController).to.be.instanceOf(SkillInfrastructureController); expect(skillInfraController.profile).equal(TEST_PROFILE); expect(skillInfraController.doDebug).equal(false); }); }); describe('# test class method: bootstrapInfrastructures', () => { const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); beforeEach(() => { new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); }); afterEach(() => { ResourcesConfig.dispose(); sinon.restore(); }); it('| skill infrastructures infra type not set, expect error is called back', (done) => { // setup ResourcesConfig.getInstance().setSkillInfraType(TEST_PROFILE, ' '); // call skillInfraController.bootstrapInfrastructures(TEST_WORKSPACE, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal('[Error]: Please set the "type" field for your skill infrastructures.'); done(); }); }); it('| loading deploy delegate error, expect error is called back', (done) => { // setup sinon.stub(DeployDelegate, 'load').callsArgWith(1, 'error'); // call skillInfraController.bootstrapInfrastructures(TEST_WORKSPACE, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal('error'); done(); }); }); it('| loading deploy delegate pass but bootstrap fails, expect error is called back', (done) => { // setup const bootstrapStub = sinon.stub(); const mockDeployDelegate = { bootstrap: bootstrapStub, invoke: () => 'invoke' }; sinon.stub(DeployDelegate, 'load').callsArgWith(1, null, mockDeployDelegate); bootstrapStub.callsArgWith(1, 'error'); // call skillInfraController.bootstrapInfrastructures(TEST_WORKSPACE, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal('error'); done(); }); }); it('| loading deploy delegate and its bootstrap pass, expect config is called correctly in each step', (done) => { // setup const oldUserConfig = ResourcesConfig.getInstance().getSkillInfraUserConfig(TEST_PROFILE); const bootstrapStub = sinon.stub(); const mockDeployDelegate = { bootstrap: bootstrapStub, invoke: () => 'invoke' }; sinon.stub(DeployDelegate, 'load').callsArgWith(1, null, mockDeployDelegate); bootstrapStub.callsArgWith(1, null, { userConfig: TEST_USER_CONFIG }); // call skillInfraController.bootstrapInfrastructures(TEST_WORKSPACE, (err, res) => { // verify expect(bootstrapStub.args[0][0].workspacePath).equal(TEST_WORKSPACE); expect(bootstrapStub.args[0][0].userConfig).equal(oldUserConfig); expect(res).equal(undefined); expect(err).equal(undefined); expect(ResourcesConfig.getInstance().getSkillInfraUserConfig(TEST_PROFILE)).deep.equal(TEST_USER_CONFIG); done(); }); }); }); describe('# test class method: deployInfrastructure', () => { const TEST_DEPLOY_DELEGATE = {}; const TEST_DEPLOY_RESULT = { default: { endpoint: { url: 'TEST_URL' }, lastDeployHash: 'TEST_HASH', deployState: {} } }; const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); beforeEach(() => { new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); }); afterEach(() => { ResourcesConfig.dispose(); sinon.restore(); }); it('| prepare deploy delegate fails, expect error called back', (done) => { // setup sinon.stub(DeployDelegate, 'load').callsArgWith(1, 'error'); // call skillInfraController.deployInfrastructure((err, res) => { // verify expect(res).equal(undefined); expect(err).equal('error'); done(); }); }); it('| deploy infra to all regions fails, expect error called back', (done) => { // setup sinon.stub(DeployDelegate, 'load').callsArgWith(1, null, TEST_DEPLOY_DELEGATE); sinon.stub(SkillInfrastructureController.prototype, 'deployInfraToAllRegions').callsArgWith(1, 'error'); // call skillInfraController.deployInfrastructure((err, res) => { // verify expect(res).equal(undefined); expect(err).equal('error'); done(); }); }); it('| deploy to all regions passes but update skill manifest after deploy fails, expect error called back', (done) => { // setup sinon.stub(DeployDelegate, 'load').callsArgWith(1, null, TEST_DEPLOY_DELEGATE); sinon.stub(SkillInfrastructureController.prototype, 'deployInfraToAllRegions').callsArgWith(1, null, TEST_DEPLOY_RESULT); sinon.stub(SkillInfrastructureController.prototype, 'updateSkillManifestWithDeployResult').callsArgWith(1, 'error'); sinon.stub(fs, 'writeFileSync'); // call skillInfraController.deployInfrastructure((err, res) => { // verify expect(res).equal(undefined); expect(err).equal('error'); done(); }); }); it('| update resources config and update skill manifest after deploy pass, expect no error called back', (done) => { // setup sinon.stub(DeployDelegate, 'load').callsArgWith(1, null, TEST_DEPLOY_DELEGATE); sinon.stub(SkillInfrastructureController.prototype, 'deployInfraToAllRegions').callsArgWith(1, null, TEST_DEPLOY_RESULT); sinon.stub(SkillInfrastructureController.prototype, 'updateSkillManifestWithDeployResult').callsArgWith(1, null); sinon.stub(fs, 'writeFileSync'); // call skillInfraController.deployInfrastructure((err, res) => { // verify expect(res).equal(undefined); expect(err).equal(undefined); done(); }); }); }); describe('# test class method: deployInfraToAllRegions', () => { const TEST_DD = {}; let ddStub; const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); beforeEach(() => { new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); new Manifest(FIXTURE_MANIFEST_FILE_PATH); ddStub = sinon.stub(); TEST_DD.validateDeployDelegateResponse = ddStub; }); afterEach(() => { ResourcesConfig.dispose(); Manifest.dispose(); sinon.restore(); }); it('| skill name failed to parse, expect error called back', (done) => { // setup Manifest.getInstance().setSkillName('中文 '); sinon.stub(path, 'basename').returns('中文 '); // call skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal('[Error]: Failed to parse the skill name used to decide the CloudFormation stack name. ' + 'Please make sure your skill name or skill project folder basename contains alphanumeric characters.'); done(); }); }); it('| code does not have any region, expect error called back', (done) => { // setup sinon.stub(ResourcesConfig.prototype, 'getCodeRegions').returns([]); // call skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal('[Warn]: Skip the infrastructure deployment, as the "code" field has not been set in the resources config file.'); done(); }); }); it('| start multi-tasks fails, expect error called back', (done) => { // setup sinon.stub(MultiTasksView.prototype, 'loadTask'); sinon.stub(MultiTasksView.prototype, 'start').callsArgWith(0, { error: 'error' }); // call skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal('error'); expect(MultiTasksView.prototype.loadTask.callCount).equal(3); expect(MultiTasksView.prototype.loadTask.args[0][1]).equal('Deploy Alexa skill infrastructure for region "default"'); expect(MultiTasksView.prototype.loadTask.args[0][2]).equal('default'); expect(MultiTasksView.prototype.loadTask.args[1][1]).equal('Deploy Alexa skill infrastructure for region "NA"'); expect(MultiTasksView.prototype.loadTask.args[1][2]).equal('NA'); expect(MultiTasksView.prototype.loadTask.args[2][1]).equal('Deploy Alexa skill infrastructure for region "EU"'); expect(MultiTasksView.prototype.loadTask.args[2][2]).equal('EU'); done(); }); }); it('| start multi-tasks fails partially, expect error called back and state updated', (done) => { // setup sinon.stub(MultiTasksView.prototype, 'loadTask'); sinon.stub(MultiTasksView.prototype, 'start').callsArgWith(0, { error: 'error', partialResult: { NA: 'partial' } }); sinon.stub(SkillInfrastructureController.prototype, '_updateResourcesConfig'); // call skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal('error'); expect(SkillInfrastructureController.prototype._updateResourcesConfig.args[0][0]).deep.equal({ NA: 'partial' }); done(); }); }); it('| deploy delegate validate response fails, expect error called back', (done) => { // setup sinon.stub(MultiTasksView.prototype, 'loadTask'); sinon.stub(MultiTasksView.prototype, 'start').callsArgWith(0); ddStub.throws(new Error('error')); // call skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { // verify expect(res).equal(undefined); expect(err.message).equal('error'); done(); }); }); it('| deploy infra to all regions pass, expect no error called back', (done) => { // setup sinon.stub(SkillInfrastructureController.prototype, '_deployInfraByRegion'); sinon.stub(SkillInfrastructureController.prototype, '_updateResourcesConfig'); sinon.stub(MultiTasksView.prototype, 'loadTask').callsArgWith(0); sinon.stub(MultiTasksView.prototype, 'start').callsArgWith(0, null, {}); // call skillInfraController.deployInfraToAllRegions(TEST_DD, (err, res) => { // verify expect(res).deep.equal({}); expect(err).equal(null); expect(MultiTasksView.prototype.loadTask.callCount).equal(3); expect(MultiTasksView.prototype.loadTask.args[0][1]).equal('Deploy Alexa skill infrastructure for region "default"'); expect(MultiTasksView.prototype.loadTask.args[0][2]).equal('default'); expect(MultiTasksView.prototype.loadTask.args[1][1]).equal('Deploy Alexa skill infrastructure for region "NA"'); expect(MultiTasksView.prototype.loadTask.args[1][2]).equal('NA'); expect(MultiTasksView.prototype.loadTask.args[2][1]).equal('Deploy Alexa skill infrastructure for region "EU"'); expect(MultiTasksView.prototype.loadTask.args[2][2]).equal('EU'); done(); }); }); }); describe('# test class method: updateSkillManifestWithDeployResult', () => { const TEST_DEPLOY_RESULT = { default: { endpoint: { url: 'TEST_URL1' } }, EU: { endpoint: { url: 'TEST_URL2' } } }; const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); beforeEach(() => { new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); new Manifest(FIXTURE_MANIFEST_FILE_PATH); sinon.stub(fs, 'writeFileSync'); }); afterEach(() => { ResourcesConfig.dispose(); Manifest.dispose(); sinon.restore(); }); it('| manifest update correctly but hash fails, expect error called back', (done) => { // setup sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(hashUtils, 'getHash').callsArgWith(1, 'hash error'); // call skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal('hash error'); expect(hashUtils.getHash.args[0][0]).equal(ResourcesConfig.getInstance().getSkillMetaSrc(TEST_PROFILE)); expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'default').url).equal('TEST_URL1'); expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'EU').url).equal('TEST_URL2'); done(); }); }); it('| manifest update correctly but hash is same, expect called back with nothing', (done) => { // setup ResourcesConfig.getInstance().setSkillMetaLastDeployHash(TEST_PROFILE, 'TEST_HASH'); sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, 'TEST_HASH'); // call skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal(undefined); expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'default').url).equal('TEST_URL1'); expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'EU').url).equal('TEST_URL2'); done(); }); }); it('| manifest update correctly but skill manifest update fails, expect update error called back', (done) => { // setup sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, 'TEST_HASH'); sinon.stub(SkillInfrastructureController.prototype, '_ensureSkillManifestGotUpdated').callsArgWith(0, 'update error'); // call skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal('update error'); expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'default').url).equal('TEST_URL1'); expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'EU').url).equal('TEST_URL2'); done(); }); }); it('| manifest update correctly, expect success message and new hash set', (done) => { // setup sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, 'TEST_HASH'); sinon.stub(SkillInfrastructureController.prototype, '_ensureSkillManifestGotUpdated').callsArgWith(0); // call skillInfraController.updateSkillManifestWithDeployResult(TEST_DEPLOY_RESULT, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal(undefined); expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'default').url).equal('TEST_URL1'); expect(Manifest.getInstance().getApisEndpointByDomainRegion('custom', 'EU').url).equal('TEST_URL2'); expect(ResourcesConfig.getInstance().getSkillMetaLastDeployHash(TEST_PROFILE)).equal('TEST_HASH'); done(); }); }); }); describe('# test class method: _deployInfraByRegion', () => { let ddStub; const TEST_REPORTER = {}; const TEST_DD = {}; const TEST_REGION = 'default'; const TEST_SKILL_NAME = 'skillName'; const TEST_HASH = 'hash'; const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); beforeEach(() => { new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); sinon.stub(path, 'resolve').returns('base'); sinon.stub(fse, 'statSync').returns({ isDirectory: () => true }); ddStub = sinon.stub(); TEST_DD.invoke = ddStub; }); afterEach(() => { ResourcesConfig.dispose(); sinon.restore(); }); it('| get hash fails, expect error called back', (done) => { // setup sinon.stub(hashUtils, 'getHash').callsArgWith(1, 'hash error'); // call skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal('hash error'); done(); }); }); it('| deploy delegate invoke fails, expect error called back', (done) => { // setup sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_HASH); ResourcesConfig.getInstance().setCodeLastDeployHashByRegion(TEST_PROFILE, TEST_REGION, TEST_HASH); ddStub.callsArgWith(2, 'invoke error'); // call skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, (err, res) => { // verify expect(res).equal(undefined); expect(err).equal('invoke error'); expect(ddStub.args[0][1].code.isCodeModified).equal(false); done(); }); }); it('| deploy delegate invoke passes with isCodeDeployed true, expect invoke result called back with currentHash', (done) => { // setup sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_HASH); ddStub.callsArgWith(2, null, { isCodeDeployed: true, isAllStepSuccess: true }); // call skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, (err, res) => { // verify expect(res).deep.equal({ isCodeDeployed: true, isAllStepSuccess: true, lastDeployHash: TEST_HASH }); expect(err).equal(null); done(); }); }); it('| deploy delegate invoke passes, expect invoke result called back', (done) => { // setup sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_HASH); ddStub.callsArgWith(2, null, { isCodeDeployed: false, isAllStepSuccess: true, resultMessage: 'success', deployState: {} }); // call skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, (err, res) => { // verify expect(res).deep.equal({ isCodeDeployed: false, isAllStepSuccess: true, resultMessage: 'success', deployState: {} }); expect(err).equal(null); done(); }); }); it('| deploy delegate invoke partial succeed with reasons called back, expect invoke result called back along with the message', (done) => { // setup sinon.stub(hashUtils, 'getHash').callsArgWith(1, null, TEST_HASH); ddStub.callsArgWith(2, null, { isCodeDeployed: true, isAllStepSuccess: false, resultMessage: 'partial fail', deployState: {} }); // call skillInfraController._deployInfraByRegion(TEST_REPORTER, TEST_DD, TEST_REGION, TEST_SKILL_NAME, (err, res) => { // verify expect(res).equal(undefined); expect(err).deep.equal({ isCodeDeployed: true, isAllStepSuccess: false, lastDeployHash: TEST_HASH, resultMessage: 'partial fail', deployState: {} }); done(); }); }); }); describe('# test class method: _updateResourcesConfig', () => { const TEST_DEPLOY_RESULT = { default: { endpoint: { url: 'TEST_URL' }, lastDeployHash: 'TEST_HASH', deployState: {} } }; const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); beforeEach(() => { new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); sinon.stub(fse, 'writeFileSync'); }); afterEach(() => { ResourcesConfig.dispose(); sinon.restore(); }); it('| update resources config correctly', () => { // setup sinon.stub(hashUtils, 'getHash').callsArgWith(1, 'hash error'); // call skillInfraController._updateResourcesConfig(TEST_DEPLOY_RESULT); // verify expect(ResourcesConfig.getInstance().getCodeLastDeployHashByRegion(TEST_PROFILE, 'default')).equal('TEST_HASH'); expect(ResourcesConfig.getInstance().getSkillInfraDeployState(TEST_PROFILE)).deep.equal({ default: {} }); expect(fse.writeFileSync.callCount).equal(2); }); }); describe('# test class method: _ensureSkillManifestGotUpdated', () => { const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); beforeEach(() => { new ResourcesConfig(FIXTURE_RESOURCES_CONFIG_FILE_PATH); new Manifest(FIXTURE_MANIFEST_FILE_PATH); sinon.stub(fs, 'writeFileSync'); }); afterEach(() => { ResourcesConfig.dispose(); Manifest.dispose(); sinon.restore(); }); it('| SMAPI update manifest connection fails, expect error called back', (done) => { // setup sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(httpClient, 'request').callsArgWith(3, 'error'); // call skillInfraController._ensureSkillManifestGotUpdated((err, res) => { // verify expect(res).equal(undefined); expect(err).equal('error'); done(); }); }); it('| SMAPI update manifest fails with >= 300 error code, expect SMAPI error called back', (done) => { // setup const TEST_SMAPI_RESPONSE = { statusCode: 401, body: { message: 'unauthrized' } }; sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_SMAPI_RESPONSE); // call skillInfraController._ensureSkillManifestGotUpdated((err, res) => { // verify expect(res).equal(undefined); expect(err).equal(jsonView.toString(TEST_SMAPI_RESPONSE.body)); done(); }); }); it('| SMAPI update manifest passes but polling fails, expect polling error called back', (done) => { // setup const TEST_SMAPI_RESPONSE = { statusCode: 202 }; sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_SMAPI_RESPONSE); sinon.stub(SkillInfrastructureController.prototype, '_pollSkillStatus').callsArgWith(2, 'poll error'); // call skillInfraController._ensureSkillManifestGotUpdated((err, res) => { // verify expect(res).equal(undefined); expect(err).equal('poll error'); done(); }); }); it('| SMAPI update manifest passes but polling cause SMAPI to fail, expect SMAPI error called back', (done) => { // setup const TEST_SMAPI_RESPONSE = { statusCode: 202 }; const TEST_POLL_RESPONSE = { body: 'invalid' }; sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_SMAPI_RESPONSE); sinon.stub(SkillInfrastructureController.prototype, '_pollSkillStatus').callsArgWith(2, null, TEST_POLL_RESPONSE); // call skillInfraController._ensureSkillManifestGotUpdated((err, res) => { // verify expect(res).equal(undefined); expect(err.startsWith('[Error]: Failed to extract the manifest result from SMAPI\'s response.\n')).equal(true); done(); }); }); it('| SMAPI update manifest passes but polling result is not SUCCEEDED, expect SMAPI response errored back', (done) => { // setup const TEST_SMAPI_RESPONSE = { statusCode: 202 }; const TEST_POLL_RESPONSE = { body: { manifest: { lastUpdateRequest: { status: 'TEST_STATUS' } } } }; sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_SMAPI_RESPONSE); sinon.stub(SkillInfrastructureController.prototype, '_pollSkillStatus').callsArgWith(2, null, TEST_POLL_RESPONSE); // call skillInfraController._ensureSkillManifestGotUpdated((err, res) => { // verify expect(res).equal(undefined); expect(err).equal('[Error]: Updating skill manifest but received non-success message from SMAPI: TEST_STATUS'); done(); }); }); it('| SMAPI update manifest passes and update succeeds, expect call back with no error', (done) => { // setup const TEST_SMAPI_RESPONSE = { statusCode: 202 }; const TEST_POLL_RESPONSE = { body: { manifest: { lastUpdateRequest: { status: CONSTANTS.SKILL.SKILL_STATUS.SUCCEEDED } } } }; sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_SMAPI_RESPONSE); sinon.stub(SkillInfrastructureController.prototype, '_pollSkillStatus').callsArgWith(2, null, TEST_POLL_RESPONSE); // call skillInfraController._ensureSkillManifestGotUpdated((err, res) => { // verify expect(res).equal(undefined); expect(err).equal(undefined); done(); }); }); }); describe('# test class method: _pollSkillStatus', () => { const testSmapiClient = new SmapiClient(TEST_CONFIGURATION); const skillInfraController = new SkillInfrastructureController(TEST_CONFIGURATION); afterEach(() => { sinon.restore(); }); it('| poll skill status but error happens when polling status', (done) => { // setup sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(httpClient, 'request').callsArgWith(3, 'error'); // call skillInfraController._pollSkillStatus(testSmapiClient, TEST_SKILL_ID, (err, res) => { // verify expect(res).equal(null); expect(err).equal('error'); done(); }); }); it('| poll skill status but SMAPI returns failure', (done) => { // setup const TEST_SMAPI_RESPONSE = { statusCode: 401, body: { message: 'unauthrized' } }; sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_SMAPI_RESPONSE); // call skillInfraController._pollSkillStatus(testSmapiClient, TEST_SKILL_ID, (err, res) => { // verify expect(res).equal(null); expect(err).equal(jsonView.toString(TEST_SMAPI_RESPONSE.body)); done(); }); }); it('| poll skill status successfully complete', (done) => { // setup const TEST_SMAPI_RESPONSE = { statusCode: 202, body: { manifest: { lastUpdateRequest: { status: 'TEST' } } } }; sinon.stub(AuthorizationController.prototype, 'tokenRefreshAndRead').callsArgWith(1); sinon.stub(httpClient, 'request').callsArgWith(3, null, TEST_SMAPI_RESPONSE); // call skillInfraController._pollSkillStatus(testSmapiClient, TEST_SKILL_ID, (err, res) => { // verify expect(err).equal(null); expect(res.statusCode).equal(202); expect(res.body).deep.equal(TEST_SMAPI_RESPONSE.body); done(); }); }); }); });