wa-chat-server
Version:
Watson Assistant powered chat server
439 lines (438 loc) • 22.9 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WatsonWrapperTest = void 0;
const ConversationServiceMock_1 = require("../mock/ConversationServiceMock");
const ConversationServicesMock_1 = require("../mock/ConversationServicesMock");
const ConversationAPIMock_1 = require("../mock/ConversationAPIMock");
const MessageResponseMock_1 = require("../mock/MessageResponseMock");
const MessageRequestMock_1 = require("../mock/MessageRequestMock");
const WAChatServerConfigMock_1 = require("../mock/WAChatServerConfigMock");
const WatsonWrapper_1 = require("../../class/WatsonWrapper");
const ConversationServiceValidationException_1 = require("../../exception/ConversationServiceValidationException");
const ConversationServiceRuntimeException_1 = require("../../exception/ConversationServiceRuntimeException");
const SchemaValidationException_1 = require("../../exception/SchemaValidationException");
const Logger_1 = require("../../class/Logger/Logger");
const LoggerDriverMock_1 = require("../mock/LoggerDriverMock");
const SessionMock_1 = require("../mock/SessionMock");
class WatsonWrapperTest {
constructor() {
this.schemaDir = '';
this.config = new WAChatServerConfigMock_1.WAChatServerConfigMock();
}
getLogger(check = false, silence = true) {
return new Logger_1.Logger(this.config, new LoggerDriverMock_1.LoggerDriverMock(check, silence));
}
getWatsonSimpleRequest(extraParams = {}) {
return {
output: {
generic: [
{
// eslint-disable-next-line @typescript-eslint/camelcase
response_type: 'text',
text: 'Ignored',
},
],
},
context: Object.assign({ 'request-service': 'SERVICE_NAME', 'request-params-PARAM1': 'VALUE1' }, extraParams),
};
}
getWatsonSimpleRequestCleanedCtx(extraParams = {}) {
const retVal = {
'request-service': null,
'request-params-PARAM1': null,
};
Object.keys(extraParams).forEach((key) => {
retVal[key] = null;
});
return retVal;
}
getSimpleJsonSchema(type) {
return {
type: 'object',
properties: {
PARAM1: { type },
},
};
}
getWatsonComplexRequest() {
return this.getWatsonSimpleRequest({
'request-params-PARAM2-PARAM3': 'VALUE3',
});
}
/**
* Parameters from meta are added to Watson context
*/
metaParametersTest() {
it('meta-parameters', () => __awaiter(this, void 0, void 0, function* () {
const services = new ConversationServicesMock_1.ConversationServicesMock();
const meta = {
url: 'URL',
userAgent: 'AGENT',
resolution: 'RESOLUTION',
};
const adapter = new ConversationAPIMock_1.ConversationAPIMock()
.addResponse(MessageResponseMock_1.MessageResponseMock.okResponseWithResult(Object.assign(Object.assign({}, this.getWatsonSimpleRequest()), { context: {} })))
.addRequestValidator((msg) => {
const client = msg.context.client;
return expect(client).toStrictEqual(meta);
});
const request = new MessageRequestMock_1.MessageRequestMock();
const session = new SessionMock_1.SessionMock();
const watson = new WatsonWrapper_1.WatsonWrapper(this.getLogger(), adapter, services, [], [], request, meta, session);
yield watson.getResponse();
}));
}
/**
* An exception must be thrown if the watson context variable $request-service specifies
* an unknown service
*/
conversationServiceUnknownServiceTest() {
it('conversation-service-unknown-service', () => __awaiter(this, void 0, void 0, function* () {
const services = new ConversationServicesMock_1.ConversationServicesMock();
const adapter = new ConversationAPIMock_1.ConversationAPIMock().addResponse(MessageResponseMock_1.MessageResponseMock.okResponseWithResult(this.getWatsonSimpleRequest()));
const request = new MessageRequestMock_1.MessageRequestMock();
const session = new SessionMock_1.SessionMock();
const watson = new WatsonWrapper_1.WatsonWrapper(this.getLogger(), adapter, services, [], [], request, null, session);
return expect(watson.getResponse()).rejects.toStrictEqual(new ConversationServiceValidationException_1.ConversationServiceValidationException("Conversation service 'SERVICE_NAME' received in $request-service not registered"));
}));
}
/**
* Verifies that the watson context variables $request-params-* are correctly transformed to
* the conversation service request
*/
conversationServiceRequestComputationTest() {
it('conversation-service-request-computation', () => __awaiter(this, void 0, void 0, function* () {
expect.assertions(1);
const services = new ConversationServicesMock_1.ConversationServicesMock();
const service = new ConversationServiceMock_1.ConversationServiceMock({
logger: this.getLogger(),
services,
requestValidation: false,
responseValidation: false,
});
service.requestValidator = (request) => {
return expect(request).toStrictEqual({
PARAM1: 'VALUE1',
PARAM2: { PARAM3: 'VALUE3' },
});
};
services.serviceMock = service;
yield service.loadSchemas();
const adapter = new ConversationAPIMock_1.ConversationAPIMock().addResponse(MessageResponseMock_1.MessageResponseMock.okResponseWithResult(this.getWatsonComplexRequest()));
const request = new MessageRequestMock_1.MessageRequestMock();
const session = new SessionMock_1.SessionMock();
const watson = new WatsonWrapper_1.WatsonWrapper(this.getLogger(), adapter, services, [], [], request, null, session);
yield watson.getResponse();
}));
}
/**
* Tests that en error is throws if the conversation service requires a request validation
* and the request is not in line with the corresponding JSON schema
*/
conversationServiceInvalidRequestTest() {
it('conversation-service-invalid-request', () => __awaiter(this, void 0, void 0, function* () {
expect.assertions(1);
const services = new ConversationServicesMock_1.ConversationServicesMock();
const service = new ConversationServiceMock_1.ConversationServiceMock({
logger: this.getLogger(),
services,
requestValidation: true,
responseValidation: false,
});
services.serviceMock = service;
services.schemaPathToSchema.set(`${this.schemaDir}/request/Mock.json`, JSON.stringify(this.getSimpleJsonSchema('number')));
yield service.loadSchemas();
const adapter = new ConversationAPIMock_1.ConversationAPIMock()
.addResponse(MessageResponseMock_1.MessageResponseMock.okResponseWithResult(this.getWatsonSimpleRequest()))
.addRequestValidator(() => null)
.addRequestValidator((msg) => {
const errorText = msg.context.response.error;
return expect(errorText.startsWith('Error: Conversation service Mock: request validation failed - ')).toStrictEqual(true);
});
const request = new MessageRequestMock_1.MessageRequestMock();
const session = new SessionMock_1.SessionMock();
const watson = new WatsonWrapper_1.WatsonWrapper(this.getLogger(), adapter, services, [], [], request, null, session);
yield watson.getResponse();
}));
}
/**
* Tests that a simple conversation service with no request/response validation results in
* a second watson call and that the service response is correctly mapped to the watson context
* of this second call
*/
conversationServiceWithoutValidationTest() {
it('conversation-service-without-validation', () => __awaiter(this, void 0, void 0, function* () {
expect.assertions(1);
const services = new ConversationServicesMock_1.ConversationServicesMock();
const service = new ConversationServiceMock_1.ConversationServiceMock({
logger: this.getLogger(),
services,
requestValidation: false,
responseValidation: false,
});
service.response = { a: 'A' };
services.serviceMock = service;
yield service.loadSchemas();
const adapter = new ConversationAPIMock_1.ConversationAPIMock()
.addResponse(MessageResponseMock_1.MessageResponseMock.okResponseWithResult(this.getWatsonSimpleRequest()))
.addRequestValidator(() => null)
.addRequestValidator((msg) => {
const { context, intents } = msg;
return expect({ context, intents }).toStrictEqual({
context: Object.assign({ response: {
result: { a: 'A' },
} }, this.getWatsonSimpleRequestCleanedCtx()),
intents: [
{
intent: 'response1',
confidence: 1.0,
},
],
});
});
const request = new MessageRequestMock_1.MessageRequestMock();
const session = new SessionMock_1.SessionMock();
const watson = new WatsonWrapper_1.WatsonWrapper(this.getLogger(), adapter, services, [], [], request, null, session);
yield watson.getResponse();
}));
}
/**
* An error must be thrown if the conversation service requires a response validation and
* the returned object is not in line with the corresponding JSON schema
*/
conversationServiceInvalidResponseTest() {
it('conversation-service-invalid-response', () => __awaiter(this, void 0, void 0, function* () {
expect.assertions(1);
const services = new ConversationServicesMock_1.ConversationServicesMock();
const service = new ConversationServiceMock_1.ConversationServiceMock({
logger: this.getLogger(),
services,
requestValidation: false,
responseValidation: true,
});
service.response = { PARAM1: 'A' };
services.serviceMock = service;
services.schemaPathToSchema.set(`${this.schemaDir}/response/Mock.json`, JSON.stringify(this.getSimpleJsonSchema('number')));
yield service.loadSchemas();
const adapter = new ConversationAPIMock_1.ConversationAPIMock().addResponse(MessageResponseMock_1.MessageResponseMock.okResponseWithResult(this.getWatsonSimpleRequest()));
const request = new MessageRequestMock_1.MessageRequestMock();
const session = new SessionMock_1.SessionMock();
const watson = new WatsonWrapper_1.WatsonWrapper(this.getLogger(), adapter, services, [], [], request, null, session);
try {
yield watson.getResponse();
}
catch (e) {
const instanceTest = e instanceof SchemaValidationException_1.SchemaValidationException;
const text = 'Error: Conversation service Mock: response validation failed - ';
const textTest = e.toString().startsWith(text);
return expect(instanceTest && textTest).toStrictEqual(true);
}
}));
}
/**
* The failure of the conversation service must result in a second watson call; information about
* the failure must be correclty propagated to the watson context
*/
conversationServiceFailureTest() {
it('conversation-service-failure', () => __awaiter(this, void 0, void 0, function* () {
expect.assertions(1);
const services = new ConversationServicesMock_1.ConversationServicesMock();
const service = new ConversationServiceMock_1.ConversationServiceMock({
logger: this.getLogger(),
services,
requestValidation: false,
responseValidation: false,
});
service.response = new Error('E');
services.serviceMock = service;
yield service.loadSchemas();
const adapter = new ConversationAPIMock_1.ConversationAPIMock()
.addResponse(MessageResponseMock_1.MessageResponseMock.okResponseWithResult(this.getWatsonSimpleRequest()))
.addRequestValidator(() => null)
.addRequestValidator((msg) => {
const { context, intents } = msg;
return expect({ context, intents }).toStrictEqual({
context: Object.assign({ response: { error: 'Error: E' } }, this.getWatsonSimpleRequestCleanedCtx()),
intents: [
{
intent: 'error1',
confidence: 1.0,
},
],
});
});
const request = new MessageRequestMock_1.MessageRequestMock();
const session = new SessionMock_1.SessionMock();
const watson = new WatsonWrapper_1.WatsonWrapper(this.getLogger(), adapter, services, [], [], request, null, session);
yield watson.getResponse();
}));
}
conversationServiceResponseMappingToRootTest() {
it('conversation-service-response-mapping-to-root', () => __awaiter(this, void 0, void 0, function* () {
expect.assertions(1);
const services = new ConversationServicesMock_1.ConversationServicesMock();
const service = new ConversationServiceMock_1.ConversationServiceMock({
logger: this.getLogger(),
services,
requestValidation: false,
responseValidation: false,
});
service.response = { a: 'A' };
services.serviceMock = service;
yield service.loadSchemas();
const adapter = new ConversationAPIMock_1.ConversationAPIMock()
.addResponse(MessageResponseMock_1.MessageResponseMock.okResponseWithResult(this.getWatsonSimpleRequest({
'request-resultTarget': '',
})))
.addRequestValidator(() => null)
.addRequestValidator((msg) => {
const { context, intents } = msg;
return expect({ context, intents }).toStrictEqual({
context: Object.assign({ a: 'A' }, this.getWatsonSimpleRequestCleanedCtx({
'request-resultTarget': '',
})),
intents: [
{
intent: 'response1',
confidence: 1.0,
},
],
});
});
const request = new MessageRequestMock_1.MessageRequestMock();
const session = new SessionMock_1.SessionMock();
const watson = new WatsonWrapper_1.WatsonWrapper(this.getLogger(), adapter, services, [], [], request, null, session);
yield watson.getResponse();
}));
}
conversationServiceResponseMappingToCustomLocTest() {
it('conversation-service-response-mapping-to-custom-location', () => __awaiter(this, void 0, void 0, function* () {
expect.assertions(1);
const services = new ConversationServicesMock_1.ConversationServicesMock();
const service = new ConversationServiceMock_1.ConversationServiceMock({
logger: this.getLogger(),
services,
requestValidation: false,
responseValidation: false,
});
service.response = { a: 'A' };
services.serviceMock = service;
yield service.loadSchemas();
const adapter = new ConversationAPIMock_1.ConversationAPIMock()
.addResponse(MessageResponseMock_1.MessageResponseMock.okResponseWithResult(this.getWatsonSimpleRequest({
'request-resultTarget': 'my.special.location',
})))
.addRequestValidator(() => null)
.addRequestValidator((msg) => {
const { context, intents } = msg;
return expect({ context, intents }).toStrictEqual({
context: Object.assign({ my: {
special: {
location: {
a: 'A',
},
},
} }, this.getWatsonSimpleRequestCleanedCtx({
'request-resultTarget': 'my.special.location',
})),
intents: [
{
intent: 'response1',
confidence: 1.0,
},
],
});
});
const request = new MessageRequestMock_1.MessageRequestMock();
const session = new SessionMock_1.SessionMock();
const watson = new WatsonWrapper_1.WatsonWrapper(this.getLogger(), adapter, services, [], [], request, null, session);
yield watson.getResponse();
}));
}
conversationServiceErrorMappingToCustomLocTest() {
it('conversation-service-error-mapping-to-custom-location', () => __awaiter(this, void 0, void 0, function* () {
expect.assertions(1);
const services = new ConversationServicesMock_1.ConversationServicesMock();
const service = new ConversationServiceMock_1.ConversationServiceMock({
logger: this.getLogger(),
services,
requestValidation: false,
responseValidation: false,
});
service.response = new Error('E');
services.serviceMock = service;
yield service.loadSchemas();
const adapter = new ConversationAPIMock_1.ConversationAPIMock()
.addResponse(MessageResponseMock_1.MessageResponseMock.okResponseWithResult(this.getWatsonSimpleRequest({
'request-errorTarget': 'my.error',
})))
.addRequestValidator(() => null)
.addRequestValidator((msg) => {
const { context, intents } = msg;
return expect({ context, intents }).toStrictEqual({
context: Object.assign({ my: { error: 'Error: E' } }, this.getWatsonSimpleRequestCleanedCtx({
'request-errorTarget': 'my.error',
})),
intents: [
{
intent: 'error1',
confidence: 1.0,
},
],
});
});
const request = new MessageRequestMock_1.MessageRequestMock();
const session = new SessionMock_1.SessionMock();
const watson = new WatsonWrapper_1.WatsonWrapper(this.getLogger(), adapter, services, [], [], request, null, session);
yield watson.getResponse();
}));
}
conversationServiceUnsupportedPrimitiveResponseMappingTest() {
it('conversation-service-unsupported-primitive-response-mapping', () => __awaiter(this, void 0, void 0, function* () {
expect.assertions(1);
const services = new ConversationServicesMock_1.ConversationServicesMock();
const service = new ConversationServiceMock_1.ConversationServiceMock({
logger: this.getLogger(),
services,
requestValidation: false,
responseValidation: false,
});
service.response = 0;
services.serviceMock = service;
yield service.loadSchemas();
const adapter = new ConversationAPIMock_1.ConversationAPIMock().addResponse(MessageResponseMock_1.MessageResponseMock.okResponseWithResult(this.getWatsonSimpleRequest({
'request-resultTarget': '',
})));
const request = new MessageRequestMock_1.MessageRequestMock();
const session = new SessionMock_1.SessionMock();
const watson = new WatsonWrapper_1.WatsonWrapper(this.getLogger(), adapter, services, [], [], request, null, session);
return expect(watson.getResponse()).rejects.toStrictEqual(new ConversationServiceRuntimeException_1.ConversationServiceRuntimeException("Not possible to map primitive value '0' to context"));
}));
}
test() {
return __awaiter(this, void 0, void 0, function* () {
this.metaParametersTest();
this.conversationServiceUnknownServiceTest();
this.conversationServiceRequestComputationTest();
this.conversationServiceInvalidRequestTest();
this.conversationServiceWithoutValidationTest();
this.conversationServiceInvalidResponseTest();
this.conversationServiceFailureTest();
this.conversationServiceResponseMappingToRootTest();
this.conversationServiceResponseMappingToCustomLocTest();
this.conversationServiceErrorMappingToCustomLocTest();
this.conversationServiceUnsupportedPrimitiveResponseMappingTest();
});
}
}
exports.WatsonWrapperTest = WatsonWrapperTest;
new WatsonWrapperTest().test();