kafka-penguin
Version:
An easy-to-use, light weight KafkaJS library for message re-processing strategies.
263 lines (239 loc) • 9.54 kB
text/typescript
/* eslint-disable no-shadow */
/* eslint-disable import/extensions */
/* eslint-disable import/no-unresolved */
/* eslint-disable no-unused-vars */
/* eslint-disable no-console */
/* eslint-disable no-undef */
import { DeadLetterQueue, DeadLetterQueueErrorConsumer, DeadLetterQueueErrorProducer } from './index';
import testClient from './clientConfig';
// Dead Letter Queue Tests
describe('Dead Letter Queue Tests', () => {
// Constructor Tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
describe('Constructor', () => {
const testInstance = new DeadLetterQueue(testClient, 'test1', () => true);
const mockClient = {
topic: expect.any(String),
innerProducer: expect.any(Object),
callback: expect.any(Function),
innerConsumer: null,
admin: expect.any(Object),
client: expect.any(Object),
};
describe('Initial State', () => {
it('Starts off with callback, topic, and client supplied', () => {
expect(testInstance).toBeInstanceOf(DeadLetterQueue);
expect(testInstance).toMatchObject(mockClient);
});
});
describe('Client is live & configured', () => {
it('Client is supplying the class with producers', () => {
const { client } = testInstance;
const producer = jest.fn(() => client.producer());
producer();
expect(producer).toReturnWith(expect.objectContaining({
send: expect.any(Function),
connect: expect.any(Function),
disconnect: expect.any(Function),
}));
});
it('Client is supplying the class with consumers', () => {
const { client } = testInstance;
const consumer = jest.fn(() => client.consumer({ groupId: 'my-group' }));
consumer();
expect(consumer).toReturnWith(expect.objectContaining({
subscribe: expect.any(Function),
run: expect.any(Function),
}));
});
it('Client is supplying the class with admins', () => {
const { client } = testInstance;
const admin = jest.fn(() => client.admin());
admin();
expect(admin).toReturnWith(expect.any(Object));
});
});
});
describe('Methods', () => {
let testInstance = new DeadLetterQueue(testClient, 'test1', () => true);
afterEach(() => {
testInstance = new DeadLetterQueue(testClient, 'test1', () => true);
});
// Producer Initialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
describe('Producer', () => {
const testingProducer = jest.fn(() => testInstance.producer());
describe('Returns/SideEffects', () => {
it('returns the DLQ instance', () => {
testingProducer();
expect(testInstance.producer()).toMatchObject(expect.objectContaining({
connect: expect.any(Function),
disconnect: expect.any(Function),
send: expect.any(Function),
}));
});
it('Assigns the producer to a instance of client producer', () => {
testingProducer();
expect(testInstance.innerProducer).toEqual(expect.objectContaining({
send: expect.any(Function),
connect: expect.any(Function),
disconnect: expect.any(Function),
}));
});
});
});
// Consumer Initialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
describe('Consumer', () => {
const id = { groupId: 'Jest Tests' };
const testingConsumer = jest.fn(() => testInstance.consumer(id));
describe('Returns/SideEffects', () => {
it('returns the Dead Letter Queue instance', () => {
testingConsumer();
expect(testInstance.consumer(id)).toMatchObject(expect.objectContaining({
connect: expect.any(Function),
disconnect: expect.any(Function),
run: expect.any(Function),
subscribe: expect.any(Function),
}));
});
it('Assigns the producer to a instance of client producer', () => {
testingConsumer();
expect(testInstance.innerConsumer).toEqual(expect.objectContaining({
connect: expect.any(Function),
disconnect: expect.any(Function),
run: expect.any(Function),
subscribe: expect.any(Function),
}));
});
});
});
// Producer Tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
describe('Producer Methods', () => {
const testingProducer = jest.fn(() => testInstance.producer());
describe('Connect', () => {
describe('Returns/SideEffects', () => {
it('returns the client producer connect method', () => {
testingProducer();
expect(testingProducer).toReturn();
});
it('connect method resolves', () => {
testingProducer();
const { innerProducer } = testInstance;
return innerProducer.connect()
.then((input: any) => expect(input).not.toBeNull())
.finally(() => { innerProducer.disconnect(); });
});
});
});
describe('Send', () => {
describe('Returns/SideEffects', () => {
it('throws a DLQ Error with a bad message, then sends it to the DLQ', async () => {
testingProducer();
const { innerProducer } = testInstance;
const message = {
topic: 'wrong-topic',
messages: [{
key: 'value',
value: 'key',
}],
};
return innerProducer.send(message)
.catch((e?: any) => {
innerProducer.send({
messages: message.messages,
topic: `${testInstance.topic}.deadLetterQueue`,
})
.then(innerProducer.disconnect())
.catch((e: Error) => console.log(e));
// Print the error to the console
const newError = new DeadLetterQueueErrorProducer(e);
console.log(newError);
}).finally(() => { innerProducer.disconnect(); });
});
it('disconnects the producer with an bad message', () => {
testingProducer();
const { innerProducer } = testInstance;
const message = {
topic: 'wrong-topic',
messages: [{
key: 'value',
value: 'key',
}],
};
return innerProducer.send(message).catch((e: any) => {
expect(e).toBeInstanceOf(Error);
}).finally(() => { innerProducer.disconnect(); });
});
});
});
describe('Disconnect', () => {
describe('Returns/SideEffects', () => {
it('returns the client producer disconnect method & disconnects successfully', () => {
testingProducer();
const { innerProducer } = testInstance;
expect(innerProducer.disconnect).toEqual(expect.any(Function));
return innerProducer.disconnect()
.then((input: any) => expect(input).not.toBeNull())
.finally(() => { innerProducer.disconnect(); });
});
});
});
});
// Consumer Tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
describe('Consumer Methods', () => {
const group = { groupId: 'JestTests' };
const testingConsumer = jest.fn(() => testInstance.consumer(group));
describe('Connect', () => {
describe('Returns/SideEffects', () => {
it('returns the client consumer connect method', () => {
testingConsumer();
expect(testingConsumer).toReturn();
});
it('connect method resolves', () => {
testingConsumer();
const { innerConsumer } = testInstance;
return innerConsumer.connect()
.then((input: any) => expect(input).not.toBeNull())
.finally(() => { innerConsumer.disconnect(); });
});
});
});
describe('Send', () => {
const run = jest.fn(async (input) => {
await testInstance.innerConsumer.connect()
.then(() => {
testInstance.innerConsumer.subscribe({
topic: testInstance.topic,
fromBeginning: false,
});
})
.then(() => {
testInstance.innerConsumer.run(input);
})
.catch((e: any) => { expect(e).toBeInstanceOf(Error); })
.finally(() => testInstance.innerConsumer.disconnect());
});
describe('Returns/SideEffects', () => {
it('throws a DLQ Error with a bad message, then sends it to the DLQ', async () => {
testingConsumer();
return run({
eachMessage: ({ topic, partitions, message }: {
topic: any, partitions: any, message: any
}) => false,
});
});
});
});
describe('Disconnect', () => {
describe('Returns/SideEffects', () => {
it('returns the client producer disconnect method & disconnects successfully', () => {
testingConsumer();
const { innerConsumer } = testInstance;
expect(innerConsumer.disconnect).toEqual(expect.any(Function));
return innerConsumer.disconnect()
.then((input: any) => expect(input).not.toBeNull())
.finally(() => { innerConsumer.disconnect(); });
});
});
});
});
});
});