mocksse
v1.0.4
Published
Allows testing of EventSource / Server Sent Events
Downloads
18,462
Maintainers
Readme
MockSSE
This project is a port/rewrite of MockEvent (which targets the browser). Instead, this project was designed for mocking EventSource (specifically the npm package eventsource) /Server Sent Events (SSE) where both your server side and client side are written for the NodeJS platform.
MockSSE simulates SSE.
Useful if you want to:
- Build the client side without having the server side available to you
- Or simply unit testing -> C/I, rather than integration tests
This project has no dependencies other than native modules.
Install
npm install mocksse --save-dev
Usage
All examples include:
- How to instantiate a
MockEvent
which streams the data - How to instantiate an
EventSource
which consumes the data - Adding at least one event listener
As well as the following examples:
- The tests demonstrate how to use the project along with the feature set
- The project that uses
mocksse
for testing the client side of its server sent events (SSE) can be seen at the purpleteam repository
Example 0
Getting started with the least amount of work (based on test should handle an event to relative url
).
const { MockEvent, EventSource } = require('mocksse');
// Instantiate a MockEvent.
new MockEvent({
url: '/your-relative-or-absolute-url',
responses: [
{ type: 'a message event', data: 'a short message' }
]
});
// Instantiate an EventSource.
const evtSource = new EventSource('/your-relative-or-absolute-url');
// Listen for a "a message event" event and handle appropriately.
evtSource.addEventListener('a message event', (event) => {
// event.type === 'a message event'
// event.data === 'a short message'
});
Example 1
Multiple event listeners (based on test should handle an event with setInterval, and collection of full responses).
const { MockEvent, EventSource } = require('mocksse');
// Instantiate a MockEvent.
new MockEvent({
url: 'http://noPlaceLikeHome:2000/your-route',
setInterval: 10,
responses: [
{ lastEventId: 'event Id One', type: 'progressEvent', data: { progress: 'Look mum, I am making great progress' } },
{ lastEventId: 'event Id Two', type: 'pctCompleteEvent', data: { pctComplete: 11 } },
{ lastEventId: 'event Id three', type: 'temperatureEvent', data: { temperature: 25 } }
]
});
// Instantiate an EventSource.
const evtSource = new EventSource('http://noPlaceLikeHome:2000/your-route');
// Listen for multiple events and handle appropriately.
evtSource.onopen = (event) => { // Optionally subscribing to the open event
// You can see this event in mocksse.js.
// event === { message: 'The opening message.', anotherCustomeProp: { prop: 'whatever' } }
};
evtSource.addEventListener('progressEvent', (event) => {
// event.type === 'progressEvent'
// event.data === { progress: 'Look mum, I am making great progress' }
// event.origin === 'http://noPlaceLikeHome:2000'
// event.lastEventId === 'event Id One'
});
evtSource.addEventListener('pctCompleteEvent', (event) => {
// event.type === 'pctCompleteEvent'
// event.data === { pctComplete: 11 }
// event.origin === 'http://noPlaceLikeHome:2000'
// event.lastEventId === 'event Id Two'
});
evtSource.addEventListener('temperatureEvent', (event) => {
// event.type === 'temperatureEvent'
// event.data === { temperature: 25 }
// event.origin === 'http://noPlaceLikeHome:2000'
// event.lastEventId === 'event Id three'
});
url
: The relative or full URL for your Server Sent Event API. This is the URL we will subscribe to viaEventSource
setInterval
: Miliseconds to wait before sending the next event/responseresponses
: A list of event/responses to send and the order in which to send themlastEventId
can be set and readtype
: Server Sent Events can have a name that you directly subscribe to in case you want to handle that name differently. In the above example we require you to subscribe to 3 different namesprogressEvent
,pctCompleteEvent
, andtemperatureEvent
. A working example of this can be seen in the purpleteam projectdata
: The data you want to send
Example 2
Dynamically make responses and then have them stream
ed (based on test response function should be called, which then sends event).
const { MockEvent, EventSource } = require('mocksse');
// Instantiate a MockEvent.
new MockEvent({
url: 'http://noPlaceLikeHome:2000/your-route',
setInterval: [100, 200],
response: (mockEvent, evtSource) => {
const data = [
{ lastEventId: 'event Id One', type: 'yourEvent', data: { yourProp: 'Wish I was done!' } },
{ lastEventId: 'event Id Two', type: 'yourEvent', data: { yourProp: 'Oh, wow, nearly done!' } }
];
// In this case we have static data, but you can build that data
// however you choose and then stream it when you're ready.
mockEvent.stream(data);
}
});
// Instantiate an EventSource.
const evtSource = new EventSource('http://noPlaceLikeHome:2000/your-route');
// Listen for a "yourEvent" event and handle appropriately.
evtSource.addEventListener('yourEvent', (event) => {
// On first invocation: event === { origin: 'http://noPlaceLikeHome:2000, lastEventId: 'event Id One', type: 'yourEvent', data: { yourProp: 'Wish I was done!' } }
// On second invocation: event === { origin: 'http://noPlaceLikeHome:2000, lastEventId: 'event Id Two', type: 'yourEvent', data: { yourProp: 'Oh, wow, nearly done!' } }
});
This uses the response
attribute instead of the plural responses
method. Here you can build build a list of responses to send and then stream them when you're ready.
The stream
method respects the setInterval
property you specified. Also notice that setInterval
can be set to an int
, float
, or array
representing a min/max range of milliseconds.
Technically you can use any method and then call handler.stream
. The benefit of using the response
hook is that you get the mockEvent
and evtSource
object in case you need those values for anything. Example 3 shows how you can benefit from these objects.
Example 3
Dynamically make responses and then stream
them yourself within your response
function (based on test response function should be called, which then streams events itself).
const { MockEvent, EventSource } = require('mocksse');
// Instantiate a MockEvent.
new MockEvent({
url: 'http://noPlaceLikeHome:2000/your-route',
setInterval: [100, 200],
response: (mockEvent, evtSource) => {
const data = [
{ lastEventId: 'event Id One', type: 'yourEvent', data: { yourProp: 'Wish I was done!' } },
{ lastEventId: 'event Id Two', type: 'yourEvent', data: { yourProp: 'Oh, wow, nearly done!' } }
];
// In this case we have static data, but you can build that data
// however you choose and then stream it when you're ready.
const intervalId = setInterval(() => {
const responseData = data.shift() || clearInterval(intervalId);
if (responseData) mockEvent.dispatchEvent(responseData);
}, mockEvent.setInterval);
}
});
// Instantiate an EventSource.
const evtSource = new EventSource('http://noPlaceLikeHome:2000/your-route');
// Listen for a "yourEvent" event and handle appropriately.
evtSource.addEventListener('yourEvent', (event) => {
// On first invocation: event === { origin: 'http://noPlaceLikeHome:2000, lastEventId: 'event Id One', type: 'yourEvent', data: { yourProp: 'Wish I was done!' } }
// On second invocation: event === { origin: 'http://noPlaceLikeHome:2000, lastEventId: 'event Id Two', type: 'yourEvent', data: { yourProp: 'Oh, wow, nearly done!' } }
});
Here we write our own stream
method that loops through data and sends. Still respecting the setInterval
attribute and leveraging the internal dispatchEvent
method of the mockEvent
. This is not recommended, it's just used as an example to show the amount of access you have to all attributes. Using the dispatchEvent
method directly overwrites the stream
attribute and will not respect other queues that maybe set by you later.
Example 4
Closing the EventSource then subscribing to an event will invoke the error handler if you have subscribed to onerror
(based on test closing the EventSource then subscribing to an event should invoke the error handler
).
const { MockEvent, EventSource } = require('mocksse');
// Instantiate a MockEvent.
const mockEvent = new MockEvent({
url: 'http://noPlaceLikeHome:2000/your-route',
verbose: true, // Feel free to turn verbosity on.
responses: [
{ type: 'a message event', data: 'a short message' }
]
});
// Instantiate an EventSource.
const evtSource = new EventSource('http://noPlaceLikeHome:2000/your-route');
evtSource.close();
// Listen for a "a message event" event and handle appropriately.
evtSource.addEventListener('a message event', (event) => {
// The event handler will not be invoked on a closed EventSource.
});
evtSource.onerror = (error) => {
// Expect to see the following message
// error.message === '`EventSource` instance closed while sending.'
};
Contribution
Please open an issue to discus the proposed change before submitting a merge request.
Acknowledgements
This project is a port/rewrite of MockEvent, which targets the browser.
Inspiration was also taken from eventsourcemock, which is also browser focussed and very minimal.
License
Copyright Kim Carter and other contributors, Licensed under MIT.