courtbot-engine
Version:
An engine for courtbot-like functionality to be included in city/county services sites.
171 lines (147 loc) • 6.46 kB
JavaScript
import proxyquire from "proxyquire";
import setup from './setup';
import registrationState from "../src/registrationState";
import EventEmitter from "events";
describe("CourtbotConversation", () => {
const {sandbox, chance, expect} = setup();
let conversationType;
let registrationSource;
let getCasePartiesStub;
let getLoggerStub;
let logger;
let ConversationClass;
let conversation;
let emitter;
let events;
beforeEach(() => {
conversationType = chance.word();
registrationSource = {};
logger = {
info: sandbox.stub(),
debug: sandbox.stub(),
};
getCasePartiesStub = sandbox.stub();
getLoggerStub = sandbox.stub().returns(logger);
emitter = new EventEmitter();
events = { default: emitter, getCaseParties: getCasePartiesStub };
ConversationClass = proxyquire("../src/conversation", {
log4js: { getLogger: getLoggerStub },
"./events": events,
"./messaging": proxyquire("../src/messaging", {
"./events": events
})
}).default;
conversation = new ConversationClass(conversationType, registrationSource);
});
it("has the correct settings", () => {
expect(conversation.conversationType).to.equal(conversationType);
expect(conversation.registrationSource).to.equal(registrationSource);
});
it("creates a class level loger", () => {
return expect(getLoggerStub).to.have.been.calledWith("CourtbotConversation");
});
describe("emitReply", () => {
it("emits a reply event", () => {
const msg = chance.paragraph()
return expect(() => conversation.emitReply(msg)).to.emitFrom(conversation, "reply", msg, {});
});
describe("promise handling", () => {
it("handles a single promise", () => {
const msg = chance.paragraph()
const promResult = chance.word();
conversation.on("reply", (msg, result) => {
result.promise = Promise.resolve(promResult);
});
return expect(conversation.emitReply(msg)).to.eventually.equal(promResult);
});
it("handles multiple promises", () => {
const msg = chance.paragraph()
const promResult1 = chance.word();
const promResult2 = chance.word();
const promResult3 = chance.word();
conversation.on("reply", (msg, result) => {
result.promises = [
Promise.resolve(promResult1),
Promise.resolve(promResult2),
Promise.resolve(promResult3)
];
});
return expect(conversation.emitReply(msg)).to.eventually.eql([promResult1, promResult2, promResult3]);
});
});
});
describe("parse", () => {
beforeEach(() => {
conversation.fetchActiveConversation = sandbox.stub();
conversation.createNewConversation = sandbox.stub();
conversation.chooseParty = sandbox.stub();
conversation.finalQuestion = sandbox.stub();
});
it("creates a new conversation if no conversation is active", () => {
const msg = chance.word();
const from = chance.phone();
conversation.fetchActiveConversation.returns(Promise.resolve(null));
conversation.createNewConversation.returns(Promise.resolve());
return conversation.parse(msg, from).then(() => {
expect(conversation.fetchActiveConversation).to.have.been.calledWith(from);
expect(conversation.createNewConversation).to.have.been.calledWith(msg, from);
});
});
it("chooses a party if it was waiting for a party", () => {
const msg = chance.word();
const from = chance.phone();
const reg = { state: registrationState.ASKED_PARTY };
conversation.fetchActiveConversation.returns(Promise.resolve(reg));
conversation.createNewConversation.returns(Promise.resolve());
return conversation.parse(msg, from).then(() => {
expect(conversation.fetchActiveConversation).to.have.been.calledWith(from);
expect(conversation.chooseParty).to.have.been.calledWith(reg, msg, from);
});
});
it("finalizes the registration if it was waiting for the final question", () => {
const msg = chance.word();
const from = chance.phone();
const reg = { state: registrationState.ASKED_REMINDER };
conversation.fetchActiveConversation.returns(Promise.resolve(reg));
conversation.createNewConversation.returns(Promise.resolve());
return conversation.parse(msg, from).then(() => {
expect(conversation.fetchActiveConversation).to.have.been.calledWith(from);
expect(conversation.finalQuestion).to.have.been.calledWith(reg, msg, from);
});
});
});
describe("finalQuestion", () => {
let msg;
let from;
let conv;
beforeEach(() => {
from = chance.phone();
msg = chance.paragraph();
registrationSource.updateRegistrationState = sandbox.stub();
conv = {
registration_id: chance.integer(),
state: registrationState.ASKED_REMINDER
}
});
it("sets the registration state to REMINDING if the response counts as yes", () => {
emitter.on("courtbot-messaging-is-yes", evt => evt.result = true);
const eventStub = sandbox.stub();
const noMessage = "NO MESSAGE PROVIDED";
emitter.on("courtbot-messaging-confirm-registration", eventStub);
return conversation.finalQuestion(conv, msg, from).then(() => {
expect(registrationSource.updateRegistrationState).to.have.been.calledWith(conv.registration_id, registrationState.REMINDING);
expect(eventStub).to.have.been.calledWith({phone: from, pending: conv, message: noMessage});
});
});
it("sets the registration state to UNSUBSCRIBED if the response counts as no", () => {
emitter.on("courtbot-messaging-is-no", evt => evt.result = true);
const eventStub = sandbox.stub();
const noMessage = "NO MESSAGE PROVIDED";
emitter.on("courtbot-messaging-cancel-registration", eventStub);
return conversation.finalQuestion(conv, msg, from).then(() => {
expect(registrationSource.updateRegistrationState).to.have.been.calledWith(conv.registration_id, registrationState.UNSUBSCRIBED);
expect(eventStub).to.have.been.calledWith({phone: from, pending: conv, message: noMessage});
});
});
});
});