Skip to content

Commit 8df1caa

Browse files
authored
Add locale support in DirectLine options (#293)
* add locale userid and username support * change to locale support only * remove unused parameters * change locale to conversationStartLocale * change to conversation start properties JSON * change the test bot endpoint and add locale tests * fixed comments
1 parent 973de3b commit 8df1caa

7 files changed

Lines changed: 159 additions & 10 deletions
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import 'dotenv/config';
2+
3+
import onErrorResumeNext from 'on-error-resume-next';
4+
5+
import { timeouts } from './constants.json';
6+
import * as createDirectLine from './setup/createDirectLine';
7+
import waitForBotToRespond from './setup/waitForBotToRespond';
8+
9+
describe('Happy path', () => {
10+
let unsubscribes;
11+
12+
beforeEach(() => unsubscribes = []);
13+
afterEach(() => unsubscribes.forEach(fn => onErrorResumeNext(fn)));
14+
15+
describe('should receive the welcome message from bot in English', () => {
16+
let directLine;
17+
18+
describe('using REST', () => {
19+
beforeEach(() => jest.setTimeout(timeouts.rest));
20+
21+
test('without conversation start properties', async () => {
22+
directLine = await createDirectLine.forREST({ token: true });
23+
});
24+
25+
test('without locale in conversation start properties', async () => {
26+
directLine = await createDirectLine.forREST({ token: true }, { conversationStartProperties: {} });
27+
});
28+
29+
test('with locale "en-US" in conversation start properties', async () => {
30+
directLine = await createDirectLine.forREST({ token: true }, { conversationStartProperties: { locale: 'en-US' } });
31+
});
32+
});
33+
34+
describe('using Web Socket', () => {
35+
beforeEach(() => jest.setTimeout(timeouts.webSocket));
36+
37+
test('without conversation start properties', async () => {
38+
directLine = await createDirectLine.forWebSocket({ token: true });
39+
});
40+
41+
test('without locale in conversation start properties', async () => {
42+
directLine = await createDirectLine.forWebSocket({ token: true }, { conversationStartProperties: {} });
43+
});
44+
45+
test('with locale "en-US" in conversation start properties', async () => {
46+
directLine = await createDirectLine.forWebSocket({ token: true }, { conversationStartProperties: { locale: 'en-US' } });
47+
});
48+
});
49+
50+
afterEach(async () => {
51+
// If directLine object is undefined, that means the test is failing.
52+
if (!directLine) { return; }
53+
54+
unsubscribes.push(directLine.end.bind(directLine));
55+
56+
await waitForBotToRespond(directLine, ({ text }) => text === 'Welcome');
57+
});
58+
});
59+
60+
describe('should receive the welcome message from bot in Chinese', () => {
61+
let directLine;
62+
63+
describe('using REST', () => {
64+
beforeEach(() => jest.setTimeout(timeouts.rest));
65+
66+
test('with locale "zh-CN" in conversation start properties', async () => {
67+
directLine = await createDirectLine.forREST({ token: true }, { conversationStartProperties: { locale: 'zh-CN' } });
68+
});
69+
});
70+
71+
describe('using Web Socket', () => {
72+
beforeEach(() => jest.setTimeout(timeouts.webSocket));
73+
74+
test('with locale "zh-CN" in conversation start properties', async () => {
75+
directLine = await createDirectLine.forWebSocket({ token: true }, { conversationStartProperties: { locale: 'zh-CN' } });
76+
});
77+
});
78+
79+
afterEach(async () => {
80+
// If directLine object is undefined, that means the test is failing.
81+
if (!directLine) { return; }
82+
83+
unsubscribes.push(directLine.end.bind(directLine));
84+
85+
await waitForBotToRespond(directLine, ({ text }) => text === '欢迎');
86+
});
87+
});
88+
});

__tests__/happy.receiveAttachmentStreams.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ describe('Happy path', () => {
3131
unsubscribes.push(directLine.end.bind(directLine));
3232
unsubscribes.push(await waitForConnected(directLine));
3333

34-
let url1 = 'http://myasebot.azurewebsites.net/177KB.jpg';
35-
let url2 = 'http://myasebot.azurewebsites.net/100KB.jpg';
34+
let url1 = 'http://dljstestbot.azurewebsites.net/177KB.jpg';
35+
let url2 = 'http://dljstestbot.azurewebsites.net/100KB.jpg';
3636

3737
const activityFromUser = {
3838
text: 'attach ' + url1 + ' ' + url2,

__tests__/happy.uploadAttachmentStreams.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ describe('Happy path', () => {
3434
// DirectLine.postActivityWithAttachments support "contentUrl" only but not "content"
3535
attachments: [{
3636
contentType: 'image/jpg',
37-
contentUrl: 'http://myasebot.azurewebsites.net/177KB.jpg'
37+
contentUrl: 'http://dljstestbot.azurewebsites.net/177KB.jpg'
3838
}, {
3939
contentType: 'image/jpg',
40-
contentUrl: 'http://myasebot.azurewebsites.net/100KB.jpg'
40+
contentUrl: 'http://dljstestbot.azurewebsites.net/100KB.jpg'
4141
}],
4242
text: 'Hello, World!',
4343
type: 'message',

__tests__/happy.uploadAttachments.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ describe('Happy path', () => {
5353
// DirectLine.postActivityWithAttachments support "contentUrl" only but not "content"
5454
attachments: [{
5555
contentType: 'image/jpg',
56-
contentUrl: 'http://myasebot.azurewebsites.net/177KB.jpg',
56+
contentUrl: 'http://dljstestbot.azurewebsites.net/177KB.jpg',
5757
thumbnailUrl: 'data:image/png;base64,===177KB.jpg'
5858
}, {
5959
contentType: 'image/png',
60-
contentUrl: 'http://myasebot.azurewebsites.net/100KB.jpg',
60+
contentUrl: 'http://dljstestbot.azurewebsites.net/100KB.jpg',
6161
thumbnailUrl: 'data:image/png;base64,===100KB.jpb'
6262
}],
6363
text: 'Hello, World!',

__tests__/setup/createDirectLine.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import { DirectLineStreaming } from '../../src/directLineStreaming';
66

77
const {
88
DIRECT_LINE_SECRET,
9-
STREAMING_EXTENSIONS_DOMAIN = 'https://myasebot.azurewebsites.net/.bot/v3/directline'
9+
STREAMING_EXTENSIONS_DOMAIN = 'https://dljstestbot.azurewebsites.net/.bot/v3/directline'
1010
} = process.env;
1111

1212
const DEFAULT_DOMAIN = 'https://directline.botframework.com/v3/directline';
1313

1414
async function fetchDirectLineToken() {
15-
const res = await fetch('https://myasebot.azurewebsites.net/token/directline');
15+
const res = await fetch('https://dljstestbot.azurewebsites.net/token/directline');
1616

1717
if (res.ok) {
1818
return await res.json();
@@ -22,7 +22,7 @@ async function fetchDirectLineToken() {
2222
}
2323

2424
async function fetchDirectLineStreamingExtensionsToken() {
25-
const res = await fetch(`https://myasebot.azurewebsites.net/token/directlinease`);
25+
const res = await fetch(`https://dljstestbot.azurewebsites.net/token/directlinease`);
2626

2727
if (res.ok) {
2828
return await res.json();
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import 'dotenv/config';
2+
3+
import onErrorResumeNext from 'on-error-resume-next';
4+
5+
import { timeouts } from './constants.json';
6+
import * as createDirectLine from './setup/createDirectLine';
7+
import waitForBotToRespond from './setup/waitForBotToRespond';
8+
9+
describe('Unhappy path', () => {
10+
let unsubscribes;
11+
12+
beforeEach(() => unsubscribes = []);
13+
afterEach(() => unsubscribes.forEach(fn => onErrorResumeNext(fn)));
14+
15+
describe('should receive the welcome message from bot in English', () => {
16+
let directLine;
17+
18+
describe('using REST', () => {
19+
beforeEach(() => jest.setTimeout(timeouts.rest));
20+
21+
test('with invalid locale in conversation start properties', async () => {
22+
directLine = await createDirectLine.forREST({ token: true }, { conversationStartProperties: { locale: { x: 'test' } } });
23+
});
24+
});
25+
26+
describe('using Web Socket', () => {
27+
beforeEach(() => jest.setTimeout(timeouts.webSocket));
28+
29+
test('with invalid locale in conversation start properties', async () => {
30+
directLine = await createDirectLine.forWebSocket({ token: true }, { conversationStartProperties: { locale: { x: 'test' } } });
31+
});
32+
});
33+
34+
afterEach(async () => {
35+
// If directLine object is undefined, that means the test is failing.
36+
if (!directLine) { return; }
37+
38+
unsubscribes.push(directLine.end.bind(directLine));
39+
40+
await waitForBotToRespond(directLine, ({ text }) => text === 'Welcome');
41+
});
42+
});
43+
});

src/directLine.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ export interface DirectLineOptions {
370370
streamUrl?: string,
371371
timeout?: number,
372372
// Attached to all requests to identify requesting agent.
373-
botAgent?: string
373+
botAgent?: string,
374+
conversationStartProperties?: any
374375
}
375376

376377
export interface Services {
@@ -469,6 +470,8 @@ export class DirectLine implements IBotConnection {
469470
private timeout = 20 * 1000;
470471
private retries: number;
471472

473+
private localeOnStartConversation: string;
474+
472475
private pollingInterval: number = 1000; //ms
473476

474477
private tokenRefreshSubscription: Subscription;
@@ -478,6 +481,14 @@ export class DirectLine implements IBotConnection {
478481
this.token = options.secret || options.token;
479482
this.webSocket = (options.webSocket === undefined ? true : options.webSocket) && typeof WebSocket !== 'undefined' && WebSocket !== undefined;
480483

484+
if (options.conversationStartProperties && options.conversationStartProperties.locale) {
485+
if (Object.prototype.toString.call(options.conversationStartProperties.locale) === '[object String]') {
486+
this.localeOnStartConversation = options.conversationStartProperties.locale;
487+
} else {
488+
console.warn('DirectLineJS: conversationStartProperties.locale was ignored: the locale name may be a BCP 47 language tag');
489+
}
490+
}
491+
481492
if (options.domain) {
482493
this.domain = options.domain;
483494
}
@@ -616,12 +627,19 @@ export class DirectLine implements IBotConnection {
616627
? `${this.domain}/conversations/${this.conversationId}?watermark=${this.watermark}`
617628
: `${this.domain}/conversations`;
618629
const method = this.conversationId ? "GET" : "POST";
630+
const body = this.conversationId
631+
? undefined
632+
: {
633+
locale: this.localeOnStartConversation
634+
};
619635
return this.services.ajax({
620636
method,
621637
url,
638+
body,
622639
timeout: this.timeout,
623640
headers: {
624641
"Accept": "application/json",
642+
"Content-Type": "application/json",
625643
...this.commonHeaders()
626644
}
627645
})

0 commit comments

Comments
 (0)