[Lubuild] fix multiple bugs: case sensitive issue, default version issue and exception not throw out issue (#576)
* fix case issue of utterances and patterns * remove lower function for entities * adjust test cases * use a better solution to compare utterances * add tests to verify the fixes * move new added tests to luis package from lu package * add test cases for luConfig parameter in lubuild CLI * fix error not throw out bug * resolve comments of CLIError * remove uncessary semicolon * Updates and fixes * Updates * updating tests. * Updates for PR feedback, fix settings out path * updates * fix build errors * fix command parameter issue in test cases * fix tslint errors * remove lubuild.js which is not necessary * fixing bad merge * fix tslint and expose more in index.js and composerindex.js * remove lubuild module in index.js Co-authored-by: Emilio Munoz <munoz_emilio@hotmail.com> Co-authored-by: Vishwac Sena Kannan <vishwack@hotmail.com>
This commit is contained in:
Родитель
6dd1d873a9
Коммит
49f1871797
|
@ -70,6 +70,7 @@ dependencies:
|
|||
source-map-support: 0.5.16
|
||||
testdouble: 3.12.5
|
||||
ts-md5: 1.2.7
|
||||
username: 4.1.0
|
||||
uuid: 3.3.3
|
||||
window-size: 1.1.1
|
||||
xml2js: 0.4.23
|
||||
|
@ -2192,6 +2193,20 @@ packages:
|
|||
node: '>=4'
|
||||
resolution:
|
||||
integrity: sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==
|
||||
/execa/1.0.0:
|
||||
dependencies:
|
||||
cross-spawn: 6.0.5
|
||||
get-stream: 4.1.0
|
||||
is-stream: 1.1.0
|
||||
npm-run-path: 2.0.2
|
||||
p-finally: 1.0.0
|
||||
signal-exit: 3.0.2
|
||||
strip-eof: 1.0.0
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=6'
|
||||
resolution:
|
||||
integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
|
||||
/expand-brackets/2.1.4:
|
||||
dependencies:
|
||||
debug: 2.6.9
|
||||
|
@ -2569,6 +2584,14 @@ packages:
|
|||
node: '>=4'
|
||||
resolution:
|
||||
integrity: sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
|
||||
/get-stream/4.1.0:
|
||||
dependencies:
|
||||
pump: 3.0.0
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=6'
|
||||
resolution:
|
||||
integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
|
||||
/get-stream/5.1.0:
|
||||
dependencies:
|
||||
pump: 3.0.0
|
||||
|
@ -3729,6 +3752,14 @@ packages:
|
|||
dev: false
|
||||
resolution:
|
||||
integrity: sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==
|
||||
/map-age-cleaner/0.1.3:
|
||||
dependencies:
|
||||
p-defer: 1.0.0
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=6'
|
||||
resolution:
|
||||
integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
|
||||
/map-cache/0.2.2:
|
||||
dev: false
|
||||
engines:
|
||||
|
@ -3751,6 +3782,16 @@ packages:
|
|||
dev: false
|
||||
resolution:
|
||||
integrity: sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=
|
||||
/mem/4.3.0:
|
||||
dependencies:
|
||||
map-age-cleaner: 0.1.3
|
||||
mimic-fn: 2.1.0
|
||||
p-is-promise: 2.1.0
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=6'
|
||||
resolution:
|
||||
integrity: sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
|
||||
/merge-descriptors/1.0.1:
|
||||
dev: false
|
||||
resolution:
|
||||
|
@ -3816,6 +3857,12 @@ packages:
|
|||
node: '>=4'
|
||||
resolution:
|
||||
integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
|
||||
/mimic-fn/2.1.0:
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=6'
|
||||
resolution:
|
||||
integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
/mimic-response/1.0.1:
|
||||
dev: false
|
||||
engines:
|
||||
|
@ -4228,6 +4275,12 @@ packages:
|
|||
node: '>=4'
|
||||
resolution:
|
||||
integrity: sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==
|
||||
/p-defer/1.0.0:
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=4'
|
||||
resolution:
|
||||
integrity: sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
|
||||
/p-finally/1.0.0:
|
||||
dev: false
|
||||
engines:
|
||||
|
@ -4240,6 +4293,12 @@ packages:
|
|||
node: '>=4'
|
||||
resolution:
|
||||
integrity: sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=
|
||||
/p-is-promise/2.1.0:
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=6'
|
||||
resolution:
|
||||
integrity: sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
|
||||
/p-limit/2.2.2:
|
||||
dependencies:
|
||||
p-try: 2.2.0
|
||||
|
@ -5764,6 +5823,15 @@ packages:
|
|||
node: '>=0.10.0'
|
||||
resolution:
|
||||
integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
|
||||
/username/4.1.0:
|
||||
dependencies:
|
||||
execa: 1.0.0
|
||||
mem: 4.3.0
|
||||
dev: false
|
||||
engines:
|
||||
node: '>=6'
|
||||
resolution:
|
||||
integrity: sha512-sKh1KCsMfv8jPIC9VdeQhrNAgkl842jS/M74HQv7Byr0AMAwKZt8mLWX9DmtMeD8nQA3eKa10f5LbqlSVmokMg==
|
||||
/util-deprecate/1.0.2:
|
||||
dev: false
|
||||
resolution:
|
||||
|
@ -6273,7 +6341,7 @@ packages:
|
|||
dev: false
|
||||
name: '@rush-temp/bf-lu'
|
||||
resolution:
|
||||
integrity: sha512-g5LXnFL9CB6a/KTzOv3maI9SP0mYK42CE+f9z3ozycf7sQzXsg+pkS9sx3UxcbX7/TspDTly+KQbNSELmx5HGA==
|
||||
integrity: sha512-7SyXpwe1mc1yOJjI8p5+f/IeHGFoyAcclZKa5Ziz7yQlxb/OHPyma6c0YCV685uzcI3PXeBP27K3RtqxxTNQPQ==
|
||||
tarball: 'file:projects/bf-lu.tgz'
|
||||
version: 0.0.0
|
||||
'file:projects/bf-luis-cli.tgz':
|
||||
|
@ -6310,11 +6378,12 @@ packages:
|
|||
tslib: 1.10.0
|
||||
tslint: 5.20.1_typescript@3.7.4
|
||||
typescript: 3.7.4
|
||||
username: 4.1.0
|
||||
uuid: 3.3.3
|
||||
dev: false
|
||||
name: '@rush-temp/bf-luis-cli'
|
||||
resolution:
|
||||
integrity: sha512-DDMDOkSq7aCvKWx8lg4izYltihcctg06xLi2eQ6qC7pIUg5i1ZiQI192RKFHAGvrIFf2ZKVhE0e82c+OYivS4w==
|
||||
integrity: sha512-0E667Qi/DQ3XDAvFPkzf+jij+IQqc4ELkPMweHCr8aNg7eodwsVTD/rQuQx2V8P/nUdUuCoB9AZ7Ct12YC7jzA==
|
||||
tarball: 'file:projects/bf-luis-cli.tgz'
|
||||
version: 0.0.0
|
||||
'file:projects/bf-qnamaker.tgz':
|
||||
|
@ -6473,6 +6542,7 @@ specifiers:
|
|||
source-map-support: ~0.5.16
|
||||
testdouble: ^3.11.0
|
||||
ts-md5: ^1.2.6
|
||||
username: ^4.1.0
|
||||
uuid: ^3.3.3
|
||||
window-size: ^1.1.0
|
||||
xml2js: ^0.4.19
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
module.exports = {
|
||||
parseFile: require('./lufile/parseFileContents').parseFile,
|
||||
validateLUISBlob: require('./luis/luisValidator')
|
||||
parser: {
|
||||
parseFile: require('./lufile/parseFileContents').parseFile,
|
||||
validateLUISBlob: require('./luis/luisValidator')
|
||||
},
|
||||
sectionHandler: {
|
||||
luParser: require('./lufile/luParser'),
|
||||
sectionOperator: require('./lufile/sectionOperator'),
|
||||
luSectionTypes: require('./utils/enums/lusectiontypes')
|
||||
},
|
||||
}
|
|
@ -27,11 +27,6 @@ const modules = {
|
|||
|
||||
Parser: require('./lufile/classes/parserObject')
|
||||
},
|
||||
sectionHandler: {
|
||||
luParser: require('./lufile/luParser'),
|
||||
sectionOperator: require('./lufile/sectionOperator'),
|
||||
luSectionTypes: require('./utils/enums/lusectiontypes')
|
||||
},
|
||||
V2 : {
|
||||
Luis: require('./luis/luis'),
|
||||
LU: require('./lu/lu'),
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
const modules = {
|
||||
luBuild: {
|
||||
Builder: require('./lubuild/builder').Builder
|
||||
}
|
||||
};
|
||||
module.exports = modules;
|
|
@ -12,6 +12,8 @@ const fs = require('fs-extra')
|
|||
const delay = require('delay')
|
||||
const fileHelper = require('./../../utils/filehelper')
|
||||
const fileExtEnum = require('./../utils/helpers').FileExtTypeEnum
|
||||
const retCode = require('./../utils/enums/CLI-errors')
|
||||
const exception = require('./../utils/exception')
|
||||
const LuisBuilderVerbose = require('./../luis/luisCollate')
|
||||
const LuisBuilder = require('./../luis/luisBuilder')
|
||||
const LUOptions = require('./../lu/luOptions')
|
||||
|
@ -38,8 +40,17 @@ export class Builder {
|
|||
let fileCulture: string
|
||||
let fileName: string
|
||||
const luFiles = await fileHelper.getLuObjects(undefined, file, true, fileExtEnum.LUFile)
|
||||
const result = await LuisBuilderVerbose.build(luFiles, true, culture)
|
||||
const fileContent = result.parseToLuContent()
|
||||
|
||||
let fileContent = ''
|
||||
let result
|
||||
try {
|
||||
result = await LuisBuilderVerbose.build(luFiles, true, culture)
|
||||
fileContent = result.parseToLuContent()
|
||||
} catch (err) {
|
||||
err.text = `Invalid LU file ${file}: ${err.text}`
|
||||
throw(new exception(retCode.errorCode.INVALID_INPUT_FILE, err.text))
|
||||
}
|
||||
|
||||
this.handler(`${file} loaded\n`)
|
||||
let cultureFromPath = fileHelper.getCultureFromPath(file)
|
||||
if (cultureFromPath) {
|
||||
|
@ -47,7 +58,7 @@ export class Builder {
|
|||
let fileNameWithCulture = path.basename(file, path.extname(file))
|
||||
fileName = fileNameWithCulture.substring(0, fileNameWithCulture.length - fileCulture.length - 1)
|
||||
} else {
|
||||
fileCulture = culture
|
||||
fileCulture = result.culture !== 'en-us' ? result.culture : culture
|
||||
fileName = path.basename(file, path.extname(file))
|
||||
}
|
||||
|
||||
|
@ -95,7 +106,7 @@ export class Builder {
|
|||
})
|
||||
|
||||
if (hasDuplicates) {
|
||||
throw new Error('Files with same name and locale are found.')
|
||||
throw(new exception(retCode.errorCode.INVALID_INPUT_FILE, 'Files with same name and locale are found.'))
|
||||
}
|
||||
|
||||
return {luContents, recognizers, multiRecognizers, settings}
|
||||
|
@ -200,16 +211,23 @@ export class Builder {
|
|||
return dialogContents
|
||||
}
|
||||
|
||||
async writeDialogAssets(contents: any[], force: boolean, out: string) {
|
||||
async writeDialogAssets(contents: any[], force: boolean, out: string, luconfig: string) {
|
||||
let writeDone = false
|
||||
if (out) {
|
||||
let settingsContents = contents.filter(c => c.id.endsWith('.json'))
|
||||
let writeContents = contents.filter(c => c.id.endsWith('.dialog'))
|
||||
|
||||
if (settingsContents && settingsContents.length > 0) {
|
||||
writeContents.push(this.mergeSettingsContent(path.join(path.resolve(out), settingsContents[0].id), settingsContents))
|
||||
let writeContents = contents.filter(c => c.id.endsWith('.dialog'))
|
||||
let settingsContents = contents.filter(c => c.id.endsWith('.json'))
|
||||
|
||||
if (settingsContents && settingsContents.length > 0) {
|
||||
let outPath
|
||||
if (luconfig) {
|
||||
outPath = path.join(path.resolve(path.dirname(luconfig)), settingsContents[0].id)
|
||||
} else if (out) {
|
||||
outPath = path.join(path.resolve(out), settingsContents[0].id)
|
||||
}
|
||||
writeContents.push(this.mergeSettingsContent(outPath, settingsContents))
|
||||
}
|
||||
|
||||
if (out) {
|
||||
for (const content of writeContents) {
|
||||
const outFilePath = path.join(path.resolve(out), path.basename(content.path))
|
||||
if (force || !fs.existsSync(outFilePath)) {
|
||||
|
@ -219,7 +237,7 @@ export class Builder {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for (const content of contents) {
|
||||
for (const content of writeContents) {
|
||||
if (force || !fs.existsSync(content.path)) {
|
||||
this.handler(`Writing to ${content.path}\n`)
|
||||
await fs.writeFile(content.path, content.content, 'utf-8')
|
||||
|
@ -269,7 +287,7 @@ export class Builder {
|
|||
const versionObjs = await luBuildCore.listApplicationVersions(recognizer.getAppId())
|
||||
for (const versionObj of versionObjs) {
|
||||
if (versionObj.version !== newVersionId) {
|
||||
this.handler(`deleting old version=${versionObj.version}`)
|
||||
this.handler(`${recognizer.getLuPath()} deleting old version=${versionObj.version}`)
|
||||
await luBuildCore.deleteVersion(recognizer.getAppId(), versionObj.version)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,13 +49,7 @@ export class LuBuildCore {
|
|||
public compareApplications(currentApp: any, existingApp: any) {
|
||||
currentApp.desc = currentApp.desc && currentApp.desc !== '' && currentApp.desc !== existingApp.desc ? currentApp.desc : existingApp.desc
|
||||
currentApp.culture = currentApp.culture && currentApp.culture !== '' && currentApp.culture !== existingApp.culture ? currentApp.culture : existingApp.culture
|
||||
currentApp.versionId = currentApp.versionId && currentApp.versionId !== '' && currentApp.versionId !== existingApp.versionId ? currentApp.versionId : existingApp.versionId;
|
||||
|
||||
// convert utterance text from lu file to lower case
|
||||
// as utterances from luis api are all converted to lower case automatically
|
||||
(currentApp.utterances || []).forEach((u: any) => {
|
||||
u.text = u.text.toLowerCase()
|
||||
});
|
||||
currentApp.versionId = currentApp.versionId && currentApp.versionId !== '' && currentApp.versionId > existingApp.versionId ? currentApp.versionId : existingApp.versionId;
|
||||
|
||||
// convert list entities to remove synonyms word in list which is same with canonicalForm
|
||||
(currentApp.closedLists || []).forEach((c: any) => {
|
||||
|
@ -85,7 +79,7 @@ export class LuBuildCore {
|
|||
|
||||
public updateVersion(currentApp: any, existingApp: any) {
|
||||
let newVersionId: string
|
||||
if (currentApp.versionId && currentApp.versionId !== existingApp.versionId) {
|
||||
if (currentApp.versionId > existingApp.versionId) {
|
||||
newVersionId = currentApp.versionId
|
||||
} else {
|
||||
newVersionId = this.updateVersionValue(existingApp.versionId)
|
||||
|
@ -178,12 +172,12 @@ export class LuBuildCore {
|
|||
equal = equal && this.isArrayEqual(appA.closedLists, appB.closedLists)
|
||||
equal = equal && this.isArrayEqual(appA.composites, appB.composites)
|
||||
equal = equal && this.isArrayEqual(appA.entities, appB.entities)
|
||||
equal = equal && this.isArrayEqual(appA.modelFeatures, appB.modelFeatures)
|
||||
equal = equal && this.isArrayEqual(appA.model_features, appB.modelFeatures)
|
||||
equal = equal && this.isArrayEqual(appA.patternAnyEntities, appB.patternAnyEntities)
|
||||
equal = equal && this.isArrayEqual(appA.patterns, appB.patterns)
|
||||
equal = equal && this.isArrayEqual(appA.prebuiltEntities, appB.prebuiltEntities)
|
||||
equal = equal && this.isArrayEqual(appA.regexEntities, appB.regexEntities)
|
||||
equal = equal && this.isArrayEqual(appA.regexFeatures, appB.regexFeatures)
|
||||
equal = equal && this.isArrayEqual(appA.regex_entities, appB.regexEntities)
|
||||
equal = equal && this.isArrayEqual(appA.regex_features, appB.regexFeatures)
|
||||
equal = equal && this.isArrayEqual(appA.utterances, appB.utterances)
|
||||
|
||||
// handle exception for none intent which is default added in luis portal
|
||||
|
@ -205,15 +199,14 @@ export class LuBuildCore {
|
|||
let yObj = []
|
||||
|
||||
if (x && x.length > 0) {
|
||||
xObj = JSON.parse(JSON.stringify(x))
|
||||
xObj = JSON.parse(JSON.stringify(x).toLowerCase().replace(/ {2}/g, ' '))
|
||||
}
|
||||
|
||||
if (y && y.length > 0) {
|
||||
yObj = JSON.parse(JSON.stringify(y))
|
||||
yObj = JSON.parse(JSON.stringify(y).toLowerCase().replace(/ {2}/g, ' '))
|
||||
}
|
||||
|
||||
if (xObj.length !== yObj.length) return false
|
||||
|
||||
if (differenceWith(xObj, yObj, isEqual).length > 0) return false
|
||||
|
||||
return true
|
||||
|
|
|
@ -1,558 +0,0 @@
|
|||
import {expect, test} from '@oclif/test'
|
||||
const path = require('path')
|
||||
const fs = require('fs-extra')
|
||||
const uuidv1 = require('uuid/v1')
|
||||
const nock = require('nock')
|
||||
|
||||
const compareFiles = async function (file1: string, file2: string) {
|
||||
let result = await fs.readFile(path.join(__dirname, file1))
|
||||
let fixtureFile = await fs.readFile(path.join(__dirname, file2))
|
||||
result = result.toString().replace(/\r\n/g, '\n')
|
||||
fixtureFile = fixtureFile.toString().replace(/\r\n/g, '\n')
|
||||
expect(fixtureFile).to.deep.equal(result)
|
||||
return result === fixtureFile
|
||||
}
|
||||
|
||||
xdescribe('luis:build cli parameters test', () => {
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--help'])
|
||||
.it('should print the help contents when --help is passed as an argument', ctx => {
|
||||
expect(ctx.stdout).to.contain('Build lu files to train and publish luis applications')
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.stderr()
|
||||
.command(['luis:build', '--in', `${path.join(__dirname, './../../fixtures/testcases/lubuild')}`, '--botName', 'Contoso'])
|
||||
.it('displays an error if any required input parameters are missing', ctx => {
|
||||
expect(ctx.stderr).to.contain('Missing required flag:\n --authoringKey AUTHORINGKEY')
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.stderr()
|
||||
.command(['luis:build', '--authoringKey', uuidv1(), '--botName', 'Contoso'])
|
||||
.it('displays an error if any required input parameters are missing', ctx => {
|
||||
expect(ctx.stderr).to.contain('Missing input. Please use stdin or pass a file or folder location with --in flag')
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.stderr()
|
||||
.command(['luis:build', '--authoringKey', uuidv1(), '--in', `${path.join(__dirname, './../../fixtures/testcases/lubuild')}`])
|
||||
.it('displays an error if any required input parameters are missing', ctx => {
|
||||
expect(ctx.stderr).to.contain('Missing bot name. Please pass bot name with --botName flag')
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.stderr()
|
||||
.command(['luis:build', '--authoringKey', uuidv1(), '--in', `${path.join(__dirname, './../../fixtures/testcases/lubuild/file-name-duplicated')}`, '--botName', 'Contoso'])
|
||||
.it('displays an error if files with same name and locale are found', ctx => {
|
||||
expect(ctx.stderr).to.contain('Files with same name and locale are found')
|
||||
})
|
||||
})
|
||||
|
||||
xdescribe('luis:build create a new application successfully', () => {
|
||||
before(function () {
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, [{
|
||||
name: 'test.en-us.lu',
|
||||
id: 'f8c64e2a-1111-3a09-8f78-39d7adc76ec5'
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('import'))
|
||||
.reply(201, {
|
||||
appId: 'f8c64e2a-2222-3a09-8f78-39d7adc76ec5'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('train'))
|
||||
.reply(202, {
|
||||
statusId: 2,
|
||||
status: 'UpToDate'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('train'))
|
||||
.reply(200, [{
|
||||
modelId: '99999',
|
||||
details: {
|
||||
statusId: 0,
|
||||
status: 'Success',
|
||||
exampleCount: 0
|
||||
}
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('publish'))
|
||||
.reply(201, {
|
||||
versionId: '0.2',
|
||||
isStaging: true
|
||||
})
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich//lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log'])
|
||||
.it('should create a new application successfully', ctx => {
|
||||
expect(ctx.stdout).to.contain('Start to handle applications')
|
||||
expect(ctx.stdout).to.contain('Creating LUIS.ai application')
|
||||
expect(ctx.stdout).to.contain('training version=0.1')
|
||||
expect(ctx.stdout).to.contain('waiting for training for version=0.1')
|
||||
expect(ctx.stdout).to.contain('publishing version=0.1')
|
||||
expect(ctx.stdout).to.contain('publishing finished')
|
||||
})
|
||||
})
|
||||
|
||||
xdescribe('luis:build update application succeed when utterances changed', () => {
|
||||
const existingLuisApp = require('./../../fixtures/testcases/lubuild/sandwich/luis/test(development)-sandwich.utteranceChanged.en-us.lu.json')
|
||||
before(function () {
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, [{
|
||||
name: 'test(development)-sandwich.en-us.lu',
|
||||
id: 'f8c64e2a-8635-3a09-8f78-39d7adc76ec5'
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, {
|
||||
name: 'test(development)-sandwich.en-us.lu',
|
||||
id: 'f8c64e2a-8635-3a09-8f78-39d7adc76ec5',
|
||||
activeVersion: '0.1'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('export'))
|
||||
.reply(200, existingLuisApp)
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('import'))
|
||||
.reply(201, '0.2')
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('train'))
|
||||
.reply(202, {
|
||||
statusId: 2,
|
||||
status: 'UpToDate'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('train'))
|
||||
.reply(200, [{
|
||||
modelId: '99999',
|
||||
details: {
|
||||
statusId: 0,
|
||||
status: 'Success',
|
||||
exampleCount: 0
|
||||
}
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('publish'))
|
||||
.reply(201, {
|
||||
versionId: '0.2',
|
||||
isStaging: true
|
||||
})
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich/lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log'])
|
||||
.it('should update a luis application when utterances changed', ctx => {
|
||||
expect(ctx.stdout).to.contain('Start to handle applications')
|
||||
expect(ctx.stdout).to.contain('creating version=0.2')
|
||||
expect(ctx.stdout).to.contain('training version=0.2')
|
||||
expect(ctx.stdout).to.contain('waiting for training for version=0.2')
|
||||
expect(ctx.stdout).to.contain('publishing version=0.2')
|
||||
expect(ctx.stdout).to.contain('publishing finished')
|
||||
})
|
||||
})
|
||||
|
||||
xdescribe('luis:build update application succeed when utterances added', () => {
|
||||
const existingLuisApp = require('./../../fixtures/testcases/lubuild/sandwich/luis/test(development)-sandwich.utteranceAdded.en-us.lu.json')
|
||||
before(function () {
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, [{
|
||||
name: 'test(development)-sandwich.en-us.lu',
|
||||
id: 'f8c64e2a-8635-3a09-8f78-39d7adc76ec5'
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, {
|
||||
name: 'test(development)-sandwich.en-us.lu',
|
||||
id: 'f8c64e2a-8635-3a09-8f78-39d7adc76ec5',
|
||||
activeVersion: '0.1'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('export'))
|
||||
.reply(200, existingLuisApp)
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('import'))
|
||||
.reply(201, '0.2')
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('train'))
|
||||
.reply(202, {
|
||||
statusId: 2,
|
||||
status: 'UpToDate'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('train'))
|
||||
.reply(200, [{
|
||||
modelId: '99999',
|
||||
details: {
|
||||
statusId: 0,
|
||||
status: 'Success',
|
||||
exampleCount: 0
|
||||
}
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('publish'))
|
||||
.reply(201, {
|
||||
versionId: '0.2',
|
||||
isStaging: true
|
||||
})
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich/lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log'])
|
||||
.it('should update a luis application when utterances added', ctx => {
|
||||
expect(ctx.stdout).to.contain('Start to handle applications')
|
||||
expect(ctx.stdout).to.contain('creating version=0.2')
|
||||
expect(ctx.stdout).to.contain('training version=0.2')
|
||||
expect(ctx.stdout).to.contain('waiting for training for version=0.2')
|
||||
expect(ctx.stdout).to.contain('publishing version=0.2')
|
||||
expect(ctx.stdout).to.contain('publishing finished')
|
||||
})
|
||||
})
|
||||
|
||||
xdescribe('luis:build not update application if no changes', () => {
|
||||
const existingLuisApp = require('./../../fixtures/testcases/lubuild/sandwich/luis/test(development)-sandwich.en-us.lu.json')
|
||||
before(function () {
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, [{
|
||||
name: 'test(development)-sandwich.en-us.lu',
|
||||
id: 'f8c64e2a-8635-3a09-8f78-39d7adc76ec5'
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, {
|
||||
name: 'test(development)-sandwich.en-us.lu',
|
||||
id: 'f8c64e2a-8635-3a09-8f78-39d7adc76ec5',
|
||||
activeVersion: '0.1'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('export'))
|
||||
.reply(200, existingLuisApp)
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich/lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log'])
|
||||
.it('should not update a luis application when there are no changes for the coming lu file', ctx => {
|
||||
expect(ctx.stdout).to.contain('Start to handle applications')
|
||||
expect(ctx.stdout).to.contain('no changes')
|
||||
})
|
||||
})
|
||||
|
||||
xdescribe('luis:build write dialog assets successfully if --dialog set', () => {
|
||||
const existingLuisApp = require('./../../fixtures/testcases/lubuild/sandwich/luis/test(development)-sandwich.en-us.lu.json')
|
||||
before(async function () {
|
||||
await fs.ensureDir(path.join(__dirname, './../../../results/'))
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, [{
|
||||
name: 'test(development)-sandwich.en-us.lu',
|
||||
id: 'f8c64e2a-8635-3a09-8f78-39d7adc76ec5'
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, {
|
||||
name: 'test(development)-sandwich.en-us.lu',
|
||||
id: 'f8c64e2a-8635-3a09-8f78-39d7adc76ec5',
|
||||
activeVersion: '0.1'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('export'))
|
||||
.reply(200, existingLuisApp)
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await fs.remove(path.join(__dirname, './../../../results/'))
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich/lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--dialog', '--out', './results', '--log'])
|
||||
.it('should write dialog assets successfully when --dialog set', async ctx => {
|
||||
expect(await compareFiles('./../../../results/luis.settings.development.westus.json', './../../fixtures/testcases/lubuild/sandwich/config/luis.settings.development.westus.json')).to.be.true
|
||||
expect(await compareFiles('./../../../results/sandwich.en-us.lu.dialog', './../../fixtures/testcases/lubuild/sandwich/dialogs/sandwich.en-us.lu.dialog')).to.be.true
|
||||
expect(await compareFiles('./../../../results/sandwich.lu.dialog', './../../fixtures/testcases/lubuild/sandwich/dialogs/sandwich.lu.dialog')).to.be.true
|
||||
})
|
||||
})
|
||||
|
||||
xdescribe('luis:build create multiple applications successfully when input is a folder', () => {
|
||||
before(async function () {
|
||||
await fs.ensureDir(path.join(__dirname, './../../../results/'))
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, [{
|
||||
name: 'test.en-us.lu',
|
||||
id: 'f8c64e2a-1111-3a09-8f78-39d7adc76ec5'
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('import'))
|
||||
.reply(201, {
|
||||
appId: 'f8c64e2a-1111-3a09-8f78-39d7adc76ec5'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('import'))
|
||||
.reply(201, {
|
||||
appId: 'f8c64e2a-2222-3a09-8f78-39d7adc76ec5'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('import'))
|
||||
.reply(201, {
|
||||
appId: 'f8c64e2a-3333-3a09-8f78-39d7adc76ec5'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('train'))
|
||||
.reply(202, {
|
||||
statusId: 2,
|
||||
status: 'UpToDate'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('train'))
|
||||
.reply(202, {
|
||||
statusId: 2,
|
||||
status: 'UpToDate'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('train'))
|
||||
.reply(202, {
|
||||
statusId: 2,
|
||||
status: 'UpToDate'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('train'))
|
||||
.reply(200, [{
|
||||
modelId: '99999',
|
||||
details: {
|
||||
statusId: 0,
|
||||
status: 'Success',
|
||||
exampleCount: 0
|
||||
}
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('train'))
|
||||
.reply(200, [{
|
||||
modelId: '99999',
|
||||
details: {
|
||||
statusId: 0,
|
||||
status: 'Success',
|
||||
exampleCount: 0
|
||||
}
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('train'))
|
||||
.reply(200, [{
|
||||
modelId: '99999',
|
||||
details: {
|
||||
statusId: 0,
|
||||
status: 'Success',
|
||||
exampleCount: 0
|
||||
}
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('publish'))
|
||||
.reply(201, {
|
||||
versionId: '0.2',
|
||||
isStaging: true
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('publish'))
|
||||
.reply(201, {
|
||||
versionId: '0.2',
|
||||
isStaging: true
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('publish'))
|
||||
.reply(201, {
|
||||
versionId: '0.2',
|
||||
isStaging: true
|
||||
})
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await fs.remove(path.join(__dirname, './../../../results/'))
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/foo/lufiles', '--authoringKey', uuidv1(), '--botName', 'test', '--dialog', '--out', './results', '--log'])
|
||||
.it('should create multiple applications and write dialog assets successfully when input is a folder', async ctx => {
|
||||
expect(ctx.stdout).to.contain('foo.fr-fr.lu loaded')
|
||||
expect(ctx.stdout).to.contain('foo.lu loaded')
|
||||
expect(ctx.stdout).to.contain('foo.zh-cn.lu loaded')
|
||||
|
||||
expect(ctx.stdout).to.contain('Start to handle applications')
|
||||
expect(ctx.stdout).to.contain('Creating LUIS.ai application')
|
||||
expect(ctx.stdout).to.contain('training version=0.1')
|
||||
expect(ctx.stdout).to.contain('waiting for training for version=0.1')
|
||||
expect(ctx.stdout).to.contain('publishing version=0.1')
|
||||
|
||||
expect(ctx.stdout).to.contain('foo.fr-fr.lu publishing finished')
|
||||
expect(ctx.stdout).to.contain('foo.lu publishing finished')
|
||||
expect(ctx.stdout).to.contain('foo.zh-cn.lu publishing finished')
|
||||
|
||||
expect(await compareFiles('./../../../results/luis.settings.development.westus.json', './../../fixtures/testcases/lubuild/foo/config/luis.settings.development.westus.json')).to.be.true
|
||||
expect(await compareFiles('./../../../results/foo.lu.dialog', './../../fixtures/testcases/lubuild/foo/dialogs/foo.lu.dialog')).to.be.true
|
||||
expect(await compareFiles('./../../../results/foo.en-us.lu.dialog', './../../fixtures/testcases/lubuild/foo/dialogs/foo.en-us.lu.dialog')).to.be.true
|
||||
expect(await compareFiles('./../../../results/foo.fr-fr.lu.dialog', './../../fixtures/testcases/lubuild/foo/dialogs/foo.fr-fr.lu.dialog')).to.be.true
|
||||
expect(await compareFiles('./../../../results/foo.zh-cn.lu.dialog', './../../fixtures/testcases/lubuild/foo/dialogs/foo.zh-cn.lu.dialog')).to.be.true
|
||||
})
|
||||
})
|
||||
|
||||
xdescribe('luis:build update dialog assets successfully when dialog assets exist', () => {
|
||||
const existingLuisApp_EN_US = require('./../../fixtures/testcases/lubuild/foo2/luis/test(development)-foo.en-us.lu.json')
|
||||
const existingLuisApp_FR_FR = require('./../../fixtures/testcases/lubuild/foo2/luis/test(development)-foo.fr-fr.lu.json')
|
||||
before(async function () {
|
||||
await fs.ensureDir(path.join(__dirname, './../../../results/'))
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, [
|
||||
{
|
||||
name: 'test(development)-foo.fr-fr.lu',
|
||||
id: 'f8c64e2a-1111-3a09-8f78-39d7adc76ec5'
|
||||
},
|
||||
{
|
||||
name: 'test(development)-foo.en-us.lu',
|
||||
id: 'f8c64e2a-2222-3a09-8f78-39d7adc76ec5'
|
||||
}
|
||||
])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('import'))
|
||||
.reply(201, {
|
||||
appId: 'f8c64e2a-3333-3a09-8f78-39d7adc76ec5'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps') && uri.includes('f8c64e2a-2222-3a09-8f78-39d7adc76ec5'))
|
||||
.reply(200, {
|
||||
name: 'test(development)-foo.en-us.lu',
|
||||
id: 'f8c64e2a-2222-3a09-8f78-39d7adc76ec5',
|
||||
activeVersion: '0.1'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps') && uri.includes('f8c64e2a-1111-3a09-8f78-39d7adc76ec5'))
|
||||
.reply(200, {
|
||||
name: 'test(development)-foo.fr-fr.lu',
|
||||
id: 'f8c64e2a-1111-3a09-8f78-39d7adc76ec5',
|
||||
activeVersion: '0.1'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('train'))
|
||||
.reply(202, {
|
||||
statusId: 2,
|
||||
status: 'UpToDate'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('export') && uri.includes('f8c64e2a-2222-3a09-8f78-39d7adc76ec5'))
|
||||
.reply(200, existingLuisApp_EN_US)
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('export') && uri.includes('f8c64e2a-1111-3a09-8f78-39d7adc76ec5'))
|
||||
.reply(200, existingLuisApp_FR_FR)
|
||||
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('train'))
|
||||
.reply(200, [{
|
||||
modelId: '99999',
|
||||
details: {
|
||||
statusId: 0,
|
||||
status: 'Success',
|
||||
exampleCount: 0
|
||||
}
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('publish'))
|
||||
.reply(201, {
|
||||
versionId: '0.2',
|
||||
isStaging: true
|
||||
})
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await fs.remove(path.join(__dirname, './../../../results/'))
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/foo2/lufiles-and-dialog-assets', '--authoringKey', uuidv1(), '--botName', 'test', '--dialog', '--out', './results', '--log'])
|
||||
.it('should update dialog assets successfully when dialog assets exist', async ctx => {
|
||||
expect(ctx.stdout).to.contain('foo.fr-fr.lu loaded')
|
||||
expect(ctx.stdout).to.contain('foo.lu loaded')
|
||||
expect(ctx.stdout).to.contain('foo.zh-cn.lu loaded')
|
||||
|
||||
expect(ctx.stdout).to.contain('luis.settings.development.westus.json loaded')
|
||||
expect(ctx.stdout).to.contain('foo.lu.dialog loaded')
|
||||
|
||||
expect(ctx.stdout).to.contain('Start to handle applications')
|
||||
|
||||
expect(ctx.stdout).to.contain('foo.en-us.lu.dialog loaded')
|
||||
expect(ctx.stdout).to.contain('foo.fr-fr.lu.dialog loaded')
|
||||
|
||||
expect(ctx.stdout).to.contain('Creating LUIS.ai application')
|
||||
expect(ctx.stdout).to.contain('training version=0.1')
|
||||
expect(ctx.stdout).to.contain('waiting for training for version=0.1')
|
||||
expect(ctx.stdout).to.contain('publishing version=0.1')
|
||||
|
||||
expect(ctx.stdout).to.contain('foo.fr-fr.lu no changes')
|
||||
expect(ctx.stdout).to.contain('foo.lu no changes')
|
||||
expect(ctx.stdout).to.contain('foo.zh-cn.lu publishing finished')
|
||||
|
||||
expect(await compareFiles('./../../../results/luis.settings.development.westus.json', './../../fixtures/testcases/lubuild/foo2/config/luis.settings.development.westus.json')).to.be.true
|
||||
expect(await compareFiles('./../../../results/foo.lu.dialog', './../../fixtures/testcases/lubuild/foo2/dialogs/foo.lu.dialog')).to.be.true
|
||||
expect(await compareFiles('./../../../results/foo.en-us.lu.dialog', './../../fixtures/testcases/lubuild/foo2/dialogs/foo.en-us.lu.dialog')).to.be.true
|
||||
expect(await compareFiles('./../../../results/foo.fr-fr.lu.dialog', './../../fixtures/testcases/lubuild/foo2/dialogs/foo.fr-fr.lu.dialog')).to.be.true
|
||||
expect(await compareFiles('./../../../results/foo.zh-cn.lu.dialog', './../../fixtures/testcases/lubuild/foo2/dialogs/foo.zh-cn.lu.dialog')).to.be.true
|
||||
})
|
||||
})
|
|
@ -71,6 +71,7 @@
|
|||
"ts-node": "^8.4.1",
|
||||
"tslint": "^5.20.1",
|
||||
"typescript": "^3.5.3",
|
||||
"uuid": "^3.3.3"
|
||||
"uuid": "^3.3.3",
|
||||
"username": "^4.1.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import {Command, flags} from '@microsoft/bf-cli-command'
|
||||
import {CLIError, Command, flags} from '@microsoft/bf-cli-command'
|
||||
const path = require('path')
|
||||
const fs = require('fs-extra')
|
||||
const exception = require('@microsoft/bf-lu/lib/parser/utils/exception')
|
||||
const username = require('username')
|
||||
const file = require('@microsoft/bf-lu/lib/utils/filehelper')
|
||||
const fileExtEnum = require('@microsoft/bf-lu/lib/parser/utils/helpers').FileExtTypeEnum
|
||||
const Content = require('@microsoft/bf-lu').V2.LU
|
||||
|
@ -27,105 +29,115 @@ export default class LuisBuild extends Command {
|
|||
in: flags.string({char: 'i', description: 'Lu file or folder'}),
|
||||
authoringKey: flags.string({description: 'LUIS authoring key', required: true}),
|
||||
botName: flags.string({description: 'Bot name'}),
|
||||
out: flags.string({description: 'Output location'}),
|
||||
region: flags.string({description: 'LUIS authoring region [westus|westeurope|australiaeast]', default: 'westus'}),
|
||||
out: flags.string({char: 'o', description: 'Output file or folder name. If not specified, current directory will be used as output'}),
|
||||
defaultCulture: flags.string({description: 'Culture code for the content. Infer from .lu if available. Defaults to en-us'}),
|
||||
region: flags.string({description: 'LUIS authoring region'}),
|
||||
suffix: flags.string({description: 'Environment name as a suffix identifier to include in LUIS app name'}),
|
||||
force: flags.boolean({char: 'f', description: 'Force write dialog and settings files', default: false}),
|
||||
dialog: flags.boolean({description: 'Write out .dialog files', default: false}),
|
||||
fallbackLocale: flags.string({description: 'Locale to be used at the fallback if no locale specific recognizer is found. Only valid if --dialog is set'}),
|
||||
suffix: flags.string({description: 'Environment name as a suffix identifier to include in LUIS app name. Defaults to current logged in useralias'}),
|
||||
dialog: flags.boolean({description: 'Write out .dialog files', default: false}),
|
||||
force: flags.boolean({char: 'f', description: 'If --dialog flag is provided, overwirtes relevant dialog file', default: false}),
|
||||
luConfig: flags.string({description: 'Path to config for lu build'}),
|
||||
log: flags.boolean({description: 'write out log messages to console', default: false}),
|
||||
}
|
||||
|
||||
async run() {
|
||||
const {flags} = this.parse(LuisBuild)
|
||||
try {
|
||||
const {flags} = this.parse(LuisBuild)
|
||||
|
||||
flags.stdin = await this.readStdin()
|
||||
flags.stdin = await this.readStdin()
|
||||
|
||||
let files: string[] = []
|
||||
if (flags.luConfig) {
|
||||
const configFilePath = path.resolve(flags.luConfig)
|
||||
if (fs.existsSync(configFilePath)) {
|
||||
const configObj = JSON.parse(await file.getContentFromFile(configFilePath))
|
||||
if (configObj.name && configObj.name !== '') flags.botName = configObj.name
|
||||
if (configObj.defaultLanguage && configObj.defaultLanguage !== '') flags.defaultCulture = configObj.defaultLanguage
|
||||
if (configObj.deleteOldVersion) flags.deleteOldVersion = true
|
||||
if (configObj.out && configObj.out !== '') flags.out = configObj.out
|
||||
if (configObj.writeDialogFiles) flags.dialog = true
|
||||
if (configObj.models && configObj.models.length > 0) {
|
||||
files = configObj.models.map((m: string) => path.resolve(m))
|
||||
let files: string[] = []
|
||||
if (flags.luConfig) {
|
||||
const configFilePath = path.resolve(flags.luConfig)
|
||||
if (fs.existsSync(configFilePath)) {
|
||||
const configObj = JSON.parse(await file.getContentFromFile(configFilePath))
|
||||
if (configObj.name && configObj.name !== '') flags.botName = configObj.name
|
||||
if (configObj.defaultLanguage && configObj.defaultLanguage !== '') flags.defaultCulture = configObj.defaultLanguage
|
||||
if (configObj.deleteOldVersion) flags.deleteOldVersion = true
|
||||
if (configObj.out && configObj.out !== '') flags.out = path.isAbsolute(configObj.out) ? configObj.out : path.join(path.dirname(configFilePath), configObj.out)
|
||||
if (configObj.writeDialogFiles) flags.dialog = true
|
||||
if (configObj.models && configObj.models.length > 0) {
|
||||
files = configObj.models.map((m: string) => path.isAbsolute(m) ? m : path.join(path.dirname(configFilePath), m))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!flags.stdin && !flags.in && files.length === 0) {
|
||||
throw new Error('Missing input. Please use stdin or pass a file or folder location with --in flag')
|
||||
}
|
||||
|
||||
if (!flags.botName) {
|
||||
throw new Error('Missing bot name. Please pass bot name with --botName flag')
|
||||
}
|
||||
|
||||
flags.defaultCulture = flags.defaultCulture && flags.defaultCulture !== '' ? flags.defaultCulture : 'en-us'
|
||||
flags.region = flags.region && flags.region !== '' ? flags.region : 'westus'
|
||||
flags.suffix = flags.suffix && flags.suffix !== '' ? flags.suffix : 'development'
|
||||
flags.fallbackLocale = flags.fallbackLocale && flags.fallbackLocale !== '' ? flags.fallbackLocale : 'en-us'
|
||||
|
||||
// create builder class
|
||||
const builder = new Builder((input: string) => {
|
||||
if (flags.log) this.log(input)
|
||||
})
|
||||
|
||||
let luContents: any[] = []
|
||||
let recognizers = new Map<string, any>()
|
||||
let multiRecognizers = new Map<string, any>()
|
||||
let settings = new Map<string, any>()
|
||||
|
||||
if (flags.stdin && flags.stdin !== '') {
|
||||
// load lu content from stdin and create default recognizer, multiRecognier and settings
|
||||
this.log('Load lu content from stdin')
|
||||
const content = new Content(flags.stdin, new LUOptions('stdin', true, flags.defaultCulture, path.join(process.cwd(), 'stdin')))
|
||||
luContents.push(content)
|
||||
multiRecognizers.set('stdin', new MultiLanguageRecognizer(path.join(process.cwd(), 'stdin.lu.dialog'), {}))
|
||||
settings.set('stdin', new Settings(path.join(process.cwd(), `luis.settings.${flags.suffix}.${flags.region}.json`), {}))
|
||||
const recognizer = Recognizer.load(content.path, content.name, path.join(process.cwd(), `${content.name}.dialog`), settings.get('stdin'), {})
|
||||
recognizers.set(content.name, recognizer)
|
||||
} else {
|
||||
this.log('Start to load lu files')
|
||||
|
||||
// get lu files from flags.in
|
||||
if (flags.in && flags.in !== '') {
|
||||
const luFiles = await file.getLuFiles(flags.in, true, fileExtEnum.LUFile)
|
||||
files.push(...luFiles)
|
||||
if (!flags.stdin && !flags.in && files.length === 0) {
|
||||
throw new CLIError('Missing input. Please use stdin or pass a file or folder location with --in flag')
|
||||
}
|
||||
|
||||
// load lu contents from lu files
|
||||
// load existing recognizers, multiRecogniers and settings or create default ones
|
||||
const loadedResources = await builder.loadContents(files, flags.defaultCulture, flags.suffix, flags.region)
|
||||
luContents = loadedResources.luContents
|
||||
recognizers = loadedResources.recognizers
|
||||
multiRecognizers = loadedResources.multiRecognizers
|
||||
settings = loadedResources.settings
|
||||
}
|
||||
if (!flags.botName) {
|
||||
throw new CLIError('Missing bot name. Please pass bot name with --botName flag')
|
||||
}
|
||||
|
||||
// update or create and then train and publish luis applications based on loaded resources
|
||||
this.log('Start to handle applications')
|
||||
const dialogContents = await builder.build(luContents, recognizers, flags.authoringKey, flags.region, flags.botName, flags.suffix, flags.fallbackLocale, flags.deleteOldVersion, multiRecognizers, settings)
|
||||
flags.defaultCulture = flags.defaultCulture && flags.defaultCulture !== '' ? flags.defaultCulture : 'en-us'
|
||||
flags.region = flags.region && flags.region !== '' ? flags.region : 'westus'
|
||||
flags.suffix = flags.suffix && flags.suffix !== '' ? flags.suffix : await username() || 'development'
|
||||
flags.fallbackLocale = flags.fallbackLocale && flags.fallbackLocale !== '' ? flags.fallbackLocale : 'en-us'
|
||||
|
||||
// write dialog assets based on config
|
||||
if (flags.dialog) {
|
||||
const writeDone = await builder.writeDialogAssets(dialogContents, flags.force, flags.out)
|
||||
const dialogFilePath = (flags.stdin || !flags.in) ? process.cwd() : flags.in.endsWith(fileExtEnum.LUFile) ? path.dirname(path.resolve(flags.in)) : path.resolve(flags.in)
|
||||
const outputFolder = flags.out ? path.resolve(flags.out) : dialogFilePath
|
||||
if (writeDone) {
|
||||
this.log(`Successfully wrote .dialog files to ${outputFolder}`)
|
||||
// create builder class
|
||||
const builder = new Builder((input: string) => {
|
||||
if (flags.log) this.log(input)
|
||||
})
|
||||
|
||||
let luContents: any[] = []
|
||||
let recognizers = new Map<string, any>()
|
||||
let multiRecognizers = new Map<string, any>()
|
||||
let settings = new Map<string, any>()
|
||||
|
||||
if (flags.stdin && flags.stdin !== '') {
|
||||
// load lu content from stdin and create default recognizer, multiRecognier and settings
|
||||
if (flags.log) this.log('Load lu content from stdin\n')
|
||||
const content = new Content(flags.stdin, new LUOptions('stdin', true, flags.defaultCulture, path.join(process.cwd(), 'stdin')))
|
||||
luContents.push(content)
|
||||
multiRecognizers.set('stdin', new MultiLanguageRecognizer(path.join(process.cwd(), 'stdin.lu.dialog'), {}))
|
||||
settings.set('stdin', new Settings(path.join(process.cwd(), `luis.settings.${flags.suffix}.${flags.region}.json`), {}))
|
||||
const recognizer = Recognizer.load(content.path, content.name, path.join(process.cwd(), `${content.name}.dialog`), settings.get('stdin'), {})
|
||||
recognizers.set(content.name, recognizer)
|
||||
} else {
|
||||
this.log(`No changes to the .dialog files in ${outputFolder}`)
|
||||
if (flags.log) this.log('Loading files...\n')
|
||||
|
||||
// get lu files from flags.in.
|
||||
if (flags.in && flags.in !== '') {
|
||||
const luFiles = await file.getLuFiles(flags.in, true, fileExtEnum.LUFile)
|
||||
files.push(...luFiles)
|
||||
}
|
||||
|
||||
// de-dupe the files list
|
||||
files = [...new Set(files)]
|
||||
|
||||
// load lu contents from lu files
|
||||
// load existing recognizers, multiRecogniers and settings or create default ones
|
||||
const loadedResources = await builder.loadContents(files, flags.defaultCulture, flags.suffix, flags.region)
|
||||
luContents = loadedResources.luContents
|
||||
recognizers = loadedResources.recognizers
|
||||
multiRecognizers = loadedResources.multiRecognizers
|
||||
settings = loadedResources.settings
|
||||
}
|
||||
} else {
|
||||
this.log('The published application ids:')
|
||||
this.log(JSON.parse(dialogContents[dialogContents.length - 1].content).luis)
|
||||
|
||||
// update or create and then train and publish luis applications based on loaded resources
|
||||
if (flags.log) this.log('Handling applications...')
|
||||
const dialogContents = await builder.build(luContents, recognizers, flags.authoringKey, flags.region, flags.botName, flags.suffix, flags.fallbackLocale, flags.deleteOldVersion, multiRecognizers, settings)
|
||||
|
||||
// write dialog assets based on config
|
||||
if (flags.dialog) {
|
||||
const writeDone = await builder.writeDialogAssets(dialogContents, flags.force, flags.out, flags.luConfig)
|
||||
const dialogFilePath = (flags.stdin || !flags.in) ? process.cwd() : flags.in.endsWith(fileExtEnum.LUFile) ? path.dirname(path.resolve(flags.in)) : path.resolve(flags.in)
|
||||
const outputFolder = flags.out ? path.resolve(flags.out) : dialogFilePath
|
||||
if (writeDone) {
|
||||
this.log(`Successfully wrote .dialog files to ${outputFolder}\n`)
|
||||
} else {
|
||||
this.log(`No changes to the .dialog files in ${outputFolder}\n`)
|
||||
}
|
||||
} else {
|
||||
this.log('The published application ids:')
|
||||
this.log(JSON.parse(dialogContents[dialogContents.length - 1].content).luis)
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof exception) {
|
||||
throw new CLIError(error.text)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,15 @@ describe('luis:build cli parameters test', () => {
|
|||
.it('displays an error if files with same name and locale are found', ctx => {
|
||||
expect(ctx.stderr).to.contain('Files with same name and locale are found')
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.stderr()
|
||||
.command(['luis:build', '--authoringKey', uuidv1(), '--in', `${path.join(__dirname, './../../fixtures/testcases/bad3.lu')}`, '--botName', 'Contoso'])
|
||||
.it('displays an error if error occurs in parsing lu content', ctx => {
|
||||
expect(ctx.stderr).to.contain('Invalid LU file')
|
||||
expect(ctx.stderr).to.contain('[ERROR] line 4:0 - line 4:16: Invalid intent body line, did you miss \'-\' at line begin')
|
||||
})
|
||||
})
|
||||
|
||||
describe('luis:build create a new application successfully', () => {
|
||||
|
@ -97,9 +106,9 @@ describe('luis:build create a new application successfully', () => {
|
|||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich//lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log'])
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich//lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log', '--suffix', 'development'])
|
||||
.it('should create a new application successfully', ctx => {
|
||||
expect(ctx.stdout).to.contain('Start to handle applications')
|
||||
expect(ctx.stdout).to.contain('Handling applications...')
|
||||
expect(ctx.stdout).to.contain('Creating LUIS.ai application')
|
||||
expect(ctx.stdout).to.contain('training version=0.1')
|
||||
expect(ctx.stdout).to.contain('waiting for training for version=0.1')
|
||||
|
@ -162,9 +171,9 @@ describe('luis:build update application succeed when utterances changed', () =>
|
|||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich/lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log'])
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich/lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log', '--suffix', 'development'])
|
||||
.it('should update a luis application when utterances changed', ctx => {
|
||||
expect(ctx.stdout).to.contain('Start to handle applications')
|
||||
expect(ctx.stdout).to.contain('Handling applications...')
|
||||
expect(ctx.stdout).to.contain('creating version=0.2')
|
||||
expect(ctx.stdout).to.contain('training version=0.2')
|
||||
expect(ctx.stdout).to.contain('waiting for training for version=0.2')
|
||||
|
@ -227,9 +236,9 @@ describe('luis:build update application succeed when utterances added', () => {
|
|||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich/lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log'])
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich/lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log', '--suffix', 'development'])
|
||||
.it('should update a luis application when utterances added', ctx => {
|
||||
expect(ctx.stdout).to.contain('Start to handle applications')
|
||||
expect(ctx.stdout).to.contain('Handling applications...')
|
||||
expect(ctx.stdout).to.contain('creating version=0.2')
|
||||
expect(ctx.stdout).to.contain('training version=0.2')
|
||||
expect(ctx.stdout).to.contain('waiting for training for version=0.2')
|
||||
|
@ -263,9 +272,9 @@ describe('luis:build not update application if no changes', () => {
|
|||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich/lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log'])
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich/lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log', '--suffix', 'development'])
|
||||
.it('should not update a luis application when there are no changes for the coming lu file', ctx => {
|
||||
expect(ctx.stdout).to.contain('Start to handle applications')
|
||||
expect(ctx.stdout).to.contain('Handling applications...')
|
||||
expect(ctx.stdout).to.contain('no changes')
|
||||
})
|
||||
})
|
||||
|
@ -301,7 +310,7 @@ describe('luis:build write dialog assets successfully if --dialog set', () => {
|
|||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich/lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--dialog', '--out', './results', '--log'])
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/sandwich/lufiles/sandwich.en-us.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--dialog', '--out', './results', '--log', '--suffix', 'development'])
|
||||
.it('should write dialog assets successfully when --dialog set', async ctx => {
|
||||
expect(await compareFiles('./../../../results/luis.settings.development.westus.json', './../../fixtures/testcases/lubuild/sandwich/config/luis.settings.development.westus.json')).to.be.true
|
||||
expect(await compareFiles('./../../../results/sandwich.en-us.lu.dialog', './../../fixtures/testcases/lubuild/sandwich/dialogs/sandwich.en-us.lu.dialog')).to.be.true
|
||||
|
@ -420,13 +429,13 @@ describe('luis:build create multiple applications successfully when input is a f
|
|||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/foo/lufiles', '--authoringKey', uuidv1(), '--botName', 'test', '--dialog', '--out', './results', '--log'])
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/foo/lufiles', '--authoringKey', uuidv1(), '--botName', 'test', '--dialog', '--out', './results', '--log', '--suffix', 'development'])
|
||||
.it('should create multiple applications and write dialog assets successfully when input is a folder', async ctx => {
|
||||
expect(ctx.stdout).to.contain('foo.fr-fr.lu loaded')
|
||||
expect(ctx.stdout).to.contain('foo.lu loaded')
|
||||
expect(ctx.stdout).to.contain('foo.zh-cn.lu loaded')
|
||||
|
||||
expect(ctx.stdout).to.contain('Start to handle applications')
|
||||
expect(ctx.stdout).to.contain('Handling applications...')
|
||||
expect(ctx.stdout).to.contain('Creating LUIS.ai application')
|
||||
expect(ctx.stdout).to.contain('training version=0.1')
|
||||
expect(ctx.stdout).to.contain('waiting for training for version=0.1')
|
||||
|
@ -526,7 +535,7 @@ describe('luis:build update dialog assets successfully when dialog assets exist'
|
|||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/foo2/lufiles-and-dialog-assets', '--authoringKey', uuidv1(), '--botName', 'test', '--dialog', '--out', './results', '--log'])
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/foo2/lufiles-and-dialog-assets', '--authoringKey', uuidv1(), '--botName', 'test', '--dialog', '--out', './results', '--log', '--suffix', 'development'])
|
||||
.it('should update dialog assets successfully when dialog assets exist', async ctx => {
|
||||
expect(ctx.stdout).to.contain('foo.fr-fr.lu loaded')
|
||||
expect(ctx.stdout).to.contain('foo.lu loaded')
|
||||
|
@ -535,7 +544,7 @@ describe('luis:build update dialog assets successfully when dialog assets exist'
|
|||
expect(ctx.stdout).to.contain('luis.settings.development.westus.json loaded')
|
||||
expect(ctx.stdout).to.contain('foo.lu.dialog loaded')
|
||||
|
||||
expect(ctx.stdout).to.contain('Start to handle applications')
|
||||
expect(ctx.stdout).to.contain('Handling applications...')
|
||||
|
||||
expect(ctx.stdout).to.contain('foo.en-us.lu.dialog loaded')
|
||||
expect(ctx.stdout).to.contain('foo.fr-fr.lu.dialog loaded')
|
||||
|
@ -555,4 +564,128 @@ describe('luis:build update dialog assets successfully when dialog assets exist'
|
|||
expect(await compareFiles('./../../../results/foo.fr-fr.lu.dialog', './../../fixtures/testcases/lubuild/foo2/dialogs/foo.fr-fr.lu.dialog')).to.be.true
|
||||
expect(await compareFiles('./../../../results/foo.zh-cn.lu.dialog', './../../fixtures/testcases/lubuild/foo2/dialogs/foo.zh-cn.lu.dialog')).to.be.true
|
||||
})
|
||||
})
|
||||
|
||||
describe('luis:build not update application if only cases of utterances or patterns are changed', () => {
|
||||
const existingLuisApp = require('./../../fixtures/testcases/lubuild/case-insensitive/luis/test(development)-case-insensitive.en-us.lu.json')
|
||||
before(function () {
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, [{
|
||||
name: 'test(development)-case-insensitive.en-us.lu',
|
||||
id: 'f8c64e2a-8635-3a09-8f78-39d7adc76ec5'
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, {
|
||||
name: 'test(development)-case-insensitive.en-us.lu',
|
||||
id: 'f8c64e2a-8635-3a09-8f78-39d7adc76ec5',
|
||||
activeVersion: '0.1'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('export'))
|
||||
.reply(200, existingLuisApp)
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--in', './test/fixtures/testcases/lubuild/case-insensitive/lufiles/case-insensitive.lu', '--authoringKey', uuidv1(), '--botName', 'test', '--log', '--suffix', 'development'])
|
||||
.it('should not update a luis application when only cases of utterances or patterns are different for the coming lu file', ctx => {
|
||||
expect(ctx.stdout).to.contain('Handling applications...')
|
||||
expect(ctx.stdout).to.contain('no changes')
|
||||
})
|
||||
})
|
||||
|
||||
describe('luis:build update application succeed with parameters set from luconfig', () => {
|
||||
const existingLuisApp = require('./../../fixtures/testcases/lubuild/luconfig/luis/MyProject(development)-test.en-us.lu.json')
|
||||
before(async function () {
|
||||
await fs.ensureDir(path.join(__dirname, './../../../results/'))
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, [{
|
||||
name: 'MyProject(development)-test.en-us.lu',
|
||||
id: 'f8c64e2a-8635-3a09-8f78-39d7adc76ec5'
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, {
|
||||
name: 'MyProject(development)-test.en-us.lu',
|
||||
id: 'f8c64e2a-8635-3a09-8f78-39d7adc76ec5',
|
||||
activeVersion: '0.1'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('export'))
|
||||
.reply(200, existingLuisApp)
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('import'))
|
||||
.reply(201, '0.2')
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('apps'))
|
||||
.reply(200, [
|
||||
{
|
||||
version: '0.1'
|
||||
},
|
||||
{
|
||||
version: '0.2'
|
||||
}
|
||||
])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.delete(uri => uri.includes('apps'))
|
||||
.reply(200)
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('train'))
|
||||
.reply(202, {
|
||||
statusId: 2,
|
||||
status: 'UpToDate'
|
||||
})
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.get(uri => uri.includes('train'))
|
||||
.reply(200, [{
|
||||
modelId: '99999',
|
||||
details: {
|
||||
statusId: 0,
|
||||
status: 'Success',
|
||||
exampleCount: 0
|
||||
}
|
||||
}])
|
||||
|
||||
nock('https://westus.api.cognitive.microsoft.com')
|
||||
.post(uri => uri.includes('publish'))
|
||||
.reply(201, {
|
||||
versionId: '0.2',
|
||||
isStaging: true
|
||||
})
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await fs.remove(path.join(__dirname, './../../../results/'))
|
||||
})
|
||||
|
||||
test
|
||||
.stdout()
|
||||
.command(['luis:build', '--authoringKey', uuidv1(), '--luConfig', './test/fixtures/testcases/lubuild/luconfig/lufiles/luconfig.json', '--log', '--suffix', 'development'])
|
||||
.it('should update a luis application when utterances changed', async ctx => {
|
||||
console.log(ctx)
|
||||
expect(ctx.stdout).to.contain('Handling applications...')
|
||||
expect(ctx.stdout).to.contain('creating version=0.2')
|
||||
expect(ctx.stdout).to.contain('deleting old version=0.1')
|
||||
expect(ctx.stdout).to.contain('training version=0.2')
|
||||
expect(ctx.stdout).to.contain('waiting for training for version=0.2')
|
||||
expect(ctx.stdout).to.contain('publishing version=0.2')
|
||||
expect(ctx.stdout).to.contain('publishing finished')
|
||||
|
||||
expect(await compareFiles('./../../../results/luis.settings.development.westus.json', './../../fixtures/testcases/lubuild/luconfig/config/luis.settings.development.westus.json')).to.be.true
|
||||
expect(await compareFiles('./../../../results/test.en-us.lu.dialog', './../../fixtures/testcases/lubuild/luconfig/dialogs/test.en-us.lu.dialog')).to.be.true
|
||||
expect(await compareFiles('./../../../results/test.lu.dialog', './../../fixtures/testcases/lubuild/luconfig/dialogs/test.lu.dialog')).to.be.true
|
||||
})
|
||||
})
|
34
packages/luis/test/fixtures/testcases/lubuild/case-insensitive/lufiles/case-insensitive.lu
поставляемый
Normal file
34
packages/luis/test/fixtures/testcases/lubuild/case-insensitive/lufiles/case-insensitive.lu
поставляемый
Normal file
|
@ -0,0 +1,34 @@
|
|||
# Greeting
|
||||
- Hi Morning
|
||||
- Hello Evening
|
||||
|
||||
# Help
|
||||
- Help me with {Item}
|
||||
- Please Help {Item}
|
||||
|
||||
# GetUserProfile
|
||||
- I'm 36 years old
|
||||
- My age is 36
|
||||
- I am 36
|
||||
|
||||
> Prebuilt entities
|
||||
@ prebuilt age
|
||||
@ prebuilt personName
|
||||
|
||||
> Phrase list
|
||||
@ phraselist profileDefinition(interchangeable) =
|
||||
- I'm
|
||||
- My
|
||||
- I am
|
||||
|
||||
> Define a list entity for user city
|
||||
@ list Cities =
|
||||
- seattle :
|
||||
- SEA
|
||||
- Seatac
|
||||
- redmond :
|
||||
- microsoft
|
||||
- REA
|
||||
|
||||
> Define a regex entity for user zip code
|
||||
@ regex zipCode = /[0-9]{5}/
|
117
packages/luis/test/fixtures/testcases/lubuild/case-insensitive/luis/test(development)-case-insensitive.en-us.lu.json
поставляемый
Normal file
117
packages/luis/test/fixtures/testcases/lubuild/case-insensitive/luis/test(development)-case-insensitive.en-us.lu.json
поставляемый
Normal file
|
@ -0,0 +1,117 @@
|
|||
{
|
||||
"luis_schema_version": "4.0.0",
|
||||
"versionId": "0.2",
|
||||
"name": "test(development)-case-insensitive.en-us.lu",
|
||||
"desc": "Model for test app, targetting development",
|
||||
"culture": "en-us",
|
||||
"tokenizerVersion": "1.0.0",
|
||||
"intents": [
|
||||
{
|
||||
"name": "GetUserProfile"
|
||||
},
|
||||
{
|
||||
"name": "Greeting"
|
||||
},
|
||||
{
|
||||
"name": "Help"
|
||||
},
|
||||
{
|
||||
"name": "None"
|
||||
}
|
||||
],
|
||||
"entities": [],
|
||||
"composites": [],
|
||||
"closedLists": [
|
||||
{
|
||||
"name": "Cities",
|
||||
"subLists": [
|
||||
{
|
||||
"canonicalForm": "seattle",
|
||||
"list": [
|
||||
"SEA",
|
||||
"Seatac"
|
||||
]
|
||||
},
|
||||
{
|
||||
"canonicalForm": "redmond",
|
||||
"list": [
|
||||
"microsoft",
|
||||
"REA"
|
||||
]
|
||||
}
|
||||
],
|
||||
"roles": []
|
||||
}
|
||||
],
|
||||
"patternAnyEntities": [
|
||||
{
|
||||
"name": "Item",
|
||||
"roles": [],
|
||||
"explicitList": []
|
||||
}
|
||||
],
|
||||
"regex_entities": [
|
||||
{
|
||||
"name": "zipCode",
|
||||
"regexPattern": "[0-9]{5}",
|
||||
"roles": []
|
||||
}
|
||||
],
|
||||
"prebuiltEntities": [
|
||||
{
|
||||
"name": "age",
|
||||
"roles": []
|
||||
},
|
||||
{
|
||||
"name": "personName",
|
||||
"roles": []
|
||||
}
|
||||
],
|
||||
"model_features": [
|
||||
{
|
||||
"name": "profileDefinition",
|
||||
"mode": true,
|
||||
"words": "I'm,My,I am",
|
||||
"activated": true
|
||||
}
|
||||
],
|
||||
"regex_features": [],
|
||||
"patterns": [
|
||||
{
|
||||
"pattern": "please help {Item}",
|
||||
"intent": "Help"
|
||||
},
|
||||
{
|
||||
"pattern": "help me with {Item}",
|
||||
"intent": "Help"
|
||||
}
|
||||
],
|
||||
"utterances": [
|
||||
{
|
||||
"text": "hello evening",
|
||||
"intent": "Greeting",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "hi morning",
|
||||
"intent": "Greeting",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "i am 36",
|
||||
"intent": "GetUserProfile",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "i'm 36 years old",
|
||||
"intent": "GetUserProfile",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "my age is 36",
|
||||
"intent": "GetUserProfile",
|
||||
"entities": []
|
||||
}
|
||||
],
|
||||
"settings": []
|
||||
}
|
5
packages/luis/test/fixtures/testcases/lubuild/luconfig/config/luis.settings.development.westus.json
поставляемый
Normal file
5
packages/luis/test/fixtures/testcases/lubuild/luconfig/config/luis.settings.development.westus.json
поставляемый
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"luis": {
|
||||
"test_en-us_lu": "f8c64e2a-8635-3a09-8f78-39d7adc76ec5"
|
||||
}
|
||||
}
|
6
packages/luis/test/fixtures/testcases/lubuild/luconfig/dialogs/test.en-us.lu.dialog
поставляемый
Normal file
6
packages/luis/test/fixtures/testcases/lubuild/luconfig/dialogs/test.en-us.lu.dialog
поставляемый
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"$type": "Microsoft.LuisRecognizer",
|
||||
"applicationId": "=settings.luis.test_en-us_lu",
|
||||
"endpoint": "=settings.luis.endpoint",
|
||||
"endpointKey": "=settings.luis.endpointKey"
|
||||
}
|
7
packages/luis/test/fixtures/testcases/lubuild/luconfig/dialogs/test.lu.dialog
поставляемый
Normal file
7
packages/luis/test/fixtures/testcases/lubuild/luconfig/dialogs/test.lu.dialog
поставляемый
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"$type": "Microsoft.MultiLanguageRecognizer",
|
||||
"recognizers": {
|
||||
"en-us": "test.en-us.lu",
|
||||
"": "test.en-us.lu"
|
||||
}
|
||||
}
|
10
packages/luis/test/fixtures/testcases/lubuild/luconfig/lufiles/luconfig.json
поставляемый
Normal file
10
packages/luis/test/fixtures/testcases/lubuild/luconfig/lufiles/luconfig.json
поставляемый
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "MyProject",
|
||||
"defaultLanguage": "en-us",
|
||||
"deleteOldVersion": true,
|
||||
"out": "./../../../../../../results",
|
||||
"writeDialogFiles": true,
|
||||
"models": [
|
||||
"./test.lu"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,206 @@
|
|||
> Entity definitions
|
||||
$ itemTitle : simple
|
||||
|
||||
> Add a Phrase List with todo variations. Mark them as interchangeable.
|
||||
$ todoItem : PhraseList interchangeable
|
||||
- todo
|
||||
- todos
|
||||
- to dos
|
||||
- todo list
|
||||
- todos list
|
||||
- item list
|
||||
- items collection
|
||||
|
||||
> Add a list entity to detect list tye
|
||||
$ listType : todo =
|
||||
- to do
|
||||
- todos
|
||||
- laundry
|
||||
|
||||
$ listType : shopping =
|
||||
- shopping
|
||||
- shop
|
||||
- shoppers
|
||||
|
||||
$ listType : grocery =
|
||||
- groceries
|
||||
- fruits
|
||||
- vegetables
|
||||
- household items
|
||||
- house hold items
|
||||
|
||||
> Help intent and related utterances.
|
||||
# Help
|
||||
- What can I say?
|
||||
- Who are you?
|
||||
- I need help
|
||||
- Not sure what I can do
|
||||
- What do you want me to say?
|
||||
- What can you do?
|
||||
- What can you help with?
|
||||
- help please
|
||||
- What are my options?
|
||||
- well, I do not know what my todo's title is
|
||||
- I do not know
|
||||
- can you please help?
|
||||
|
||||
> Greeting intent and related utterances
|
||||
# Greeting
|
||||
- hi
|
||||
- hello
|
||||
- hiya
|
||||
- how are you?
|
||||
- how do you do?
|
||||
|
||||
> Cancel intent and related utterances
|
||||
# Cancel
|
||||
- cancel
|
||||
- cancel all
|
||||
- stop that
|
||||
- do not do it
|
||||
- abort
|
||||
- please stop what you are doing
|
||||
- I changed my mind
|
||||
- cancel add todo
|
||||
- cancel that
|
||||
- I do not want to add a todo
|
||||
- No todo for me
|
||||
- Cancel this
|
||||
- cancel delete todo
|
||||
- Let's just leave it as is
|
||||
- I do not wish to delete my todo anymore
|
||||
- Keep my todos as is
|
||||
- No todo for me
|
||||
|
||||
> Add item
|
||||
# AddItem
|
||||
- Add todo
|
||||
- add a to do item
|
||||
- Please remind me to {itemTitle=buy milk}
|
||||
- Please remember that I need to {itemTitle=buy milk}
|
||||
- I need you to remember that {itemTitle=my wife's birthday is Jan 9th}
|
||||
- Add a todo named {itemTitle=send report over this weekend}
|
||||
- Add {itemTitle=get a new car} to the todo list
|
||||
- Add {itemTitle=write a spec} to the list
|
||||
- Add {itemTitle=finish this demo} to my todo list
|
||||
- add a todo item {itemTitle=vacuuming by october 3rd}
|
||||
- add {itemTitle=call my mother} to my todo list
|
||||
- add {itemTitle=due date august to peanut butter jelly bread milk} on todos list
|
||||
- add {itemTitle=go running} to my todos
|
||||
- add to my todos list {itemTitle=mail the insurance forms out by saturday}
|
||||
- can i add {itemTitle=shirts} on the todos list
|
||||
- could i add {itemTitle=medicine} to the todos list
|
||||
- would you add {itemTitle=heavy cream} to the todos list
|
||||
- add {itemTitle} to my todo list
|
||||
- add a to do that {itemTitle=purchase a nice sweater}
|
||||
- add a to do to {itemTitle=buy shoes}
|
||||
- add an task of {itemTitle=chores to do around the house}
|
||||
- add {itemTitle=go to whole foods} in my to do list
|
||||
- add {itemTitle=reading} to my to do list
|
||||
- add this thing in to do list
|
||||
- add to my to do list {itemTitle=pick up clothes}
|
||||
- add to my to do list {itemTitle=print papers for 10 copies this afternoon}
|
||||
- create to do
|
||||
- create to do that {itemTitle=read a book tonight}
|
||||
- create to do to {itemTitle=go running in the park}
|
||||
- put {itemTitle=hikes} on my to do list
|
||||
- remind me to {itemTitle = pick up dry cleaning}
|
||||
- new to do
|
||||
- add another one
|
||||
- add
|
||||
> Add patterns
|
||||
- Please remember [to] {itemTitle}
|
||||
- I need you to remember [that] {itemTitle}
|
||||
- Add a todo named {itemTitle}
|
||||
- Add {itemTitle} to the list
|
||||
- [Please] add {itemTitle} to the todo list
|
||||
- Add {itemTitle} to my todo
|
||||
- add {itemTitle} to my to do list
|
||||
- add {itemTitle} to my to dos
|
||||
- add a to do that buy {itemTitle}
|
||||
- add a to do that purchase {itemTitle}
|
||||
- add a to do that shop {itemTitle}
|
||||
- add a to do to {itemTitle}
|
||||
- add to do that {itemTitle}
|
||||
- add to do to {itemTitle}
|
||||
- create a to do to {itemTitle}
|
||||
- create to do to {itemTitle}
|
||||
- remind me to {itemTitle}
|
||||
|
||||
# DeleteItem
|
||||
- Remove todo
|
||||
- Mark {itemTitle = buy milk} as complete
|
||||
- Flag {itemTitle = first one} as done
|
||||
- Remove {itemTitle = finish this demo} from the todo list
|
||||
- remove another one
|
||||
- remove
|
||||
- clear my todo named {itemTitle = get a new car}
|
||||
- I'm done with the first todo
|
||||
- I finished the las todo
|
||||
- Remove the first todo
|
||||
- Delete todo
|
||||
- Clear my todos
|
||||
- Delete all my todos
|
||||
- Remove all my todo
|
||||
- Forget the list
|
||||
- Purge the todo list
|
||||
- can you delete {itemTitle=todo1}
|
||||
- can you delete {itemTitle=xxx} item
|
||||
- delete {itemTitle=eggs} from list
|
||||
- delete off {itemTitle=pancake mix} on the shopping list
|
||||
- delete {itemTitle=shampoo} from shopping list
|
||||
- delete {itemTitle=shirts} from list
|
||||
- delete task {itemTitle=go fishing}
|
||||
- delete task {itemTitle=go to cinema tonight}
|
||||
- delete the item {itemTitle=buy socks} from my todo list
|
||||
- delete the second task in my shopping list
|
||||
- delete the task {itemTitle=house cleanup this weekend}
|
||||
- delete the task that {itemTitle=hit the gym every morning}
|
||||
- delete the to do {itemTitle=meet my friends tomorrow}
|
||||
- delete the to do that {itemTitle=daily practice piano}
|
||||
- delete the to do that {itemTitle=meet john when he come here the next friday}
|
||||
- delete to do {itemTitle=buy milk}
|
||||
- delete to do {itemTitle=go shopping}
|
||||
- delete to do that {itemTitle=go hiking tomorrow}
|
||||
- erase {itemTitle=bananas} from shopping list
|
||||
- erase {itemTitle=peanuts} on the shopping list
|
||||
- remove {itemTitle=asprin} from shopping list
|
||||
- remove {itemTitle=black shoes} from shopping list
|
||||
- remove {itemTitle=class} from todo list
|
||||
- remove {itemTitle=salad vegetables} from grocery list
|
||||
- remove task {itemTitle=buy dog food}
|
||||
- remove task {itemTitle=go shopping}
|
||||
- remove task that {itemTitle=go hiking this weekend}
|
||||
- remove task that {itemTitle=lawn mowing}
|
||||
- remove the item {itemTitle=paris} from my list
|
||||
- remove the task that {itemTitle=go to library after work}
|
||||
- remove the to do {itemTitle=physical examination}
|
||||
- remove the to do that {itemTitle=pick tom up at six p.m.}
|
||||
- remove to do {itemTitle=go to the gym}
|
||||
- remove to do that {itemTitle=go to the dentist tomorrow morning}
|
||||
> Add patterns
|
||||
- I did {itemTitle}
|
||||
- I completed {itemTitle}
|
||||
- Delete {itemTitle}
|
||||
- Mark {itemTitle} as complete
|
||||
- Remove {itemTitle} from my [todo] list
|
||||
- [Please] delete {itemTitle} from the list
|
||||
|
||||
# ViewCollection
|
||||
- show my todo
|
||||
- can you please show my todos?
|
||||
- please show my todo list
|
||||
- todo list please
|
||||
- I need to see my todo list
|
||||
- can you show me the list?
|
||||
- please show the list
|
||||
- what do i have on my todo?
|
||||
- what is on my list?
|
||||
- do i have anything left on my todo list?
|
||||
- I hope I do not have any todo left
|
||||
- do i have any tasks left?
|
||||
- hit me up with more items
|
||||
- view my todos
|
||||
- can you show my todo
|
||||
- see todo
|
||||
- I would like to see my todos list
|
1227
packages/luis/test/fixtures/testcases/lubuild/luconfig/luis/MyProject(development)-test.en-us.lu.json
поставляемый
Normal file
1227
packages/luis/test/fixtures/testcases/lubuild/luconfig/luis/MyProject(development)-test.en-us.lu.json
поставляемый
Normal file
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче