Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker compose for testing, add some tests #280

Merged
merged 1 commit into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Install dependencies
run: yarn install
- name: Start Centrifugo
run: docker run -d -p 8000:8000 -e CENTRIFUGO_PRESENCE=true centrifugo/centrifugo:latest centrifugo --client_insecure --http_stream --sse
run: docker compose up -d --wait
- name: Lint
run: yarn lint
- name: Test
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ The features implemented by this SDK can be found in [SDK feature matrix](https:
* [Protobuf support](#protobuf-support)
* [Using with NodeJS](#using-with-nodejs)
* [Custom WebSocket constructor](#custom-websocket-constructor)
* [Run tests locally](#run-tests-locally)

## Install

Expand Down Expand Up @@ -815,3 +816,17 @@ var centrifuge = new Centrifuge('ws://localhost:8000/connection/websocket', {
```

See a basic example with React Native where this technique is used [in this comment](https://github.com/centrifugal/centrifuge-js/issues/224#issuecomment-1538820023).

## Run tests locally

If you want to run `centrifuge-js` tests locally, start test Centrifugo server:

```
docker compose up
```

Then:

```
yarn test
```
14 changes: 14 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
version: '3.8'

services:
centrifugo:
image: centrifugo/centrifugo:v5
command:
- centrifugo
ports:
- "8000:8000"
environment:
- CENTRIFUGO_CLIENT_INSECURE=true
- CENTRIFUGO_HTTP_STREAM=true
- CENTRIFUGO_SSE=true
- CENTRIFUGO_PRESENCE=true
151 changes: 143 additions & 8 deletions src/centrifuge.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import { Centrifuge } from './centrifuge'
import {
DisconnectedContext, Error as CentrifugeError,
PublicationContext, TransportName, UnsubscribedContext, State, SubscriptionState
DisconnectedContext,
Error as CentrifugeError,
PublicationContext,
TransportName,
UnsubscribedContext,
State,
SubscriptionState,
SubscribedContext,
} from './types';
import { disconnectedCodes, unsubscribedCodes, connectingCodes } from './codes';
import {
disconnectedCodes,
unsubscribedCodes,
connectingCodes,
} from './codes';

import WebSocket from 'ws';
import EventSource from 'eventsource';
Expand All @@ -15,14 +25,18 @@ test('invalid endpoint', () => {
});

test('no websocket constructor', async () => {
const c = new Centrifuge('ws://localhost:8000/connection/websocket?cf_protocol_version=v2');
const c = new Centrifuge('ws://localhost:8000/connection/websocket');
expect(() => { c.connect() }).toThrowError();
});

const transportCases = [
['websocket', 'ws://localhost:8000/connection/websocket?cf_protocol_version=v2'],
['http_stream', 'http://localhost:8000/connection/http_stream?cf_protocol_version=v2'],
['sse', 'http://localhost:8000/connection/sse?cf_protocol_version=v2'],
['websocket', 'ws://localhost:8000/connection/websocket'],
['http_stream', 'http://localhost:8000/connection/http_stream'],
['sse', 'http://localhost:8000/connection/sse'],
]

const websocketOnly = [
['websocket', 'ws://localhost:8000/connection/websocket'],
]

test.each(transportCases)("%s: connects and disconnects", async (transport, endpoint) => {
Expand Down Expand Up @@ -216,7 +230,7 @@ test.each(transportCases)("%s: handles offline/online events", async (transport,
expect(c.state).toBe(State.Disconnected);
});

test.each(transportCases.slice(0, 1))("%s: not connecting on online in disconnected state", async (transport, endpoint) => {
test.each(transportCases)("%s: not connecting on online in disconnected state", async (transport, endpoint) => {
const networkEventTarget = new EventTarget();

const c = new Centrifuge([{
Expand Down Expand Up @@ -364,3 +378,124 @@ test.each(transportCases)("%s: subscribe and unsubscribe loop", async (transport
await disconnectedPromise;
expect(c.state).toBe(State.Disconnected);
});

// Make sure we can unsubscribe right after connect called and connect/subscribe
// frames not sent yet.
test.each(transportCases)("%s: unsubscribe right after connect", 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'
});

c.connect();
await c.ready(5000);

const sub = c.newSubscription('test');

let unsubcribeCalled: any;
const unsubscribedPromise = new Promise<UnsubscribedContext>((resolve, _) => {
unsubcribeCalled = resolve;
})
let subcribeCalled: any;
const subscribedPromise = new Promise<SubscribedContext>((resolve, _) => {
subcribeCalled = resolve;
})

sub.on('subscribed', (ctx) => {
subcribeCalled(ctx);
})
sub.on('unsubscribed', (ctx) => {
unsubcribeCalled(ctx);
})

sub.subscribe();
c.disconnect();
c.connect();
sub.unsubscribe();

expect(sub.state).toBe(SubscriptionState.Unsubscribed);
await unsubscribedPromise;

sub.subscribe();
await subscribedPromise;

let disconnectCalled: any;
const disconnectedPromise = new Promise<DisconnectedContext>((resolve, _) => {
disconnectCalled = resolve;
})
c.on('disconnected', (ctx) => {
disconnectCalled(ctx);
})

c.disconnect();
await disconnectedPromise;
expect(c.state).toBe(State.Disconnected);
});

// Make sure we can unsubscribe right after connect frame sent but reply has not been yet received.
// This is important to cover bug described in https://github.com/centrifugal/centrifuge-js/pull/274.
test.each(websocketOnly)("%s: unsubscribe in between connect command and reply", 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'
});

const sub = c.newSubscription('test');

let unsubcribeCalled: any;
const unsubscribedPromise = new Promise<UnsubscribedContext>((resolve, _) => {
unsubcribeCalled = resolve;
})
let subcribeCalled: any;
const subscribedPromise = new Promise<SubscribedContext>((resolve, _) => {
subcribeCalled = resolve;
})

// @ts-ignore this is only for test purposes.
c.on('__centrifuge_debug:connect_frame_sent', () => {
sub.unsubscribe();
unsubcribeCalled()
})

sub.on('subscribed', (ctx) => {
subcribeCalled(ctx);
})
sub.on('unsubscribed', (ctx) => {
unsubcribeCalled(ctx);
})

sub.subscribe();
c.connect();

await unsubscribedPromise;
await c.ready()

await new Promise(r => setTimeout(r, 2000));
sub.subscribe();

await subscribedPromise;

let disconnectCalled: any;
const disconnectedPromise = new Promise<DisconnectedContext>((resolve, _) => {
disconnectCalled = resolve;
})
c.on('disconnected', (ctx) => {
disconnectCalled(ctx);
})

c.disconnect();
await disconnectedPromise;
expect(c.state).toBe(State.Disconnected);
});
2 changes: 2 additions & 0 deletions src/centrifuge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,8 @@ export class Centrifuge extends (EventEmitter as new () => TypedEventEmitter<Cli
self._sendConnect(false);
self._sendSubscribeCommands();
self.stopBatching();
//@ts-ignore must be used only for debug and test purposes. Exposed only for non-emulation transport.
self.emit('__centrifuge_debug:connect_frame_sent', {})
},
onError: function (e: any) {
if (self._transportId != transportId) {
Expand Down