@talema/graphql-azure-servicebus-subscriptions
Version:
A GraphQL subscription library using Azure Service Bus topics as PubSub server
170 lines • 8.6 kB
JavaScript
;
// tslint:disable-next-line:no-empty
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
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());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chai = __importStar(require("chai"));
const chai_as_promised_1 = __importDefault(require("chai-as-promised"));
const sinon_chai_1 = __importDefault(require("sinon-chai"));
const ServiceBusPubSub_1 = require("../ServiceBusPubSub");
const simple_mock_1 = __importDefault(require("simple-mock"));
const service_bus_1 = require("@azure/service-bus");
const utils_1 = require("./utils");
const MessageProcessor_1 = require("../MessageProcessor");
chai.use(chai_as_promised_1.default);
chai.use(sinon_chai_1.default);
const expect = chai.expect;
const options = {
topicName: "topic",
subscriptionName: "subs-name",
connectionString: "Endpoint=sb://a;SharedAccessKeyName=b;SharedAccessKey=c;"
};
const fakeReceiver = new utils_1.FakeMessageReceiver();
const fakeSender = new utils_1.FakeMessageSender(fakeReceiver);
const data = {
eventName: "somethingChange",
message: { data: "Hello" },
};
let mesageProcessor = new MessageProcessor_1.MessageProcessor(console);
let { client, receiverMock, senderMock } = getMockedServiceBusClient(fakeSender, fakeReceiver);
let sut = new ServiceBusPubSub_1.ServiceBusPubSub(options, console, mesageProcessor, client);
function getMockedServiceBusClient(senderSpy, fakeReceiver) {
const client = new service_bus_1.ServiceBusClient(options.connectionString);
const senderMock = simple_mock_1.default.mock(client, "createSender").returnWith(senderSpy);
const receiverMock = simple_mock_1.default.mock(client, "createReceiver").returnWith(fakeReceiver);
return { client, senderMock, receiverMock };
}
describe("ServiceBusPubSub", () => {
beforeEach("Reset state", () => {
fakeReceiver.reset();
fakeSender.reset();
});
it("can subscribe and is called when events happen", () => __awaiter(void 0, void 0, void 0, function* () {
let subscribeCalled = false;
let receivedMessage = undefined;
yield sut.subscribe(data.eventName, (payload) => __awaiter(void 0, void 0, void 0, function* () {
subscribeCalled = true;
receivedMessage = payload;
}), {});
yield sut.publish(data.eventName, data.message);
expect(fakeReceiver.pendingMessages.length).to.equal(1);
yield fakeReceiver.flush();
expect(subscribeCalled).to.be.true;
expect(receivedMessage).to.equal(data.message);
}));
it("Can ignore events not specified in the subscription", () => __awaiter(void 0, void 0, void 0, function* () {
let subscribeCalled = false;
let receivedMessage = undefined;
yield sut.subscribe("unknownEvent", (payload) => __awaiter(void 0, void 0, void 0, function* () {
subscribeCalled = true;
receivedMessage = payload;
}), {});
yield sut.publish(data.eventName, data.message);
yield fakeReceiver.flush();
expect(subscribeCalled).to.be.false;
expect(receivedMessage).to.equal(undefined);
}));
it("will add eventName as an attribute to the ServiceBusMessage published", () => __awaiter(void 0, void 0, void 0, function* () {
yield sut.subscribe(data.eventName, () => { }, {});
yield sut.publish(data.eventName, data.message);
const values = [];
for (const key in fakeReceiver.pendingMessages[0].applicationProperties) {
values.push(fakeReceiver.pendingMessages[0].applicationProperties[key]);
}
expect(values).to.have.members([data.eventName]);
}));
it("will subscribe once to the save event", () => __awaiter(void 0, void 0, void 0, function* () {
yield sut.subscribe(data.eventName, () => { }, {});
yield sut.subscribe(data.eventName, () => { }, {});
expect(receiverMock.callCount).to.eq(1);
}));
it("will create publisher for the eventName once", () => __awaiter(void 0, void 0, void 0, function* () {
yield sut.publish(data.eventName, data.message);
yield sut.publish(data.eventName, data.message);
expect(senderMock.callCount).to.eq(1);
}));
it("will enrich the published ServiceBusMessage with the label", () => __awaiter(void 0, void 0, void 0, function* () {
const message = {
body: "test message",
applicationProperties: {},
};
yield sut.publish(data.eventName, message);
const publishedMessage = fakeSender.lastMessage();
expect(publishedMessage === null || publishedMessage === void 0 ? void 0 : publishedMessage.applicationProperties).to.deep.equal({
"sub.eventName": data.eventName,
});
}));
it("can unsubscribe if passed the right client identifier", () => __awaiter(void 0, void 0, void 0, function* () {
const clientId = yield sut.subscribe("a", (_) => { });
expect(yield sut.unsubscribe(clientId)).to.be.true;
}));
it("will skip unsubscribe for unknown client identifiers", () => __awaiter(void 0, void 0, void 0, function* () {
yield sut.subscribe("a", (_) => { });
let clientClosed = false;
fakeReceiver.onClose = () => {
clientClosed = true;
};
yield sut.unsubscribe(55);
expect(clientClosed).to.be.false;
}));
it("unsubscripe last client will close servicebus connection", () => __awaiter(void 0, void 0, void 0, function* () {
sut = new ServiceBusPubSub_1.ServiceBusPubSub(options, console, mesageProcessor, client);
var subIdOne = yield sut.subscribe("a", (_) => { });
var subIdTwo = yield sut.subscribe("a", (_) => { });
let clientClosed = false;
fakeReceiver.onClose = () => { clientClosed = true; };
yield sut.unsubscribe(subIdOne);
expect(clientClosed).to.be.false;
yield sut.unsubscribe(subIdTwo);
expect(clientClosed).to.be.true;
}));
it("processError handler is called when the subscription recieve error", () => __awaiter(void 0, void 0, void 0, function* () {
let errorsResult = {
"UnauthorizedAccess": false,
"MessageLockLost": false,
"ServiceBusy": false
};
var errors = Object.keys(errorsResult);
errors.forEach((errorCode) => __awaiter(void 0, void 0, void 0, function* () {
yield mesageProcessor.onError({ error: { code: errorCode, name: "ServiceBusError" } }, (error) => __awaiter(void 0, void 0, void 0, function* () {
errorsResult[errorCode] = true;
return Promise.resolve();
}));
expect(errorsResult[errorCode]).to.be.true;
}));
}));
});
//# sourceMappingURL=ServiceBusPubSub.spec.js.map