Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions __tests__/happy.localeOnStartConversation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import 'dotenv/config';

import onErrorResumeNext from 'on-error-resume-next';

import { timeouts } from './constants.json';
import * as createDirectLine from './setup/createDirectLine';
import waitForBotToRespond from './setup/waitForBotToRespond';

describe('Happy path', () => {
let unsubscribes;

beforeEach(() => unsubscribes = []);
afterEach(() => unsubscribes.forEach(fn => onErrorResumeNext(fn)));

describe('should receive the welcome message from bot in English', () => {
let directLine;

describe('using REST', () => {
beforeEach(() => jest.setTimeout(timeouts.rest));

test('without conversation start properties', async () => {
directLine = await createDirectLine.forREST({ token: true });
});

test('without locale in conversation start properties', async () => {
directLine = await createDirectLine.forREST({ token: true }, { conversationStartProperties: {} });
});

test('with locale "en-US" in conversation start properties', async () => {
directLine = await createDirectLine.forREST({ token: true }, { conversationStartProperties: { locale: 'en-US' } });
});
});

describe('using Web Socket', () => {
beforeEach(() => jest.setTimeout(timeouts.webSocket));

test('without conversation start properties', async () => {
directLine = await createDirectLine.forWebSocket({ token: true });
});

test('without locale in conversation start properties', async () => {
directLine = await createDirectLine.forWebSocket({ token: true }, { conversationStartProperties: {} });
});

test('with locale "en-US" in conversation start properties', async () => {
directLine = await createDirectLine.forWebSocket({ token: true }, { conversationStartProperties: { locale: 'en-US' } });
});
});

afterEach(async () => {
// If directLine object is undefined, that means the test is failing.
if (!directLine) { return; }

unsubscribes.push(directLine.end.bind(directLine));

await waitForBotToRespond(directLine, ({ text }) => text === 'Welcome');
});
});

describe('should receive the welcome message from bot in Chinese', () => {
let directLine;

describe('using REST', () => {
beforeEach(() => jest.setTimeout(timeouts.rest));

test('with locale "zh-CN" in conversation start properties', async () => {
directLine = await createDirectLine.forREST({ token: true }, { conversationStartProperties: { locale: 'zh-CN' } });
});
});

describe('using Web Socket', () => {
beforeEach(() => jest.setTimeout(timeouts.webSocket));

test('with locale "zh-CN" in conversation start properties', async () => {
directLine = await createDirectLine.forWebSocket({ token: true }, { conversationStartProperties: { locale: 'zh-CN' } });
});
});

afterEach(async () => {
// If directLine object is undefined, that means the test is failing.
if (!directLine) { return; }

unsubscribes.push(directLine.end.bind(directLine));

await waitForBotToRespond(directLine, ({ text }) => text === '欢迎');
});
});
});
4 changes: 2 additions & 2 deletions __tests__/happy.receiveAttachmentStreams.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ describe('Happy path', () => {
unsubscribes.push(directLine.end.bind(directLine));
unsubscribes.push(await waitForConnected(directLine));

let url1 = 'http://myasebot.azurewebsites.net/177KB.jpg';
let url2 = 'http://myasebot.azurewebsites.net/100KB.jpg';
let url1 = 'http://dljstestbot.azurewebsites.net/177KB.jpg';
let url2 = 'http://dljstestbot.azurewebsites.net/100KB.jpg';

const activityFromUser = {
text: 'attach ' + url1 + ' ' + url2,
Expand Down
4 changes: 2 additions & 2 deletions __tests__/happy.uploadAttachmentStreams.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ describe('Happy path', () => {
// DirectLine.postActivityWithAttachments support "contentUrl" only but not "content"
attachments: [{
contentType: 'image/jpg',
contentUrl: 'http://myasebot.azurewebsites.net/177KB.jpg'
contentUrl: 'http://dljstestbot.azurewebsites.net/177KB.jpg'
}, {
contentType: 'image/jpg',
contentUrl: 'http://myasebot.azurewebsites.net/100KB.jpg'
contentUrl: 'http://dljstestbot.azurewebsites.net/100KB.jpg'
}],
text: 'Hello, World!',
type: 'message',
Expand Down
4 changes: 2 additions & 2 deletions __tests__/happy.uploadAttachments.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ describe('Happy path', () => {
// DirectLine.postActivityWithAttachments support "contentUrl" only but not "content"
attachments: [{
contentType: 'image/jpg',
contentUrl: 'http://myasebot.azurewebsites.net/177KB.jpg',
contentUrl: 'http://dljstestbot.azurewebsites.net/177KB.jpg',
thumbnailUrl: 'data:image/png;base64,===177KB.jpg'
}, {
contentType: 'image/png',
contentUrl: 'http://myasebot.azurewebsites.net/100KB.jpg',
contentUrl: 'http://dljstestbot.azurewebsites.net/100KB.jpg',
thumbnailUrl: 'data:image/png;base64,===100KB.jpb'
}],
text: 'Hello, World!',
Expand Down
6 changes: 3 additions & 3 deletions __tests__/setup/createDirectLine.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import { DirectLineStreaming } from '../../src/directLineStreaming';

const {
DIRECT_LINE_SECRET,
STREAMING_EXTENSIONS_DOMAIN = 'https://myasebot.azurewebsites.net/.bot/v3/directline'
STREAMING_EXTENSIONS_DOMAIN = 'https://dljstestbot.azurewebsites.net/.bot/v3/directline'
} = process.env;

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

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

if (res.ok) {
return await res.json();
Expand All @@ -22,7 +22,7 @@ async function fetchDirectLineToken() {
}

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

if (res.ok) {
return await res.json();
Expand Down
43 changes: 43 additions & 0 deletions __tests__/unhappy.invalidLocaleOnStartConversation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'dotenv/config';

import onErrorResumeNext from 'on-error-resume-next';

import { timeouts } from './constants.json';
import * as createDirectLine from './setup/createDirectLine';
import waitForBotToRespond from './setup/waitForBotToRespond';

describe('Unhappy path', () => {
let unsubscribes;

beforeEach(() => unsubscribes = []);
afterEach(() => unsubscribes.forEach(fn => onErrorResumeNext(fn)));

describe('should receive the welcome message from bot in English', () => {
let directLine;

describe('using REST', () => {
beforeEach(() => jest.setTimeout(timeouts.rest));

test('with invalid locale in conversation start properties', async () => {
directLine = await createDirectLine.forREST({ token: true }, { conversationStartProperties: { locale: { x: 'test' } } });
});
});

describe('using Web Socket', () => {
beforeEach(() => jest.setTimeout(timeouts.webSocket));

test('with invalid locale in conversation start properties', async () => {
directLine = await createDirectLine.forWebSocket({ token: true }, { conversationStartProperties: { locale: { x: 'test' } } });
});
});

afterEach(async () => {
// If directLine object is undefined, that means the test is failing.
if (!directLine) { return; }

unsubscribes.push(directLine.end.bind(directLine));

await waitForBotToRespond(directLine, ({ text }) => text === 'Welcome');
});
});
});
20 changes: 19 additions & 1 deletion src/directLine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,8 @@ export interface DirectLineOptions {
streamUrl?: string,
timeout?: number,
// Attached to all requests to identify requesting agent.
botAgent?: string
botAgent?: string,
conversationStartProperties?: any
}

export interface Services {
Expand Down Expand Up @@ -469,6 +470,8 @@ export class DirectLine implements IBotConnection {
private timeout = 20 * 1000;
private retries: number;

private localeOnStartConversation: string;

private pollingInterval: number = 1000; //ms

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

if (options.conversationStartProperties && options.conversationStartProperties.locale) {
if (Object.prototype.toString.call(options.conversationStartProperties.locale) === '[object String]') {
this.localeOnStartConversation = options.conversationStartProperties.locale;
} else {
console.warn('DirectLineJS: conversationStartProperties.locale was ignored: the locale name may be a BCP 47 language tag');
}
}

if (options.domain) {
this.domain = options.domain;
}
Expand Down Expand Up @@ -616,12 +627,19 @@ export class DirectLine implements IBotConnection {
? `${this.domain}/conversations/${this.conversationId}?watermark=${this.watermark}`
: `${this.domain}/conversations`;
const method = this.conversationId ? "GET" : "POST";
const body = this.conversationId
? undefined
: {
locale: this.localeOnStartConversation

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if conversationStartProperties is not sent in or does not contain a locale, should we still send a body? I would assume not since we dont want to change any existing client.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In our backend, we are reading from body to get the conversationStartParameters. Because we are not only sending locale in body, we would send more parameters (like userid, username, etc) in the future. The locale parameter is optional, it would not affect any existing client.

};
return this.services.ajax({
method,
url,
body,
timeout: this.timeout,
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
Copy link

@p-nagpal p-nagpal Jul 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test to make sure adding a Content-Type doesnt affect existing clients that dont send a body.

...this.commonHeaders()
}
})
Expand Down