Skip to content

Commit

Permalink
multiple runs for many subs test
Browse files Browse the repository at this point in the history
  • Loading branch information
FZambia committed Jan 28, 2025
1 parent 463117f commit c2ac197
Showing 1 changed file with 79 additions and 77 deletions.
156 changes: 79 additions & 77 deletions src/centrifuge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -660,94 +660,96 @@ test.each(transportCases)("%s: connects and subscribes with token", async (trans
});

test.each(transportCases)("%s: subscribes and unsubscribes from many subs", async (transport, endpoint) => {
const c = new Centrifuge([{
transport: transport as TransportName,
endpoint: endpoint,
}], {
websocket: WebSocket,
fetch: fetch,
eventsource: EventSource,
readableStream: ReadableStream,
emulationEndpoint: 'http://localhost:8000/emulation',
// debug: true
});
// Keep an array of promises so that we can wait for each subscription's 'unsubscribed' event.
const unsubscribedPromises: Promise<UnsubscribedContext>[] = [];

const channels = [
'test1',
'test2',
'test3',
'test4',
'test5',
];

// Subscription tokens for anonymous users without ttl. Using an HMAC secret key used in tests ("secret").
const testTokens = {
'test1': "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3Mzc1MzIzNDgsImNoYW5uZWwiOiJ0ZXN0MSJ9.eqPQxbBtyYxL8Hvbkm-P6aH7chUsSG_EMWe-rTwF_HI",
'test2': "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3Mzc1MzIzODcsImNoYW5uZWwiOiJ0ZXN0MiJ9.tTJB3uSa8XpEmCvfkmrSKclijofnJ5RkQk6L2SaGtUE",
'test3': "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3Mzc1MzIzOTgsImNoYW5uZWwiOiJ0ZXN0MyJ9.nyLcMrIot441CszOKska7kQIjo2sEm8pSxV1XWfNCsI",
'test4': "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3Mzc1MzI0MDksImNoYW5uZWwiOiJ0ZXN0NCJ9.wWAX2AhJX6Ep4HVexQWSVF3-cWytVhzY9Pm7QsMdCsI",
'test5': "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3Mzc1MzI0MTgsImNoYW5uZWwiOiJ0ZXN0NSJ9.hCSfpHYws5TXLKkN0bW0DU6C-wgEUNuhGaIy8W1sT9o"
}
for (let index = 0; index < 5; index++) {
const c = new Centrifuge([{
transport: transport as TransportName,
endpoint: endpoint,
}], {
websocket: WebSocket,
fetch: fetch,
eventsource: EventSource,
readableStream: ReadableStream,
emulationEndpoint: 'http://localhost:8000/emulation',
// debug: true
});
// Keep an array of promises so that we can wait for each subscription's 'unsubscribed' event.
const unsubscribedPromises: Promise<UnsubscribedContext>[] = [];

c.connect();
const channels = [
'test1',
'test2',
'test3',
'test4',
'test5',
];

const subscriptions: any[] = [];
// Subscription tokens for anonymous users without ttl. Using an HMAC secret key used in tests ("secret").
const testTokens = {
'test1': "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3Mzc1MzIzNDgsImNoYW5uZWwiOiJ0ZXN0MSJ9.eqPQxbBtyYxL8Hvbkm-P6aH7chUsSG_EMWe-rTwF_HI",
'test2': "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3Mzc1MzIzODcsImNoYW5uZWwiOiJ0ZXN0MiJ9.tTJB3uSa8XpEmCvfkmrSKclijofnJ5RkQk6L2SaGtUE",
'test3': "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3Mzc1MzIzOTgsImNoYW5uZWwiOiJ0ZXN0MyJ9.nyLcMrIot441CszOKska7kQIjo2sEm8pSxV1XWfNCsI",
'test4': "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3Mzc1MzI0MDksImNoYW5uZWwiOiJ0ZXN0NCJ9.wWAX2AhJX6Ep4HVexQWSVF3-cWytVhzY9Pm7QsMdCsI",
'test5': "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3Mzc1MzI0MTgsImNoYW5uZWwiOiJ0ZXN0NSJ9.hCSfpHYws5TXLKkN0bW0DU6C-wgEUNuhGaIy8W1sT9o"
}

for (const channel of channels) {
const sub = c.newSubscription(channel, {
getToken: async function () {
// Sleep for a random time between 0 and 100 milliseconds to emulate network.
const sleep = (ms: any) => new Promise(resolve => setTimeout(resolve, ms));
await sleep(Math.random() * 100);
return testTokens[channel];
}
});
c.connect();

// Create a promise for the 'unsubscribed' event of this subscription.
const unsubPromise = new Promise<UnsubscribedContext>((resolve) => {
sub.on("unsubscribed", (ctx) => {
resolve(ctx);
const subscriptions: any[] = [];

for (const channel of channels) {
const sub = c.newSubscription(channel, {
getToken: async function () {
// Sleep for a random time between 0 and 100 milliseconds to emulate network.
const sleep = (ms: any) => new Promise(resolve => setTimeout(resolve, ms));
await sleep(Math.random() * 100);
return testTokens[channel];
}
});
});
unsubscribedPromises.push(unsubPromise);

// Actually subscribe.
sub.subscribe();
subscriptions.push(sub);
}
// Create a promise for the 'unsubscribed' event of this subscription.
const unsubPromise = new Promise<UnsubscribedContext>((resolve) => {
sub.on("unsubscribed", (ctx) => {
resolve(ctx);
});
});
unsubscribedPromises.push(unsubPromise);

// Wait until all subscriptions are in the Subscribed state.
await Promise.all(
subscriptions.map(async (sub) => {
await sub.ready(5000);
expect(sub.state).toBe(SubscriptionState.Subscribed);
})
);
// Actually subscribe.
sub.subscribe();
subscriptions.push(sub);
}

// The client itself should be connected now.
expect(c.state).toBe(State.Connected);
// Wait until all subscriptions are in the Subscribed state.
await Promise.all(
subscriptions.map(async (sub) => {
await sub.ready(5000);
expect(sub.state).toBe(SubscriptionState.Subscribed);
})
);

// Unsubscribe from all and then disconnect.
subscriptions.forEach((sub) => {
sub.unsubscribe();
});
c.disconnect();
// The client itself should be connected now.
expect(c.state).toBe(State.Connected);

// Wait until all 'unsubscribed' events are received.
const unsubscribedContexts = await Promise.all(unsubscribedPromises);
// Unsubscribe from all and then disconnect.
subscriptions.forEach((sub) => {
sub.unsubscribe();
});
c.disconnect();

// Confirm each subscription is now Unsubscribed.
subscriptions.forEach((sub) => {
expect(sub.state).toBe(SubscriptionState.Unsubscribed);
});
// Wait until all 'unsubscribed' events are received.
const unsubscribedContexts = await Promise.all(unsubscribedPromises);

// The client should be disconnected.
expect(c.state).toBe(State.Disconnected);
// Confirm each subscription is now Unsubscribed.
subscriptions.forEach((sub) => {
expect(sub.state).toBe(SubscriptionState.Unsubscribed);
});

// Assert the correct unsubscribe code for each subscription.
unsubscribedContexts.forEach((ctx) => {
expect(ctx.code).toBe(unsubscribedCodes.unsubscribeCalled);
});
// The client should be disconnected.
expect(c.state).toBe(State.Disconnected);

// Assert the correct unsubscribe code for each subscription.
unsubscribedContexts.forEach((ctx) => {
expect(ctx.code).toBe(unsubscribedCodes.unsubscribeCalled);
});
}
});

0 comments on commit c2ac197

Please sign in to comment.