From 4bff8e5e14bd717ea23c55e1c7bc5d3d6c72baad Mon Sep 17 00:00:00 2001 From: Fei Chen Date: Fri, 27 Nov 2020 15:06:26 +0800 Subject: [PATCH] support output to file for kb:export command --- packages/cli/README.md | 2 + packages/qnamaker/README.md | 2 + .../src/commands/qnamaker/kb/export.ts | 37 +++++++++++++--- .../test/commands/qnamaker/kb/export.test.ts | 42 +++++++++++++++++++ .../fixtures/verified/exportSpecialChars.qna | 6 +++ 5 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 packages/qnamaker/test/fixtures/verified/exportSpecialChars.qna diff --git a/packages/cli/README.md b/packages/cli/README.md index c814a140e..d13330c6e 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -1617,7 +1617,9 @@ USAGE $ bf qnamaker:kb:export OPTIONS + -f, --force [default: false] If --out flag is provided with the path to an existing file, overwrites that file. -h, --help qnamaker:kb:export command help + -o, --out Output file path. If not specified stdout will be used as output. --endpoint=endpoint Overrides public endpoint https://westus.api.cognitive.microsoft.com/qnamaker/v4.0/ --environment=environment [default: Prod] Specifies whether environment is Test or Prod. diff --git a/packages/qnamaker/README.md b/packages/qnamaker/README.md index 01e909a9b..a92a92dc6 100644 --- a/packages/qnamaker/README.md +++ b/packages/qnamaker/README.md @@ -400,7 +400,9 @@ USAGE $ bf qnamaker:kb:export OPTIONS + -f, --force [default: false] If --out flag is provided with the path to an existing file, overwrites that file. -h, --help qnamaker:kb:export command help + -o, --out Output file path. If not specified stdout will be used as output. --endpoint=endpoint Overrides public endpoint https://westus.api.cognitive.microsoft.com/qnamaker/v4.0/ --environment=environment [default: Prod] Specifies whether environment is Test or Prod. diff --git a/packages/qnamaker/src/commands/qnamaker/kb/export.ts b/packages/qnamaker/src/commands/qnamaker/kb/export.ts index 2651806c7..37bd10051 100644 --- a/packages/qnamaker/src/commands/qnamaker/kb/export.ts +++ b/packages/qnamaker/src/commands/qnamaker/kb/export.ts @@ -3,10 +3,12 @@ * Licensed under the MIT License. */ -import {CLIError, Command, flags} from '@microsoft/bf-cli-command' +import {CLIError, Command, flags, utils} from '@microsoft/bf-cli-command' +import {Inputs, processInputs} from '../../../utils/qnamakerbase' +const fs = require('fs-extra') +const path = require('path') const qnamaker = require('./../../../../utils/index') const exportKbJSON = require('./../../../../utils/payloads/exportkb') -import {Inputs, processInputs} from '../../../utils/qnamakerbase' export default class QnamakerKbExport extends Command { static description = 'Echos a knowledgebase in json or qna format to stdout' @@ -17,6 +19,8 @@ export default class QnamakerKbExport extends Command { environment: flags.string({description: 'Specifies whether environment is Test or Prod.', default: 'Prod'}), subscriptionKey: flags.string({description: 'Specifies the qnamaker Ocp-Apim-Subscription Key (found in Keys under Resource Management section for your Qna Maker cognitive service). Overrides the subscriptionkey value present in the config'}), endpoint: flags.string({description: 'Overrides public endpoint https://westus.api.cognitive.microsoft.com/qnamaker/v4.0/'}), + out: flags.string({char: 'o', description: 'Output file path. If not specified stdout will be used as output.'}), + force: flags.boolean({char: 'f', description: 'If --out flag is provided with the path to an existing file, overwrites that file.', default: false}), help: flags.help({char: 'h', description: 'qnamaker:kb:export command help'}), } @@ -24,14 +28,35 @@ export default class QnamakerKbExport extends Command { const {flags} = this.parse(QnamakerKbExport) let input: Inputs = await processInputs(flags, exportKbJSON, this.config.configDir) - const result = await qnamaker(input.config, input.serviceManifest, flags, input.requestBody) + let result = await qnamaker(input.config, input.serviceManifest, flags, input.requestBody) if (result.error) { throw new CLIError(JSON.stringify(result.error, null, 4)) } else { - if (typeof result === 'string') + if (typeof result !== 'string') { + result = JSON.stringify(result, null, 2) + } + + if (flags.out) { + await this.writeOutput(result, flags) + } else { this.log(result) - else - this.log(JSON.stringify(result, null, 2)) + } + } + } + + async writeOutput(result: any, flags: any) { + let fullPath = path.resolve(flags.out) + let root = path.dirname(fullPath) + if (!fs.existsSync(root)) { + fs.mkdirSync(root) + } + + const validatedPath = utils.validatePath(fullPath, '', flags.force) + + try { + await fs.writeFile(validatedPath, result, 'utf-8') + } catch (error) { + throw new CLIError('Unable to write file - ' + validatedPath + ' Error: ' + error.message) } } } diff --git a/packages/qnamaker/test/commands/qnamaker/kb/export.test.ts b/packages/qnamaker/test/commands/qnamaker/kb/export.test.ts index 6e2823b7b..d7ceb59a0 100644 --- a/packages/qnamaker/test/commands/qnamaker/kb/export.test.ts +++ b/packages/qnamaker/test/commands/qnamaker/kb/export.test.ts @@ -1,8 +1,18 @@ import {expect, test} from '@oclif/test' +const fs = require('fs-extra') +const path = require('path') import {deleteTestConfigFile, initTestConfigFile} from '../../../configfilehelper' const nock = require('nock') +const compareQnaFiles = 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") + return result === fixtureFile +} + describe('qnamaker:kb:export', () => { before(async function () { await initTestConfigFile() @@ -82,3 +92,35 @@ describe('[qnaformat] qnamaker:kb:export', () => { }) }) +describe('[qnaformat] qnamaker:kb:export to qna file', () => { + before(async function () { + await initTestConfigFile() + // runs before all tests in this block + nock('https://westus.api.cognitive.microsoft.com/qnamaker/v4.0') + .get('/knowledgebases/5690998c-4438-4ae1-900a-88a2aa3bfa68/Test/qna?qnaformat=true') + .reply(200, + `# ? Hello +- Plus d'information sur la lettre reçu des éléctions? + +\`\`\` +Plus d'information sur la lettre reçu des éléctions +\`\`\``) + }) + + after(async function () { + await deleteTestConfigFile() + await fs.remove(path.join(__dirname, './../../../../exportSpecialChars.qna')) + }) + + test + .stdout() + .command(['qnamaker:kb:export', + '--kbId', '5690998c-4438-4ae1-900a-88a2aa3bfa68', + '--environment', 'Test', + '--qnaFormat', + '--out', 'exportSpecialChars.qna']) + .it('Exports kb to qna file', async () => { + expect(await compareQnaFiles('./../../../../exportSpecialChars.qna', './../../../fixtures/verified/exportSpecialChars.qna')).to.be.true + nock.cleanAll() + }) +}) diff --git a/packages/qnamaker/test/fixtures/verified/exportSpecialChars.qna b/packages/qnamaker/test/fixtures/verified/exportSpecialChars.qna new file mode 100644 index 000000000..392f21c92 --- /dev/null +++ b/packages/qnamaker/test/fixtures/verified/exportSpecialChars.qna @@ -0,0 +1,6 @@ +# ? Hello +- Plus d'information sur la lettre reçu des éléctions? + +``` +Plus d'information sur la lettre reçu des éléctions +``` \ No newline at end of file