events-backend: add integration tests for postgres
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -21,6 +21,8 @@ import {
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
TestDatabaseId,
|
||||
TestDatabases,
|
||||
mockCredentials,
|
||||
mockServices,
|
||||
startTestBackend,
|
||||
@@ -100,149 +102,178 @@ describe('eventsPlugin', () => {
|
||||
});
|
||||
|
||||
describe('event bus', () => {
|
||||
it('should be possible to publish events as a service', async () => {
|
||||
const { server } = await startTestBackend({
|
||||
features: [eventsPlugin()],
|
||||
});
|
||||
|
||||
await request(server)
|
||||
.post('/api/events/bus/v1/events')
|
||||
.set('authorization', mockCredentials.none.header())
|
||||
.send({ event: { topic: 'test', payload: { n: 1 } } })
|
||||
.expect(401);
|
||||
|
||||
await request(server)
|
||||
.post('/api/events/bus/v1/events')
|
||||
.set('authorization', mockCredentials.user.header())
|
||||
.send({ event: { topic: 'test', payload: { n: 1 } } })
|
||||
.expect(403);
|
||||
|
||||
await request(server)
|
||||
.post('/api/events/bus/v1/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ event: { topic: 'test', payload: { n: 1 } } })
|
||||
.expect(204); // 204, since there are no subscribers
|
||||
const databases = TestDatabases.create({
|
||||
ids: ['SQLITE_3', 'POSTGRES_9', 'POSTGRES_13', 'POSTGRES_16'],
|
||||
});
|
||||
|
||||
it('should be possible to subscribe as a service and receive an event', async () => {
|
||||
const { server } = await startTestBackend({
|
||||
features: [eventsPlugin()],
|
||||
});
|
||||
async function mockKnexFactory(databaseId: TestDatabaseId) {
|
||||
const knex = await databases.init(databaseId);
|
||||
return mockServices.database.mock({
|
||||
getClient: async () => knex,
|
||||
}).factory;
|
||||
}
|
||||
|
||||
await request(server)
|
||||
.put('/api/events/bus/v1/subscriptions/tester')
|
||||
.set('authorization', mockCredentials.none.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(401);
|
||||
it.each(databases.eachSupportedId())(
|
||||
'should be possible to publish events as a service, %p',
|
||||
async databaseId => {
|
||||
const backend = await startTestBackend({
|
||||
features: [eventsPlugin(), await mockKnexFactory(databaseId)],
|
||||
});
|
||||
const { server } = backend;
|
||||
|
||||
await request(server)
|
||||
.put('/api/events/bus/v1/subscriptions/tester')
|
||||
.set('authorization', mockCredentials.user.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(403);
|
||||
await request(server)
|
||||
.post('/api/events/bus/v1/events')
|
||||
.set('authorization', mockCredentials.none.header())
|
||||
.send({ event: { topic: 'test', payload: { n: 1 } } })
|
||||
.expect(401);
|
||||
|
||||
await request(server)
|
||||
.put('/api/events/bus/v1/subscriptions/tester')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(201);
|
||||
await request(server)
|
||||
.post('/api/events/bus/v1/events')
|
||||
.set('authorization', mockCredentials.user.header())
|
||||
.send({ event: { topic: 'test', payload: { n: 1 } } })
|
||||
.expect(403);
|
||||
|
||||
await request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester/events')
|
||||
.set('authorization', mockCredentials.none.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(401);
|
||||
await request(server)
|
||||
.post('/api/events/bus/v1/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ event: { topic: 'test', payload: { n: 1 } } })
|
||||
.expect(204); // 204, since there are no subscribers
|
||||
|
||||
await request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester/events')
|
||||
.set('authorization', mockCredentials.user.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(403);
|
||||
await backend.stop();
|
||||
},
|
||||
);
|
||||
|
||||
await request(server)
|
||||
.post('/api/events/bus/v1/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ event: { topic: 'test', payload: { n: 1 } } })
|
||||
.expect(201); // 201, since there is a subscriber
|
||||
it.each(databases.eachSupportedId())(
|
||||
'should be possible to subscribe as a service and receive an event, %p',
|
||||
async databaseId => {
|
||||
const backend = await startTestBackend({
|
||||
features: [eventsPlugin(), await mockKnexFactory(databaseId)],
|
||||
});
|
||||
const { server } = backend;
|
||||
|
||||
await request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(200, {
|
||||
await request(server)
|
||||
.put('/api/events/bus/v1/subscriptions/tester')
|
||||
.set('authorization', mockCredentials.none.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(401);
|
||||
|
||||
await request(server)
|
||||
.put('/api/events/bus/v1/subscriptions/tester')
|
||||
.set('authorization', mockCredentials.user.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(403);
|
||||
|
||||
await request(server)
|
||||
.put('/api/events/bus/v1/subscriptions/tester')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(201);
|
||||
|
||||
await request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester/events')
|
||||
.set('authorization', mockCredentials.none.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(401);
|
||||
|
||||
await request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester/events')
|
||||
.set('authorization', mockCredentials.user.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(403);
|
||||
|
||||
await request(server)
|
||||
.post('/api/events/bus/v1/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ event: { topic: 'test', payload: { n: 1 } } })
|
||||
.expect(201); // 201, since there is a subscriber
|
||||
|
||||
await request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(200, {
|
||||
events: [{ topic: 'test', payload: { n: 1 } }],
|
||||
});
|
||||
|
||||
await backend.stop();
|
||||
},
|
||||
);
|
||||
|
||||
it.each(databases.eachSupportedId())(
|
||||
'should only send an event for each subscriber once, %p',
|
||||
async databaseId => {
|
||||
const backend = await startTestBackend({
|
||||
features: [eventsPlugin(), await mockKnexFactory(databaseId)],
|
||||
});
|
||||
const { server } = backend;
|
||||
|
||||
// 2 subscribers
|
||||
await request(server)
|
||||
.put('/api/events/bus/v1/subscriptions/tester-1')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(201);
|
||||
await request(server)
|
||||
.put('/api/events/bus/v1/subscriptions/tester-2')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(201);
|
||||
|
||||
// A single event
|
||||
await request(server)
|
||||
.post('/api/events/bus/v1/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ event: { topic: 'test', payload: { n: 1 } } })
|
||||
.expect(201);
|
||||
|
||||
// Single client for subscriber 1 gets the event
|
||||
await request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester-1/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(200, {
|
||||
events: [{ topic: 'test', payload: { n: 1 } }],
|
||||
});
|
||||
|
||||
// Two clients for subscriber 2, only one gets the event
|
||||
const res1 = request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester-2/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] });
|
||||
const res2 = request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester-2/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] });
|
||||
|
||||
const res = await Promise.race([res1, res2]);
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body).toEqual({
|
||||
events: [{ topic: 'test', payload: { n: 1 } }],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should only send an event for each subscriber once', async () => {
|
||||
const { server } = await startTestBackend({
|
||||
features: [eventsPlugin()],
|
||||
});
|
||||
// Post another event, which triggers the other client to return
|
||||
await request(server)
|
||||
.post('/api/events/bus/v1/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ event: { topic: 'test', payload: { n: 2 } } })
|
||||
.expect(201);
|
||||
|
||||
// 2 subscribers
|
||||
await request(server)
|
||||
.put('/api/events/bus/v1/subscriptions/tester-1')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(201);
|
||||
await request(server)
|
||||
.put('/api/events/bus/v1/subscriptions/tester-2')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(201);
|
||||
const otherRes = await Promise.all([res1, res2]).then(rs =>
|
||||
rs.find(r => r !== res),
|
||||
);
|
||||
expect(otherRes?.status).toBe(202);
|
||||
|
||||
// A single event
|
||||
await request(server)
|
||||
.post('/api/events/bus/v1/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ event: { topic: 'test', payload: { n: 1 } } })
|
||||
.expect(201);
|
||||
// Reading subscriber 2 should now return the second event only
|
||||
await request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester-2/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(200, {
|
||||
events: [{ topic: 'test', payload: { n: 2 } }],
|
||||
});
|
||||
|
||||
// Single client for subscriber 1 gets the event
|
||||
await request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester-1/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(200, {
|
||||
events: [{ topic: 'test', payload: { n: 1 } }],
|
||||
});
|
||||
|
||||
// Two clients for subscriber 2, only one gets the event
|
||||
const res1 = request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester-2/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] });
|
||||
const res2 = request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester-2/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] });
|
||||
|
||||
const res = await Promise.race([res1, res2]);
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body).toEqual({
|
||||
events: [{ topic: 'test', payload: { n: 1 } }],
|
||||
});
|
||||
|
||||
// Post another event, which triggers the other client to return
|
||||
await request(server)
|
||||
.post('/api/events/bus/v1/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ event: { topic: 'test', payload: { n: 2 } } })
|
||||
.expect(201);
|
||||
|
||||
const otherRes = await Promise.all([res1, res2]).then(rs =>
|
||||
rs.find(r => r !== res),
|
||||
await backend.stop();
|
||||
},
|
||||
);
|
||||
expect(otherRes?.status).toBe(202);
|
||||
|
||||
// Reading subscriber 2 should now return the second event only
|
||||
await request(server)
|
||||
.get('/api/events/bus/v1/subscriptions/tester-2/events')
|
||||
.set('authorization', mockCredentials.service.header())
|
||||
.send({ topics: ['test'] })
|
||||
.expect(200, {
|
||||
events: [{ topic: 'test', payload: { n: 2 } }],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user