Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: extract build logic from components page #4153

Merged
merged 11 commits into from
Sep 24, 2020
93 changes: 93 additions & 0 deletions Composer/packages/client/__tests__/utils/buildUtil.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { DialogInfo, LuFile } from '@bfc/shared';

import { createCrossTrainConfig } from '../../src/utils/buildUtil';

describe('createCrossTrainConfig', () => {
it('should create crosstrain config', () => {
const dialogs = [
{
id: 'main',
luFile: 'main',
isRoot: true,
intentTriggers: [
{ intent: 'dia1_trigger', dialogs: ['dia1'] },
{ intent: 'dia2_trigger', dialogs: ['dia2'] },
{ intent: 'dias_trigger', dialogs: ['dia5', 'dia6'] },
{ intent: 'no_dialog', dialogs: [] },
{ intent: '', dialogs: ['start_dialog_without_intent'] },
],
},
{
id: 'dia1',
luFile: 'dia1',
intentTriggers: [
{ intent: 'dia3_trigger', dialogs: ['dia3'] },
{ intent: 'dia4_trigger', dialogs: ['dia4'] },
],
},
{
id: 'dia2',
luFile: 'dia2',
intentTriggers: [],
},
{
id: 'dia3',
luFile: 'dia3',
intentTriggers: [],
},
{
id: 'dia4',
luFile: 'dia4',
intentTriggers: [],
},
{
id: 'dia5',
luFile: 'dia5',
intentTriggers: [],
},
{
id: 'dia6',
luFile: 'dia6',
intentTriggers: [],
},
{
id: 'start_dialog_without_intent',
luFile: 'start_dialog_without_intent',
intentTriggers: [],
},
{
id: 'dialog_without_lu',
intentTriggers: [],
},
];
const luFiles = [
{
id: 'main.en-us',
intents: [
{ Name: 'dia1_trigger' },
{ Name: 'dia2_trigger' },
{ Name: 'dias_trigger' },
{ Name: 'no_dialog' },
{ Name: 'dialog_without_lu' },
],
},
{ id: 'dia1.en-us', intents: [{ Name: 'dia3_trigger' }, { Name: 'dia4_trigger' }] },
{ id: 'dia2.en-us' },
{ id: 'dia3.en-us' },
{ id: 'dia5.en-us' },
{ id: 'dia6.en-us' },
];
const config = createCrossTrainConfig(dialogs as DialogInfo[], luFiles as LuFile[]);
expect(config.rootIds.length).toEqual(1);
expect(config.rootIds[0]).toEqual('main.en-us.lu');
expect(config.triggerRules['main.en-us.lu'].dia1_trigger).toEqual('dia1.en-us.lu');
expect(config.triggerRules['main.en-us.lu'].no_dialog).toEqual('');
expect(config.triggerRules['main.en-us.lu'].dia1_trigger).toEqual('dia1.en-us.lu');
expect(config.triggerRules['main.en-us.lu'].dias_trigger.length).toBe(2);
expect(config.triggerRules['dia1.en-us.lu'].dia3_trigger).toEqual('dia3.en-us.lu');
expect(config.triggerRules['dia1.en-us.lu']['dia4.en-us.lu']).toBeUndefined();
});
});
87 changes: 1 addition & 86 deletions Composer/packages/client/__tests__/utils/luUtil.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { LuFile, DialogInfo, Diagnostic, DiagnosticSeverity } from '@bfc/shared';

import { getReferredLuFiles, createCrossTrainConfig, checkLuisBuild } from '../../src/utils/luUtil';
import { getReferredLuFiles, checkLuisBuild } from '../../src/utils/luUtil';

