Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const request: WebResource = new WebResource().prepare(requestOptions);
MicrosoftAppCredentials.trustServiceUrl(this.skillManifest.endpoint);
await this.appCredentials.signRequest(request);
const response: HttpOperationResponse = await this.httpClient.sendRequest(request);
if (response.status < 200 || response.status >= 300) {
const result: string = `HTTP error when forwarding activity to the skill: Status Code:${
response.status
}, Message: '${
response.bodyAsText
}'`;
await turnContext.sendActivity({
type: ActivityTypes.Trace,
text: result
});
throw new Error(result);
}
const responseBody: Activity[] = JSON.parse(response.bodyAsText || '[]');
// Retrieve Activity responses
const skillResponses: Activity[] = responseBody.map(fixActivityTimestamp);
const filteredResponses: Activity[] = [];
let endOfConversation: boolean = false;
skillResponses.forEach(async (skillResponse: Activity) => {
// Once a Skill has finished it signals that it's handing back control to the parent through a
// EndOfConversation event which then causes the SkillDialog to be closed. Otherwise it remains "in control".
activity.id = uuid();
}
if (!activity.timestamp) {
activity.timestamp = new Date();
}
if (activity.type === 'delay') {
// The BotFrameworkAdapter and Console adapter implement this
// hack directly in the POST method. Replicating that here
// to keep the behavior as close as possible to facilitate
// more realistic tests.
// eslint-disable-next-line @typescript-eslint/tslint/config
const delayMs: number = activity.value;
await sleep(delayMs);
} else if (activity.type === ActivityTypes.Trace && activity.channelId !== 'emulator') {
// if it is a Trace activity we only send to the channel if it's the emulator.
} else if (activity.type === ActivityTypes.Typing && activity.channelId !== 'test') {
// If it's a typing activity we omit this in test scenarios to avoid test failures
} else {
// Queue up this activity for aggregation back to the calling Bot in one overall message.
this.queuedActivities.push(activity);
}
responses.push({ id: activity.id });
});
activities.forEach(async (activity: Partial, index: number) => {
if (!activity.id) {
activity.id = uuid();
}
let response: ResourceResponse|undefined = { id: '' };
if (activity.type === 'delay') {
// The Activity Schema doesn't have a delay type build in, so it's simulated
// here in the Bot. This matches the behavior in the Node connector.
const delayMs: number = activity.value;
await sleep(delayMs);
// No need to create a response. One will be created below.
}
if (activity.type !== ActivityTypes.Trace || (activity.type === ActivityTypes.Trace && activity.channelId === 'emulator')) {
const requestPath: string = `/activities/${activity.id}`;
const request: Request = Request.create('POST', requestPath);
request.setBody(activity);
const message: string = `Sending activity. ReplyToId: ${activity.replyToId}`;
this.telemetryClient.trackTrace({
message: message,
severityLevel: Severity.Information
});
const begin: [number, number] = process.hrtime();
response = await this.sendRequest(request);
const end: [number, number] = process.hrtime(begin);
const latency: { latency: number } = { latency: toMilliseconds(end) };
it('should log a nested message in a trace activity', () => {
const conversationId = 'convo1';
const activity = {
id: 'someId',
label: 'Message sent',
type: ActivityTypes.Trace,
value: {
type: ActivityTypes.Message,
from: { role: 'bot' },
text: 'Hello',
},
} as Activity;
const logItems: LogItem[] = [
textItem(LogLevel.Debug, '<- '),
inspectableObjectItem(activity.type, activity),
summaryTextItem(activity),
textItem(LogLevel.Debug, '-> '),
inspectableObjectItem(activity.value.type, activity.value),
summaryTextItem(activity.value),
];
it('should handle the "copy message" selection', async () => {
const commandServiceSpy = jest.spyOn(commandService, 'remoteCall').mockResolvedValue({ id: 'copy' });
const clipboardSpy = jest.spyOn(Electron.clipboard, 'writeText');
const activity = {
valueType: ValueTypes.Activity,
type: ActivityTypes.Trace,
value: { type: ActivityTypes.Message, text: 'Hello Bot!' },
};
mockStore.dispatch(showContextMenuForActivity(activity));
await Promise.resolve(true);
expect(commandServiceSpy).toHaveBeenCalled();
expect(clipboardSpy).toHaveBeenCalledWith('Hello Bot!');
});
it('should render a trace activity', () => {
wrapper = shallow();
const middleware = card => children => <div>{children}</div>;
const mockCard = { activity: { type: ActivityTypes.Trace, valueType: ValueTypes.Debug } };
const activityWrapper = (wrapper.instance() as any).createActivityMiddleware()(middleware)(mockCard)(<span>);
expect(activityWrapper).toBeTruthy();
});
});</span>
it('should handle the "copy json" selection', async () => {
const commandServiceSpy = jest.spyOn(commandService, 'remoteCall').mockResolvedValue({ id: 'json' });
const clipboardSpy = jest.spyOn(Electron.clipboard, 'writeText');
const activity = {
valueType: '',
type: ActivityTypes.Trace,
value: { type: ActivityTypes.Message, text: 'Hello Bot!' },
};
await mockStore.dispatch(showContextMenuForActivity(activity));
await Promise.resolve(true);
expect(commandServiceSpy).toHaveBeenCalled();
expect(clipboardSpy).toHaveBeenCalledWith(JSON.stringify(activity, null, 2));
});
const skillContext: SkillContext = await this.skillContextAccessor.get(dc.context, new SkillContext());
skillContext.setObj(location, locationObj);
await this.skillContextAccessor.set(dc.context, skillContext);
forward = false;
break;
}
case TokenEvents.tokenResponseEventName: {
forward = true;
break;
}
default: {
await dc.context.sendActivity(
{
type: ActivityTypes.Trace,
text: `"Unknown Event ${ ev.name } was received but not processed."`
}
);
forward = false;
}
}
}
if (forward) {
const result: DialogTurnResult = await dc.continueDialog();
if (result.status === DialogTurnStatus.complete) {
await this.complete(dc);
}
}
}
const timezone: string = ev.value as string;
const tz: string = new Date().toLocaleString(timezone);
const timeZoneObj: {
timezone: string;
} = {
timezone: tz
};
const skillContext: SkillContext = await this.skillContextAccessor.get(dc.context, new SkillContext());
skillContext.setObj(timezone, timeZoneObj);
await this.skillContextAccessor.set(dc.context, skillContext);
} catch {
await dc.context.sendActivity(
{
type: ActivityTypes.Trace,
text: `"Timezone passed could not be mapped to a valid Timezone. Property not set."`
}
);
}
forward = false;
break;
}
case Events.locationEvent: {
const location: string = ev.value as string;
const locationObj: {
location: string;
} = {
location: location
};
const skillContext: SkillContext = await this.skillContextAccessor.get(dc.context, new SkillContext());
private createActivityMiddleware = () => next => card => children => {
const { valueType } = card.activity;
this.activityMap[card.activity.id] = valueType === ValueTypes.Activity ? card.activity.value : card.activity;
switch (card.activity.type) {
case ActivityTypes.Trace:
return this.renderTraceActivity(next, card, children);
case ActivityTypes.EndOfConversation:
return null;
default:
return this.activityWrapper(next, card, children);
}
};