|
| 1 | +const fs = require('fs-extra') |
| 2 | +const path = require('path') |
| 3 | +const NEWLINE = require('os').EOL |
| 4 | +var chai = require('chai'); |
| 5 | +var assert = chai.assert; |
| 6 | +const LuisBuilder = require('./../../../src/parser/luis/luisBuilder') |
| 7 | + |
| 8 | +const loadLuFile = async function(filePath) { |
| 9 | + let fileContent = await fs.readFile(path.join(__dirname, filePath)) |
| 10 | + return sanitize(fileContent) |
| 11 | +} |
| 12 | + |
| 13 | +const sanitize = function(content) { |
| 14 | + return content.toString().replace(/\r\n/g, "\n") |
| 15 | +} |
| 16 | + |
| 17 | +const loadJsonFile = async function(filePath) { |
| 18 | + let result = await fs.readJson(path.join(__dirname, filePath)) |
| 19 | + result = sanitizeExampleJson(JSON.stringify(result)) |
| 20 | + return JSON.parse(result) |
| 21 | +} |
| 22 | + |
| 23 | +function sanitizeExampleJson(fileContent) { |
| 24 | + let escapedExampleNewLine = JSON.stringify('\r\n').replace(/"/g, '').replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); |
| 25 | + let escapedNewLine = JSON.stringify(NEWLINE).replace(/"/g, ''); |
| 26 | + return fileContent.replace(new RegExp(escapedExampleNewLine, 'g'), escapedNewLine); |
| 27 | +} |
| 28 | + |
| 29 | +const assertToLu = async function(srcJSONFile, tgtLUFile) { |
| 30 | + let testInputFile = await loadJsonFile(srcJSONFile) |
| 31 | + let testInputJSON = LuisBuilder.fromJson(testInputFile) |
| 32 | + let testContent = testInputJSON.parseToLuContent(); |
| 33 | + let verifiedContent = await loadLuFile(tgtLUFile) |
| 34 | + assert.deepEqual(sanitize(testContent), verifiedContent) |
| 35 | +} |
| 36 | + |
| 37 | +const assertToJSON = async function(srcLUFile, tgtJSONFile, name = undefined) { |
| 38 | + let testInputFile = await loadLuFile(srcLUFile) |
| 39 | + let testContent = await LuisBuilder.fromLUAsync(testInputFile) |
| 40 | + if (name !== undefined) testContent.name = name |
| 41 | + let verifiedContent = await loadJsonFile(tgtJSONFile) |
| 42 | + assert.deepEqual(testContent, verifiedContent) |
| 43 | +} |
| 44 | + |
| 45 | +describe('luis:convert', () => { |
| 46 | + it('luis:convert successfully reconstructs a markdown file from a LUIS input file with out of order entity references', async () => { |
| 47 | + await assertToLu('./../../fixtures/testcases/test269-d.json', './../../fixtures/verified/test269-d.lu') |
| 48 | + }) |
| 49 | + |
| 50 | + it('luis:convert successfully reconstructs a markdown file from a LUIS input file', async () => { |
| 51 | + await assertToLu('./../../fixtures/verified/all.json', './../../fixtures/verified/allGen.lu') |
| 52 | + }) |
| 53 | + |
| 54 | + it('luis:convert successfully reconstructs a markdown file from a LUIS input file (phrase list as feature)', async () => { |
| 55 | + await assertToLu('./../../fixtures/verified/plFeatures.json', './../../fixtures/verified/plFeatures.lu') |
| 56 | + }) |
| 57 | + |
| 58 | + it('luis:convert successfully reconstructs a markdown file from a LUIS input file (model as features)', async () => { |
| 59 | + await assertToLu('./../../fixtures/verified/modelAsFeatures.json', './../../fixtures/verified/modelAsFeatureGen.lu') |
| 60 | + }) |
| 61 | + it('luis:convert successfully reconstructs a markdown file from a LUIS input file (with nDepth entity definitions in utterances)', async () => { |
| 62 | + await assertToLu('./../../fixtures/verified/nDepthEntityInUtterance.json', './../../fixtures/verified/nDepthEntityInUtterance.lu') |
| 63 | + }) |
| 64 | + |
| 65 | + it('luis:convert Simple intent and utterances are parsed correctly', async () => { |
| 66 | + await assertToJSON('./../../fixtures/examples/1.lu', './../../fixtures/verified/1.json', '1') |
| 67 | + }) |
| 68 | + |
| 69 | + it('luis:convert Multiple intent and utterance definition sections are parsed correctly', async () => { |
| 70 | + await assertToJSON('./../../fixtures/examples/3.lu', './../../fixtures/verified/3.json', '3') |
| 71 | + }) |
| 72 | + |
| 73 | + it('luis:convert Uttearnces with labelled values are parsed correctly', async () => { |
| 74 | + await assertToJSON('./../../fixtures/examples/4.lu', './../../fixtures/verified/4.json', '4') |
| 75 | + }) |
| 76 | + |
| 77 | + it('luis:convert Simple entity declaration is parsed correctly', async () => { |
| 78 | + await assertToJSON('./../../fixtures/examples/5.lu', './../../fixtures/verified/5.json', '5') |
| 79 | + }) |
| 80 | + |
| 81 | + it('luis:convert Prebuilt entity types are parsed correctly', async () => { |
| 82 | + await assertToJSON('./../../fixtures/examples/6.lu', './../../fixtures/verified/6.json', '6') |
| 83 | + }) |
| 84 | + it('luis:convert Pattern.any entity types are parsed correctly', async () => { |
| 85 | + await assertToJSON('./../../fixtures/examples/7.lu', './../../fixtures/verified/7.json', '7') |
| 86 | + }) |
| 87 | + |
| 88 | + it('luis:convert List entity types are parsed correctly', async () => { |
| 89 | + await assertToJSON('./../../fixtures/examples/9.lu', './../../fixtures/verified/9.json', '9') |
| 90 | + }) |
| 91 | + |
| 92 | + it('luis:convert list entity definitions and intent definitions can be split up and will be parsed correctly', async () => { |
| 93 | + await assertToJSON('./../../fixtures/examples/9a.lu', './../../fixtures/verified/9a.json', '9a') |
| 94 | + }) |
| 95 | + |
| 96 | + it('Parse to LU instance', async () => { |
| 97 | + let luFile = ` |
| 98 | + @ ml test |
| 99 | + # test |
| 100 | + - this is a {@test = one} |
| 101 | + `; |
| 102 | + |
| 103 | + let result = ` |
| 104 | +> LUIS application information |
| 105 | +> !# @app.versionId = 0.1 |
| 106 | +> !# @app.culture = en-us |
| 107 | +> !# @app.luis_schema_version = 3.2.0 |
| 108 | +
|
| 109 | +
|
| 110 | +> # Intent definitions |
| 111 | +
|
| 112 | +## test |
| 113 | +- this is a {@test=one} |
| 114 | +
|
| 115 | +
|
| 116 | +> # Entity definitions |
| 117 | +
|
| 118 | +@ ml test |
| 119 | +
|
| 120 | +
|
| 121 | +> # PREBUILT Entity definitions |
| 122 | +
|
| 123 | +
|
| 124 | +> # Phrase list definitions |
| 125 | +
|
| 126 | +
|
| 127 | +> # List entities |
| 128 | +
|
| 129 | +> # RegEx entities |
| 130 | +
|
| 131 | +
|
| 132 | +` |
| 133 | + const luisObject = await LuisBuilder.fromLUAsync(luFile) |
| 134 | + const newLU = luisObject.parseToLU() |
| 135 | + assert.equal(sanitize(newLU.content), result); |
| 136 | + }); |
| 137 | +}) |
| 138 | +describe('luis:convert version 5 upgrade test', () => { |
| 139 | + it('luis:convert successfully reconstructs a markdown file from a LUIS input file with v5 constructs', async () => { |
| 140 | + await assertToJSON('./../../fixtures/verified/v5UpgradeTest.lu', './../../fixtures/verified/v5Upgrade.json') |
| 141 | + }) |
| 142 | + |
| 143 | + it('luis:convert successfully converts LU with ndepth entity and features to LUIS JSON model', async () => { |
| 144 | + await assertToJSON('./../../fixtures/examples/newEntityWithFeatures.lu', './../../fixtures/verified/newEntityWithFeatures.json') |
| 145 | + }) |
| 146 | + |
| 147 | + it('luis:convert successfully converts LUIS JSON model with nDepth entity and features to LU', async () => { |
| 148 | + await assertToLu('./../../fixtures/verified/newEntityWithFeatures.json', './../../fixtures/verified/newEntityWithFeatures.lu') |
| 149 | + }) |
| 150 | + |
| 151 | + it('luis:convert successfully converts LUIS JSON model with empty intent feature descriptors', async () => { |
| 152 | + await assertToLu('./../../fixtures/testcases/emptyIntentDescriptors.json', './../../fixtures/verified/emptyIntentDescriptors.lu') |
| 153 | + }) |
| 154 | + |
| 155 | + it('luis:convert successfully converts LUIS JSON model with no phrase lists (output must have phraselists if any v6 concepts are present in the .lu file)', async () => { |
| 156 | + await assertToJSON('./../../fixtures/testcases/v6WithoutPhraseLists.lu', './../../fixtures/verified/v6WithoutPhraseLists.json') |
| 157 | + }) |
| 158 | + |
| 159 | + it('luis:convert successfully converts LUIS JSON model with no phrase lists (output must have phraselists if any v6 concepts are present in the .lu file)', async () => { |
| 160 | + await assertToJSON('./../../fixtures/testcases/plWithFlags.lu', './../../fixtures/verified/plWithFlags.json') |
| 161 | + }) |
| 162 | + }) |
| 163 | + |
| 164 | +describe('luis:convert negative tests', () => { |
| 165 | + it('luis:convert should show ERR message when no utterances are found for an intent', (done) => { |
| 166 | + loadLuFile('./../../fixtures/testcases/bad3.lu') |
| 167 | + .then(res => { |
| 168 | + LuisBuilder.fromLUAsync(res) |
| 169 | + .then(res => done(res)) |
| 170 | + .catch(err => { |
| 171 | + assert.isTrue(err.text.includes(`[ERROR] line 4:0 - line 4:16: Invalid intent body line, did you miss \'-\' at line begin`)) |
| 172 | + done() |
| 173 | + }) |
| 174 | + }) |
| 175 | + |
| 176 | + }) |
| 177 | + |
| 178 | + it('luis:convert should show ERR message when no labelled value is found for an entity', (done) => { |
| 179 | + loadLuFile('./../../fixtures/testcases/bad3a.lu') |
| 180 | + .then(res => { |
| 181 | + LuisBuilder.fromLUAsync(res) |
| 182 | + .then(res => done(res)) |
| 183 | + .catch(err => { |
| 184 | + assert.isTrue(err.text.includes(`[ERROR] line 4:0 - line 4:19: No labelled value found for entity: "tomato" in utterance: "- i wangt {tomato=}"`)) |
| 185 | + done() |
| 186 | + }) |
| 187 | + }) |
| 188 | + |
| 189 | + }) |
| 190 | + |
| 191 | + it('luis:convert should show ERR message when no labelled value is found for an entity', (done) => { |
| 192 | + loadLuFile('./../../fixtures/testcases/bad2.lu') |
| 193 | + .then(res => { |
| 194 | + LuisBuilder.fromLUAsync(res) |
| 195 | + .then(res => done(res)) |
| 196 | + .catch(err => { |
| 197 | + assert.isTrue(err.text.includes(`[ERROR] line 1:0 - line 1:1: syntax error: invalid input 'f' detected.`)) |
| 198 | + done() |
| 199 | + }) |
| 200 | + }) |
| 201 | + |
| 202 | + }) |
| 203 | + }) |
| 204 | + |
| 205 | +describe('luis:convert new entity format', () => { |
| 206 | + it('luis:convert with new entity format correctly produces a LU file', async () => { |
| 207 | + assertToLu('./../../fixtures/testcases/newEntity1.json', './../../fixtures/verified/newEntity1.lu') |
| 208 | + }) |
| 209 | + |
| 210 | + it('luis:convert with new entity format and single roles correctly produces a LU file', async () => { |
| 211 | + assertToLu('./../../fixtures/testcases/newEntity1.json', './../../fixtures/verified/newEntity1.lu') |
| 212 | + }) |
| 213 | +}) |
| 214 | + |
| 215 | +describe('luis:convert with pattern.any inherits information', () => { |
| 216 | + it('luis:convert with pattern.any inherits information correctly produces a LUIS app', async () => { |
| 217 | + assertToJSON('./../../fixtures/verified/LUISAppWithPAInherits.lu', './../../fixtures/verified/LUISAppWithPAInherits.lu.json') |
| 218 | + }) |
| 219 | + |
| 220 | + it('luis:convert with pattern.any inherits information correctly produces a LUIS app', async () => { |
| 221 | + assertToLu('./../../fixtures/testcases/LUISAppWithPAInherits.json', './../../fixtures/verified/LUISAppWithPAInherits.lu') |
| 222 | + }) |
| 223 | +}) |
| 224 | + |
0 commit comments