describe('getReferredLuFiles', () => {
it('returns referred luFiles from dialog', () => {
Expand All @@ -13,91 +13,6 @@ describe('getReferredLuFiles', () => {
expect(referred.length).toEqual(1);
expect(referred[0].id).toEqual('a.en-us');
});

it('should create crosstrain config', () => {
const dialogs = [
{
id: 'main',
luFile: 'main',
isRoot: true,
intentTriggers: [
{ intent: 'dia1_trigger', dialogs: ['dia1'] },
{ intent: 'dia2_trigger', dialogs: ['dia2'] },
{ intent: 'dias_trigger', dialogs: ['dia5', 'dia6'] },
{ intent: 'no_dialog', dialogs: [] },
{ intent: '', dialogs: ['start_dialog_without_intent'] },
],
},
{
id: 'dia1',
luFile: 'dia1',
intentTriggers: [
{ intent: 'dia3_trigger', dialogs: ['dia3'] },
{ intent: 'dia4_trigger', dialogs: ['dia4'] },
],
},
{
id: 'dia2',
luFile: 'dia2',
intentTriggers: [],
},
{
id: 'dia3',
luFile: 'dia3',
intentTriggers: [],
},
{
id: 'dia4',
luFile: 'dia4',
intentTriggers: [],
},
{
id: 'dia5',
luFile: 'dia5',
intentTriggers: [],
},
{
id: 'dia6',
luFile: 'dia6',
intentTriggers: [],
},
{
id: 'start_dialog_without_intent',
luFile: 'start_dialog_without_intent',
intentTriggers: [],
},
{
id: 'dialog_without_lu',
intentTriggers: [],
},
];
const luFiles = [
{
id: 'main.en-us',
intents: [
{ Name: 'dia1_trigger' },
{ Name: 'dia2_trigger' },
{ Name: 'dias_trigger' },
{ Name: 'no_dialog' },
{ Name: 'dialog_without_lu' },
],
},
{ id: 'dia1.en-us', intents: [{ Name: 'dia3_trigger' }, { Name: 'dia4_trigger' }] },
{ id: 'dia2.en-us' },
{ id: 'dia3.en-us' },
{ id: 'dia5.en-us' },
{ id: 'dia6.en-us' },
];
const config = createCrossTrainConfig(dialogs as DialogInfo[], luFiles as LuFile[]);
expect(config.rootIds.length).toEqual(1);
expect(config.rootIds[0]).toEqual('main.en-us.lu');
expect(config.triggerRules['main.en-us.lu'].dia1_trigger).toEqual('dia1.en-us.lu');
expect(config.triggerRules['main.en-us.lu'].no_dialog).toEqual('');
expect(config.triggerRules['main.en-us.lu'].dia1_trigger).toEqual('dia1.en-us.lu');
expect(config.triggerRules['main.en-us.lu'].dias_trigger.length).toBe(2);
expect(config.triggerRules['dia1.en-us.lu'].dia3_trigger).toEqual('dia3.en-us.lu');
expect(config.triggerRules['dia1.en-us.lu']['dia4.en-us.lu']).toBeUndefined();
});
});

it('check the lu files before publish', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ import {
botLoadErrorState,
} from '../../recoilModel';
import settingsStorage from '../../utils/dialogSettingStorage';
import { QnaConfig, BotStatus, LuisConfig } from '../../constants';
import { BotStatus } from '../../constants';
import { isAbsHosted } from '../../utils/envUtil';
import useNotifications from '../../pages/notifications/useNotifications';
import { navigateTo, openInEmulator } from '../../utils/navigation';
import { getReferredQnaFiles } from '../../utils/qnaUtil';

import { getReferredLuFiles } from './../../utils/luUtil';
import { isBuildConfigComplete, needsBuild } from './../../utils/buildUtil';
import { PublishDialog } from './publishDialog';
import { ErrorCallout } from './errorCallout';
import { EmulatorOpenButton } from './emulatorOpenButton';
Expand Down Expand Up @@ -153,15 +152,14 @@ export const TestController: React.FC<{ projectId: string }> = (props) => {
}
}

async function handlePublish(config: IPublishConfig) {
async function handleBuild(config: IPublishConfig) {
setBotStatus(BotStatus.publishing, projectId);
dismissDialog();
const { luis, qna } = config;
const endpointKey = settings.qna?.endpointKey;
await setSettings(projectId, {
...settings,
luis: luis,
qna: Object.assign({}, settings.qna, qna, { endpointKey }),
qna: Object.assign({}, settings.qna, qna),
});
await build(luis, qna, projectId);
}
Expand All @@ -175,48 +173,24 @@ export const TestController: React.FC<{ projectId: string }> = (props) => {
await publishToTarget(projectId, defaultPublishConfig, { comment: '' }, sensitiveSettings);
}

function isConfigComplete(config) {
let complete = true;
if (getReferredLuFiles(luFiles, dialogs).length > 0) {
if (Object.values(LuisConfig).some((luisConfigKey) => config.luis[luisConfigKey] === '')) {
complete = false;
}
}
if (getReferredQnaFiles(qnaFiles, dialogs).length > 0) {
if (Object.values(QnaConfig).some((qnaConfigKey) => config.qna[qnaConfigKey] === '')) {
complete = false;
}
}
return complete;
}

// return true if dialogs have one with default recognizer.
function needsPublish(dialogs) {
let isDefaultRecognizer = false;
if (dialogs.some((dialog) => typeof dialog.content.recognizer === 'string')) {
isDefaultRecognizer = true;
}
return isDefaultRecognizer;
}

async function handleStart() {
dismissCallout();
const config = Object.assign(
{},
{
luis: settings.luis,
qna: {
subscriptionKey: settings.qna?.subscriptionKey,
qnaRegion: settings.qna?.qnaRegion,
endpointKey: settings.qna?.endpointKey,
},
qna: settings.qna,
}
);
if (!isAbsHosted() && needsPublish(dialogs)) {
if (botStatus === BotStatus.failed || botStatus === BotStatus.pending || !isConfigComplete(config)) {
if (!isAbsHosted() && needsBuild(dialogs)) {
if (
botStatus === BotStatus.failed ||
botStatus === BotStatus.pending ||
!isBuildConfigComplete(config, dialogs, luFiles, qnaFiles)
) {
openDialog();
} else {
await handlePublish(config);
await handleBuild(config);
}
} else {
await handleLoadBot();
Expand Down Expand Up @@ -278,7 +252,7 @@ export const TestController: React.FC<{ projectId: string }> = (props) => {
isOpen={modalOpen}
projectId={projectId}
onDismiss={dismissDialog}
onPublish={handlePublish}
onPublish={handleBuild}
/>
)}
</Fragment>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useRecoilCallback, CallbackInterface } from 'recoil';
import { ILuisConfig, IQnAConfig } from '@bfc/shared';

import * as luUtil from '../../utils/luUtil';
import * as buildUtil from '../../utils/buildUtil';
import { Text, BotStatus } from '../../constants';
import httpClient from '../../utils/httpUtil';
import luFileStatusStorage from '../../utils/luFileStatusStorage';
Expand Down Expand Up @@ -48,7 +49,7 @@ export const builderDispatcher = () => {
}
try {
//TODO crosstrain should add locale
const crossTrainConfig = luUtil.createCrossTrainConfig(dialogs, referredLuFiles);
const crossTrainConfig = buildUtil.createCrossTrainConfig(dialogs, referredLuFiles);
await httpClient.post(`/projects/${projectId}/build`, {
luisConfig,
qnaConfig,
Expand Down
Loading