Skip to content

Commit

Permalink
feat: add locale and region for AHS (#287)
Browse files Browse the repository at this point in the history
  • Loading branch information
kakhaUrigashvili authored Aug 26, 2020
1 parent 73a1646 commit 6c8991c
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 38 deletions.
15 changes: 9 additions & 6 deletions lib/clients/smapi-client/resources/alexa-hosted.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,21 @@ const NULL_PAYLOAD = null;
module.exports = (smapiHandle) => {
/**
* To submit a skill creation request for a specified vendorId
* @param {Object} manifest The JSON representation of the skill, and provides Alexa with all of the metadata required
* @param {Object} hostedSkillPayload The JSON representation of the skill, and provides Alexa with all of the metadata required
* @param {callback} callback { error, response }
*/
function createHostedSkill(manifest, callback) {
function createHostedSkill(hostedSkillPayload, callback) {
const url = 'skills/';
const runtime = CONSTANTS.HOSTED_SKILL.DEFAULT_RUNTIME[manifest.runtime];
const { vendorId, manifest, region } = hostedSkillPayload;
const runtime = CONSTANTS.HOSTED_SKILL.DEFAULT_RUNTIME[hostedSkillPayload.runtime];

const payload = {
vendorId: manifest.vendorId,
manifest: manifest.manifest,
vendorId,
manifest,
hosting: {
alexaHosted: {
runtime
runtime,
region
}
}
};
Expand Down
20 changes: 11 additions & 9 deletions lib/commands/new/hosted-skill-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,12 @@ function createHostedSkill(hostedSkillController, userInput, vendorId, callback)
if (fs.existsSync(projectPath)) {
return callback(`${projectPath} directory already exists.`);
}
const manifest = _updateManifest(userInput.skillName);
const manifest = _updateManifest(userInput);
const input = {
vendorId,
manifest,
runtime: userInput.language
runtime: userInput.language,
region: userInput.region
};

const listenSpinner = new SpinnerView();
Expand Down Expand Up @@ -108,16 +109,17 @@ function createHostedSkill(hostedSkillController, userInput, vendorId, callback)
}

/**
* To update hosted skill manifest template with customer input skill name
* To update hosted skill manifest template with user input
* and return the manifest object.
* @param {string} skillName The skill name
* @param {Object} userInput The skill name
*/
function _updateManifest(skillName) {
function _updateManifest(userInput) {
const { skillName, locale } = userInput;
const manifest = CONSTANTS.HOSTED_SKILL.MANIFEST;
const { locales } = manifest.publishingInformation;
Object.keys(locales).forEach((locale) => {
manifest.publishingInformation.locales[locale].name = skillName;
});

manifest.publishingInformation.locales[locale] = {};
manifest.publishingInformation.locales[locale].name = skillName;

return manifest;
}

Expand Down
29 changes: 29 additions & 0 deletions lib/commands/new/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const SKIP_DEPLOY_DELEGATE_SELECTION = 'self-hosted and manage your own hosting'

module.exports = {
getSkillName,
getSkillLocale,
getSkillDefaultRegion,
getProjectFolderName,
selectSkillCodeLanguage,
getTargetTemplateName,
Expand Down Expand Up @@ -39,6 +41,33 @@ function getSkillName(url, callback) {
});
}

function getSkillLocale(callback) {
inquirer.prompt([{
message: 'Choose the default locale for your skill: ',
type: 'list',
choices: CONSTANTS.HOSTED_SKILL.LOCALES,
name: 'locale',
pageSize: 5
}]).then((answer) => {
callback(null, answer.locale);
}).catch((error) => {
callback(error);
});
}

function getSkillDefaultRegion(callback) {
inquirer.prompt([{
message: 'Choose the default region for your skill: ',
type: 'list',
choices: Object.keys(CONSTANTS.HOSTED_SKILL.REGIONS),
name: 'region'
}]).then((answer) => {
callback(null, CONSTANTS.HOSTED_SKILL.REGIONS[answer.region]);
}).catch((error) => {
callback(error);
});
}

function getProjectFolderName(defaultName, callback) {
inquirer.prompt([{
message: 'Please type in your folder name for the skill project (alphanumeric): ',
Expand Down
61 changes: 44 additions & 17 deletions lib/commands/new/wizard-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,39 @@ function collectUserCreationProjectInfo(cmd, callback) {
return callback(deploymentErr);
}
userInput.deploymentType = deploymentType;
_getTemplateInfo(cmd, userInput, (templateErr, templateInfo) => {
if (templateErr) {
return callback(templateErr);
}
if (!templateInfo) {
return callback();

_getSkillLocale(userInput, (localeErr, locale) => {
if (localeErr) {
return callback(localeErr);
}
userInput.templateInfo = templateInfo;
ui.getSkillName(userInput.templateInfo.templateUrl, (getSkillNameErr, skillName) => {
if (getSkillNameErr) {
return callback(getSkillNameErr);
userInput.locale = locale;
_getSkillDefaultRegion(userInput, (regionErr, region) => {
if (regionErr) {
return callback(regionErr);
}
userInput.skillName = skillName;
const suggestedProjectName = stringUtils.filterNonAlphanumeric(skillName);
ui.getProjectFolderName(suggestedProjectName, (getFolderNameErr, folderName) => {
if (getFolderNameErr) {
return callback(getFolderNameErr);
userInput.region = region;
_getTemplateInfo(cmd, userInput, (templateErr, templateInfo) => {
if (templateErr) {
return callback(templateErr);
}
userInput.projectFolderName = folderName;
callback(null, userInput);
if (!templateInfo) {
return callback();
}
userInput.templateInfo = templateInfo;
ui.getSkillName(userInput.templateInfo.templateUrl, (getSkillNameErr, skillName) => {
if (getSkillNameErr) {
return callback(getSkillNameErr);
}
userInput.skillName = skillName;
const suggestedProjectName = stringUtils.filterNonAlphanumeric(skillName);
ui.getProjectFolderName(suggestedProjectName, (getFolderNameErr, folderName) => {
if (getFolderNameErr) {
return callback(getFolderNameErr);
}
userInput.projectFolderName = folderName;
callback(null, userInput);
});
});
});
});
});
Expand All @@ -68,6 +81,20 @@ function _getSkillCodeLanguage(cmd, callback) {
ui.selectSkillCodeLanguage((err, res) => callback(err || null, res));
}

function _getSkillLocale(userInput, callback) {
if (userInput.deploymentType !== CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME) {
return callback();
}
ui.getSkillLocale((err, res) => callback(err || null, res));
}

function _getSkillDefaultRegion(userInput, callback) {
if (userInput.deploymentType !== CONSTANTS.DEPLOYER_TYPE.HOSTED.NAME) {
return callback();
}
ui.getSkillDefaultRegion((err, res) => callback(err || null, res));
}

/**
* Get template info for non-hosted skill
* @param {Object} cmd command object
Expand Down
6 changes: 3 additions & 3 deletions lib/controllers/hosted-skill-controller/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ module.exports = class HostedSkillController {

/**
* To create an Alexa hosted skill
* @param {JSON} manifest the JSON representation of the skill, and provides Alexa with all of the metadata required
* @param {JSON} hostedSkillPayload the JSON representation of the skill, and provides Alexa with all of the metadata required
* @param {callback} callback { error, response }
*/
createSkill(manifest, callback) {
this.smapiClient.skill.alexaHosted.createHostedSkill(manifest, (createErr, createRes) => {
createSkill(hostedSkillPayload, callback) {
this.smapiClient.skill.alexaHosted.createHostedSkill(hostedSkillPayload, (createErr, createRes) => {
if (createErr) {
return callback(createErr);
}
Expand Down
10 changes: 7 additions & 3 deletions lib/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ module.exports.DEPLOY_TARGET = {

module.exports.HOSTED_SKILL = {
DEFAULT_SKILL_NAME: 'Hello World Skill',
LOCALES: ['de-DE', 'en-AU', 'en-CA', 'en-GB', 'en-IN', 'en-US', 'es-ES', 'es-MX',
'es-US', 'fr-CA', 'fr-FR', 'hi-IN', 'it-IT', 'ja-JP', 'pt-BR'],
REGIONS: {
'us-east-1': 'US_EAST_1',
'us-west-2': 'US_WEST_2',
'eu-west-1': 'EU_WEST_1'
},
DEFAULT_RUNTIME: {
NodeJS: 'NODE_10_X',
Python: 'PYTHON_3_7',
Expand All @@ -48,9 +55,6 @@ module.exports.HOSTED_SKILL = {
MANIFEST: {
publishingInformation: {
locales: {
'en-US': {
name: ''
}
}
},
apis: {
Expand Down
2 changes: 2 additions & 0 deletions test/functional/commands/high-level-commands-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ parallel('high level commands test', () => {
let inputs = [
{ match: '? Choose the programming language' },
{ match: '? Choose a method to host your skill' },
{ match: '? Choose the default locale for your skill' },
{ match: '? Choose the default region for your skill' },
{ match: '? Please type in your skill name' },
{ match: '? Please type in your folder name', input: folderName }
];
Expand Down
3 changes: 3 additions & 0 deletions test/unit/clients/smapi-client-test/resources/alexa-hosted.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ module.exports = (smapiClient) => {
const TEST_ACCESS_TOKEN = 'access_token';
const TEST_RUNTIME_FIELD = 'NodeJS';
const TEST_RUNTIME_VALUE = 'NODE_10_X';
const TEST_REGION_VALUE = 'US_EAST_1';
const TEST_MANIFEST = {
runtime: TEST_RUNTIME_FIELD,
vendorId: TEST_VENDOR_ID,
region: TEST_REGION_VALUE,
manifest: {}
};
let httpClientStub;
Expand All @@ -45,6 +47,7 @@ module.exports = (smapiClient) => {
manifest: {},
hosting: {
alexaHosted: {
region: TEST_REGION_VALUE,
runtime: TEST_RUNTIME_VALUE
}
}
Expand Down
69 changes: 69 additions & 0 deletions test/unit/commands/new/ui-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ function validateInquirerConfig(stub, expectedConfig) {

describe('Commands new - UI test', () => {
const TEST_SKILL_NAME = 'skillName';
const TEST_LOCALE = 'en-US';
const TEST_REPO_NAME = 'repo';
const TEST_FOLDER_NAME = 'folderName';
const TEST_URL = `https://${TEST_REPO_NAME}.git?data=1`;
Expand Down Expand Up @@ -144,6 +145,74 @@ describe('Commands new - UI test', () => {
});
});

describe('# validate ui.getSkillLocale', () => {
beforeEach(() => {
sinon.stub(inquirer, 'prompt');
});

afterEach(() => {
sinon.restore();
});

it('| getSkillLocale is set by user and inquirer throws exception', (done) => {
// setup
inquirer.prompt.rejects(new Error(TEST_ERROR));
// call
ui.getSkillLocale((err, response) => {
// verify
expect(err.message).equal(TEST_ERROR);
expect(response).equal(undefined);
done();
});
});

it('| getSkillLocale is set by user and return correctly', (done) => {
// setup
inquirer.prompt.resolves({ locale: TEST_LOCALE });
// call
ui.getSkillLocale((err, response) => {
// verify
expect(err).equal(null);
expect(response).equal(TEST_LOCALE);
done();
});
});
});

describe('# validate ui.getSkillDefaultRegion', () => {
beforeEach(() => {
sinon.stub(inquirer, 'prompt');
});

afterEach(() => {
sinon.restore();
});

it('| getSkillDefaultRegion is set by user and inquirer throws exception', (done) => {
// setup
inquirer.prompt.rejects(new Error(TEST_ERROR));
// call
ui.getSkillDefaultRegion((err, response) => {
// verify
expect(err.message).equal(TEST_ERROR);
expect(response).equal(undefined);
done();
});
});

it('| getSkillDefaultRegion is set by user and return correctly', (done) => {
// setup
inquirer.prompt.resolves({ region: 'us-east-1' });
// call
ui.getSkillDefaultRegion((err, response) => {
// verify
expect(err).equal(null);
expect(response).equal('US_EAST_1');
done();
});
});
});

describe('# validate ui.getProjectFolderName', () => {
beforeEach(() => {
sinon.stub(inquirer, 'prompt');
Expand Down
30 changes: 30 additions & 0 deletions test/unit/commands/new/wizard-helper-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ describe('Commands new test - wizard helper test', () => {
sinon.stub(ui, 'getTargetTemplateName');
sinon.stub(ui, 'getSkillName');
sinon.stub(ui, 'getProjectFolderName');
sinon.stub(ui, 'getSkillDefaultRegion');
sinon.stub(ui, 'getSkillLocale');
ui.getSkillLocale.yields(null, 'en-US');
ui.getSkillDefaultRegion.yields(0, null, 'US_EAST_1');
});

afterEach(() => {
Expand Down Expand Up @@ -85,6 +89,32 @@ describe('Commands new test - wizard helper test', () => {
});
});

it('| user input getSkillLocale fails, expect throw error', (done) => {
// setup
ui.selectSkillCodeLanguage.yields(null, TEST_LANGUAGE_RESPONSE);
ui.getDeploymentType.yields(null, TEST_HOSTED_DEPLOYMENT);
ui.getSkillLocale.yields(TEST_ERROR);
// call
wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => {
// verify
expect(err).equal(TEST_ERROR);
done();
});
});

it('| user input getSkillDefaultRegion fails, expect throw error', (done) => {
// setup
ui.selectSkillCodeLanguage.yields(null, TEST_LANGUAGE_RESPONSE);
ui.getDeploymentType.yields(null, TEST_HOSTED_DEPLOYMENT);
ui.getSkillDefaultRegion.yields(TEST_ERROR);
// call
wizardHelper.collectUserCreationProjectInfo(TEST_OPTIONS, (err) => {
// verify
expect(err).equal(TEST_ERROR);
done();
});
});

it('| Hosted skills do not support Java, expect throw error', (done) => {
// setup
const TEST_HOSTED_ERROR = 'Alexa hosted skills don\'t support Java currently.';
Expand Down

0 comments on commit 6c8991c

Please sign in to comment.