Skip to content
Open
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
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "EventSource implementation for React Native. Server-Sent Events (SSE) for iOS and Android.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "node --test"
},
"repository": {
"type": "git",
Expand All @@ -27,4 +27,4 @@
"url": "https://github.com/binaryminds/react-native-sse/issues"
},
"homepage": "https://github.com/binaryminds/react-native-sse#readme"
}
}
6 changes: 3 additions & 3 deletions src/EventSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,10 @@ class EventSource {
};

this.dispatch(eventType, event);

data = [];
type = undefined;
}

data = [];
type = undefined;
}
}
}
Expand Down
87 changes: 87 additions & 0 deletions test/EventSource.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import test from 'node:test';

class MockXMLHttpRequest {
static LOADING = 3;
static DONE = 4;

static latest = null;

constructor() {
MockXMLHttpRequest.latest = this;
this.readyState = 0;
this.status = 0;
this.responseText = '';
}

open() {}

setRequestHeader() {}

send() {}

abort() {}
}

globalThis.XMLHttpRequest = MockXMLHttpRequest;

// The package entry point is CommonJS while the source file is an ES module.
// Loading the source through a data URL lets Node test the real implementation
// without adding a transpiler or another test dependency.
const eventSourceCode = await readFile(new URL('../src/EventSource.js', import.meta.url), 'utf8');
const eventSourceModuleUrl = `data:text/javascript;base64,${Buffer.from(eventSourceCode).toString('base64')}`;
const { default: EventSource } = await import(eventSourceModuleUrl);

function createEventSource() {
const eventSource = new EventSource('https://example.test/events', {
pollingInterval: 0,
timeoutBeforeConnection: 60_000,
});

eventSource.open();

return {
eventSource,
xhr: MockXMLHttpRequest.latest,
};
}

function completeResponse(xhr, responseText) {
xhr.status = 200;
xhr.readyState = MockXMLHttpRequest.DONE;
xhr.responseText = responseText;
xhr.onreadystatechange();
}

test('dispatches a named event to its named listener', (t) => {
const { eventSource, xhr } = createEventSource();
t.after(() => eventSource.close());

const messages = [];
const customEvents = [];

eventSource.addEventListener('message', (event) => messages.push(event.data));
eventSource.addEventListener('custom', (event) => customEvents.push(event.data));

completeResponse(xhr, 'event: custom\ndata: hello\n\n');

assert.deepEqual(messages, []);
assert.deepEqual(customEvents, ['hello']);
});

test('clears an event type when an empty block is dispatched', (t) => {
const { eventSource, xhr } = createEventSource();
t.after(() => eventSource.close());

const messages = [];
const customEvents = [];

eventSource.addEventListener('message', (event) => messages.push(event.data));
eventSource.addEventListener('custom', (event) => customEvents.push(event.data));

completeResponse(xhr, 'event: custom\n\ndata: hello\n\n');

assert.deepEqual(messages, ['hello']);
assert.deepEqual(customEvents, []);
});