@eleven-am/pondsocket 0.1.125 → 0.1.127

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createChannelEvent = exports.createChannelEngine = void 0;
4
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
5
+ const channel_1 = require("./channel");
6
+ const channel_test_1 = require("./channel.test");
7
+ const eventResponse_1 = require("./eventResponse");
8
+ const createChannelEngine = () => {
9
+ const parentEngine = (0, channel_test_1.createParentEngine)();
10
+ return new channel_1.ChannelEngine('test', parentEngine);
11
+ };
12
+ exports.createChannelEngine = createChannelEngine;
13
+ const createChannelEvent = (name) => {
14
+ const responseEvent = {
15
+ event: 'event',
16
+ payload: {
17
+ payload: 'payload',
18
+ },
19
+ sender: 'sender',
20
+ action: pondsocket_common_1.ServerActions.BROADCAST,
21
+ recipients: ['recipient'],
22
+ channelName: name,
23
+ requestId: 'requestId',
24
+ };
25
+ return responseEvent;
26
+ };
27
+ exports.createChannelEvent = createChannelEvent;
28
+ const createChannelResponse = () => {
29
+ const channelEngine = (0, exports.createChannelEngine)();
30
+ const event = (0, exports.createChannelEvent)(channelEngine.name);
31
+ channelEngine.addUser(event.sender, { assign: 'assign' }, () => { });
32
+ channelEngine.addUser(event.recipients[0], { assign: 'assign' }, () => { });
33
+ const response = new eventResponse_1.EventResponse(event, channelEngine);
34
+ return {
35
+ channelEngine,
36
+ event,
37
+ response,
38
+ };
39
+ };
40
+ describe('ChannelResponse', () => {
41
+ it('should create a new ChannelResponse', () => {
42
+ const { response } = createChannelResponse();
43
+ expect(response).toBeDefined();
44
+ });
45
+ it('should accept the request', () => {
46
+ const { response, channelEngine } = createChannelResponse();
47
+ jest.spyOn(channelEngine, 'sendMessage');
48
+ response.accept();
49
+ expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', 'sender', ['recipient'], pondsocket_common_1.ServerActions.BROADCAST, 'event', { payload: 'payload' });
50
+ });
51
+ it('should reject the request', () => {
52
+ const { response, channelEngine, event } = createChannelResponse();
53
+ jest.spyOn(channelEngine, 'sendMessage');
54
+ response.reject();
55
+ expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', pondsocket_common_1.SystemSender.CHANNEL, [event.sender], pondsocket_common_1.ServerActions.ERROR, pondsocket_common_1.ErrorTypes.UNAUTHORIZED_BROADCAST, {
56
+ message: 'Unauthorized request',
57
+ code: 403,
58
+ });
59
+ });
60
+ it('should send a direct message', () => {
61
+ const { response, channelEngine, event } = createChannelResponse();
62
+ jest.spyOn(channelEngine, 'sendMessage');
63
+ response.send('event', { payload: 'payload' });
64
+ expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', pondsocket_common_1.SystemSender.CHANNEL, [event.sender], pondsocket_common_1.ServerActions.SYSTEM, 'event', { payload: 'payload' });
65
+ });
66
+ it('should broadcast a message', () => {
67
+ const { response, channelEngine } = createChannelResponse();
68
+ jest.spyOn(channelEngine, 'sendMessage');
69
+ response.broadcast('event', { payload: 'payload' });
70
+ expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', 'sender', pondsocket_common_1.ChannelReceiver.ALL_USERS, pondsocket_common_1.ServerActions.BROADCAST, 'event', { payload: 'payload' });
71
+ });
72
+ it('should broadcastFromUser a message', () => {
73
+ const { response, channelEngine } = createChannelResponse();
74
+ jest.spyOn(channelEngine, 'sendMessage');
75
+ response.broadcastFromUser('event', { payload: 'payload' });
76
+ expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', 'sender', pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER, pondsocket_common_1.ServerActions.BROADCAST, 'event', { payload: 'payload' });
77
+ });
78
+ it('should sendToUsers a message', () => {
79
+ const { response, channelEngine } = createChannelResponse();
80
+ jest.spyOn(channelEngine, 'sendMessage');
81
+ response.sendToUsers('event', { payload: 'payload' }, ['recipient']);
82
+ expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', 'sender', ['recipient'], pondsocket_common_1.ServerActions.BROADCAST, 'event', { payload: 'payload' });
83
+ });
84
+ it('should fail to send to non existing users', () => {
85
+ const { event, response, channelEngine } = createChannelResponse();
86
+ jest.spyOn(channelEngine, 'sendMessage');
87
+ event.recipients = ['non_existing_user'];
88
+ expect(() => response.accept()).toThrow('ChannelEngine: Invalid recipients non_existing_user some users do not exist in channel test');
89
+ expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', event.sender, ['non_existing_user'], pondsocket_common_1.ServerActions.BROADCAST, event.event, event.payload);
90
+ expect(() => response.sendToUsers('event', { payload: 'payload' }, ['non_existing_user']))
91
+ .toThrow('ChannelEngine: Invalid recipients non_existing_user some users do not exist in channel test');
92
+ });
93
+ it('should track a trackPresence', () => {
94
+ const { response, channelEngine } = createChannelResponse();
95
+ jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
96
+ response.trackPresence({ status: 'online' });
97
+ expect(channelEngine.presenceEngine.trackPresence).toHaveBeenCalledWith('sender', { status: 'online' });
98
+ });
99
+ it('should update a users assign data', () => {
100
+ const { response, channelEngine } = createChannelResponse();
101
+ jest.spyOn(channelEngine, 'updateAssigns');
102
+ response.accept({ assign: 'updated' });
103
+ expect(channelEngine.updateAssigns).toHaveBeenCalledWith('sender', { assign: 'updated' });
104
+ });
105
+ it('should evict a user', () => {
106
+ const { response, channelEngine } = createChannelResponse();
107
+ jest.spyOn(channelEngine, 'kickUser');
108
+ response.evictUser('recipient');
109
+ expect(channelEngine.kickUser).toHaveBeenCalledWith('sender', 'recipient');
110
+ });
111
+ it('should destroy the channel', () => {
112
+ const { response, channelEngine } = createChannelResponse();
113
+ jest.spyOn(channelEngine, 'destroy');
114
+ response.closeChannel('recipient');
115
+ expect(channelEngine.destroy).toHaveBeenCalledWith('recipient');
116
+ });
117
+ it('should call the presence engine when the trackPresence is called', () => {
118
+ const { response, channelEngine } = createChannelResponse();
119
+ jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
120
+ expect(channelEngine.presenceEngine.trackPresence).not.toHaveBeenCalled();
121
+ response.accept();
122
+ response.trackPresence({ status: 'online' });
123
+ expect(channelEngine.presenceEngine.trackPresence).toHaveBeenCalledWith('sender', { status: 'online' });
124
+ });
125
+ it('should throw an error if trackPresence is called twice', () => {
126
+ const { response, channelEngine } = createChannelResponse();
127
+ jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
128
+ expect(channelEngine.presenceEngine.trackPresence).not.toHaveBeenCalled();
129
+ response.accept();
130
+ response.trackPresence({ status: 'online' });
131
+ expect(channelEngine.presenceEngine.trackPresence).toHaveBeenCalledWith('sender', { status: 'online' });
132
+ expect(() => response.trackPresence({ status: 'online' })).toThrow('PresenceEngine: Presence with key sender already exists');
133
+ });
134
+ it('should throw an error if trackPresence is called for a non existing user', () => {
135
+ const { response, channelEngine } = createChannelResponse();
136
+ jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
137
+ expect(channelEngine.presenceEngine.trackPresence).not.toHaveBeenCalled();
138
+ response.accept();
139
+ expect(() => response.trackPresence({ status: 'online' }, 'non_existent_user'))
140
+ .toThrow('ChannelEngine: Invalid recipients non_existent_user some users do not exist in channel test');
141
+ });
142
+ it('should update the presence of a user that is already tracked', () => {
143
+ var _a, _b;
144
+ const { response, channelEngine } = createChannelResponse();
145
+ jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
146
+ expect(channelEngine.presenceEngine.trackPresence).not.toHaveBeenCalled();
147
+ response.accept();
148
+ response.trackPresence({ status: 'online' });
149
+ expect(channelEngine.presenceEngine.trackPresence).toHaveBeenCalledWith('sender', { status: 'online' });
150
+ expect((_a = channelEngine.presenceEngine) === null || _a === void 0 ? void 0 : _a.getPresence()).toEqual({
151
+ sender: { status: 'online' },
152
+ });
153
+ response.updatePresence({ status: 'offline' });
154
+ expect((_b = channelEngine.presenceEngine) === null || _b === void 0 ? void 0 : _b.getPresence()).toEqual({
155
+ sender: { status: 'offline' },
156
+ });
157
+ });
158
+ it('should throw an error if updatePresence is called for a non existing user', () => {
159
+ const { response, channelEngine } = createChannelResponse();
160
+ jest.spyOn(channelEngine.presenceEngine, 'trackPresence');
161
+ expect(channelEngine.presenceEngine.trackPresence).not.toHaveBeenCalled();
162
+ response.accept();
163
+ response.trackPresence({ status: 'online' });
164
+ expect(() => response.updatePresence({ status: 'online' }, 'non_existent_user'))
165
+ .toThrow('PresenceEngine: Presence with key non_existent_user does not exist');
166
+ });
167
+ it('should unTrack a trackPresence', () => {
168
+ var _a, _b;
169
+ const { response, channelEngine } = createChannelResponse();
170
+ response.trackPresence({ status: 'online' });
171
+ expect((_a = channelEngine.presenceEngine) === null || _a === void 0 ? void 0 : _a.getPresence()).toEqual({
172
+ sender: { status: 'online' },
173
+ });
174
+ response.unTrackPresence();
175
+ expect((_b = channelEngine.presenceEngine) === null || _b === void 0 ? void 0 : _b.getPresence()).toEqual({});
176
+ });
177
+ it('should throw an error if unTrackPresence is called for a non existing user', () => {
178
+ var _a;
179
+ const { response, channelEngine } = createChannelResponse();
180
+ response.trackPresence({ status: 'online' });
181
+ expect((_a = channelEngine.presenceEngine) === null || _a === void 0 ? void 0 : _a.getPresence()).toEqual({
182
+ sender: { status: 'online' },
183
+ });
184
+ expect(() => response.unTrackPresence('non_existent_user'))
185
+ .toThrow('PresenceEngine: Presence with key non_existent_user does not exist');
186
+ });
187
+ it('should throw an error if accept, reject / send is called more than once', () => {
188
+ const { response, channelEngine } = createChannelResponse();
189
+ jest.spyOn(channelEngine, 'sendMessage');
190
+ expect(channelEngine.sendMessage).not.toHaveBeenCalled();
191
+ response.accept();
192
+ expect(channelEngine.sendMessage).toHaveBeenCalledWith('requestId', 'sender', ['recipient'], pondsocket_common_1.ServerActions.BROADCAST, 'event', { payload: 'payload' });
193
+ expect(() => response.accept()).toThrow('Event response has already been executed');
194
+ expect(() => response.reject()).toThrow('Event response has already been executed');
195
+ expect(() => response.send('event', { payload: 'payload' })).toThrow('Event response has already been executed');
196
+ });
197
+ });
@@ -10,16 +10,18 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _Endpoint_instances, _Endpoint_middleware, _Endpoint_channels, _Endpoint_sockets, _Endpoint_sendMessage, _Endpoint_joinChannel, _Endpoint_execute, _Endpoint_handleMessage, _Endpoint_readMessage, _Endpoint_isObjectEmpty;
13
+ var _Endpoint_instances, _Endpoint_middleware, _Endpoint_channels, _Endpoint_sockets, _Endpoint_sendMessage, _Endpoint_joinChannel, _Endpoint_execute, _Endpoint_handleMessage, _Endpoint_readMessage;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.Endpoint = void 0;
16
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
17
+ const zod_1 = require("zod");
16
18
  const middleware_1 = require("../abstracts/middleware");
17
- const enums_1 = require("../enums");
18
19
  const pondError_1 = require("../errors/pondError");
19
20
  const joinRequest_1 = require("../lobby/joinRequest");
20
21
  const joinResponse_1 = require("../lobby/joinResponse");
21
22
  const lobby_1 = require("../lobby/lobby");
22
23
  const matcher_1 = require("../matcher/matcher");
24
+ const schema_1 = require("../schema");
23
25
  class Endpoint {
24
26
  constructor() {
25
27
  _Endpoint_instances.add(this);
@@ -83,8 +85,9 @@ class Endpoint {
83
85
  const message = {
84
86
  event,
85
87
  payload,
86
- action: enums_1.ServerActions.BROADCAST,
87
- channelName: enums_1.SystemSender.ENDPOINT,
88
+ requestId: (0, pondsocket_common_1.uuid)(),
89
+ action: pondsocket_common_1.ServerActions.BROADCAST,
90
+ channelName: pondsocket_common_1.SystemSender.ENDPOINT,
88
91
  };
89
92
  __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_sendMessage).call(this, socket, message);
90
93
  });
@@ -125,8 +128,8 @@ class Endpoint {
125
128
  exports.Endpoint = Endpoint;
126
129
  _Endpoint_middleware = new WeakMap(), _Endpoint_channels = new WeakMap(), _Endpoint_sockets = new WeakMap(), _Endpoint_instances = new WeakSet(), _Endpoint_sendMessage = function _Endpoint_sendMessage(socket, message) {
127
130
  socket.send(JSON.stringify(message));
128
- }, _Endpoint_joinChannel = function _Endpoint_joinChannel(channel, socket, joinParams) {
129
- const cache = Object.assign(Object.assign({}, socket), { channelName: channel });
131
+ }, _Endpoint_joinChannel = function _Endpoint_joinChannel(channel, socket, joinParams, requestId) {
132
+ const cache = Object.assign(Object.assign({}, socket), { requestId, channelName: channel });
130
133
  __classPrivateFieldGet(this, _Endpoint_middleware, "f").run(cache, joinParams, () => {
131
134
  throw new pondError_1.EndpointError(`GatewayEngine: Channel ${channel} does not exist`, 404);
132
135
  });
@@ -141,15 +144,15 @@ _Endpoint_middleware = new WeakMap(), _Endpoint_channels = new WeakMap(), _Endpo
141
144
  throw new Error(`GatewayEngine: Channel ${channel} does not exist`);
142
145
  }, _Endpoint_handleMessage = function _Endpoint_handleMessage(cache, message) {
143
146
  switch (message.action) {
144
- case enums_1.ClientActions.JOIN_CHANNEL:
145
- __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_joinChannel).call(this, message.channelName, cache, message.payload);
147
+ case pondsocket_common_1.ClientActions.JOIN_CHANNEL:
148
+ __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_joinChannel).call(this, message.channelName, cache, message.payload, message.requestId);
146
149
  break;
147
- case enums_1.ClientActions.LEAVE_CHANNEL:
150
+ case pondsocket_common_1.ClientActions.LEAVE_CHANNEL:
148
151
  __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_execute).call(this, message.channelName, (channel) => {
149
152
  channel.removeUser(cache.clientId);
150
153
  });
151
154
  break;
152
- case enums_1.ClientActions.BROADCAST:
155
+ case pondsocket_common_1.ClientActions.BROADCAST:
153
156
  __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_execute).call(this, message.channelName, (channel) => {
154
157
  channel.broadcastMessage(cache.clientId, message);
155
158
  });
@@ -159,49 +162,37 @@ _Endpoint_middleware = new WeakMap(), _Endpoint_channels = new WeakMap(), _Endpo
159
162
  }
160
163
  }, _Endpoint_readMessage = function _Endpoint_readMessage(cache, message) {
161
164
  const errorMessage = {
162
- event: enums_1.ErrorTypes.INVALID_MESSAGE,
163
- action: enums_1.ServerActions.ERROR,
164
- channelName: enums_1.SystemSender.ENDPOINT,
165
+ event: pondsocket_common_1.ErrorTypes.INVALID_MESSAGE,
166
+ action: pondsocket_common_1.ServerActions.ERROR,
167
+ channelName: pondsocket_common_1.SystemSender.ENDPOINT,
168
+ requestId: (0, pondsocket_common_1.uuid)(),
165
169
  payload: {},
166
170
  };
167
171
  try {
168
172
  const data = JSON.parse(message);
169
- if (!data.action) {
170
- errorMessage.payload = {
171
- message: 'No action provided',
172
- };
173
- }
174
- else if (!data.channelName) {
175
- errorMessage.payload = {
176
- message: 'No channel name provided',
177
- };
178
- }
179
- else if (!data.payload) {
173
+ const result = schema_1.clientMessageSchema.parse(data);
174
+ __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_handleMessage).call(this, cache, result);
175
+ }
176
+ catch (e) {
177
+ if (e instanceof zod_1.ZodError) {
180
178
  errorMessage.payload = {
181
- message: 'No payload provided',
179
+ message: e.message,
180
+ code: 400,
182
181
  };
183
182
  }
184
- if (!__classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_isObjectEmpty).call(this, errorMessage.payload)) {
185
- __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_sendMessage).call(this, cache.socket, errorMessage);
186
- }
187
- else {
188
- __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_handleMessage).call(this, cache, data);
189
- }
190
- }
191
- catch (e) {
192
- if (e instanceof SyntaxError) {
183
+ else if (e instanceof SyntaxError) {
193
184
  errorMessage.payload = {
194
185
  message: 'Invalid JSON',
195
186
  };
196
187
  }
197
188
  else if (e instanceof Error) {
198
- errorMessage.event = enums_1.ErrorTypes.INTERNAL_SERVER_ERROR;
189
+ errorMessage.event = pondsocket_common_1.ErrorTypes.INTERNAL_SERVER_ERROR;
199
190
  errorMessage.payload = {
200
191
  message: e.message,
201
192
  };
202
193
  }
203
194
  else if (e instanceof pondError_1.PresenceError) {
204
- errorMessage.event = enums_1.ErrorTypes.PRESENCE_ERROR;
195
+ errorMessage.event = pondsocket_common_1.ErrorTypes.PRESENCE_ERROR;
205
196
  errorMessage.channelName = e.channel;
206
197
  errorMessage.payload = {
207
198
  message: e.message,
@@ -210,7 +201,7 @@ _Endpoint_middleware = new WeakMap(), _Endpoint_channels = new WeakMap(), _Endpo
210
201
  };
211
202
  }
212
203
  else if (e instanceof pondError_1.ChannelError) {
213
- errorMessage.event = enums_1.ErrorTypes.CHANNEL_ERROR;
204
+ errorMessage.event = pondsocket_common_1.ErrorTypes.CHANNEL_ERROR;
214
205
  errorMessage.channelName = e.channel;
215
206
  errorMessage.payload = {
216
207
  message: e.message,
@@ -218,14 +209,17 @@ _Endpoint_middleware = new WeakMap(), _Endpoint_channels = new WeakMap(), _Endpo
218
209
  };
219
210
  }
220
211
  else if (e instanceof pondError_1.EndpointError) {
221
- errorMessage.event = enums_1.ErrorTypes.ENDPOINT_ERROR;
212
+ errorMessage.event = pondsocket_common_1.ErrorTypes.ENDPOINT_ERROR;
222
213
  errorMessage.payload = {
223
214
  message: e.message,
224
215
  code: e.code,
225
216
  };
226
217
  }
218
+ else {
219
+ errorMessage.payload = {
220
+ message: 'Unknown error',
221
+ };
222
+ }
227
223
  __classPrivateFieldGet(this, _Endpoint_instances, "m", _Endpoint_sendMessage).call(this, cache.socket, errorMessage);
228
224
  }
229
- }, _Endpoint_isObjectEmpty = function _Endpoint_isObjectEmpty(obj) {
230
- return Object.keys(obj).length === 0;
231
225
  };
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
16
+ const superwstest_1 = __importDefault(require("superwstest"));
17
+ const pondSocket_1 = require("../server/pondSocket");
18
+ /* eslint-disable line-comment-position, no-inline-comments */
19
+ describe('endpoint', () => {
20
+ let socket;
21
+ let server;
22
+ beforeEach((done) => {
23
+ socket = new pondSocket_1.PondSocket();
24
+ server = socket.listen(3000, 'localhost', done);
25
+ });
26
+ afterEach((done) => {
27
+ server.close(done);
28
+ });
29
+ it('should be able to close a single socket', () => __awaiter(void 0, void 0, void 0, function* () {
30
+ let count = 0;
31
+ const endpoint = socket.createEndpoint('/api/:room', (req, res) => {
32
+ if (req.params.room === 'socket') {
33
+ res.accept();
34
+ count++;
35
+ setTimeout(() => {
36
+ endpoint.closeConnection(req.id);
37
+ }, 1000);
38
+ }
39
+ else {
40
+ res.reject();
41
+ }
42
+ });
43
+ yield (0, superwstest_1.default)(server)
44
+ .ws('/api/socket')
45
+ .expectUpgrade((res) => expect(res.statusCode).toBe(101))
46
+ .wait(200)
47
+ .expectClosed();
48
+ expect(count).toBe(1);
49
+ }));
50
+ it('should be able to list connections', () => __awaiter(void 0, void 0, void 0, function* () {
51
+ const endpoint = socket.createEndpoint('/api/:room', (req, res) => {
52
+ if (req.params.room === 'socket') {
53
+ res.accept();
54
+ const connections = endpoint.listConnections();
55
+ expect(connections).toHaveLength(1);
56
+ }
57
+ else {
58
+ res.reject();
59
+ }
60
+ });
61
+ yield (0, superwstest_1.default)(server)
62
+ .ws('/api/socket')
63
+ .expectUpgrade((res) => expect(res.statusCode).toBe(101));
64
+ }));
65
+ it('should be able to refuse connections to the endpoint', () => __awaiter(void 0, void 0, void 0, function* () {
66
+ let count = 0;
67
+ socket.createEndpoint('/api/:path', (req, res) => {
68
+ count++;
69
+ expect(req.params.path).toBe('socket');
70
+ res.reject();
71
+ });
72
+ yield (0, superwstest_1.default)(server)
73
+ .ws('/api/socket')
74
+ .expectUpgrade((res) => expect(res.statusCode).toBe(101)) // the connection is still upgraded, so we can send error messages
75
+ .expectMessage(expect.objectContaining({
76
+ action: pondsocket_common_1.ServerActions.ERROR,
77
+ event: pondsocket_common_1.ErrorTypes.UNAUTHORIZED_CONNECTION,
78
+ channelName: pondsocket_common_1.SystemSender.ENDPOINT,
79
+ payload: {
80
+ message: 'Unauthorized connection',
81
+ code: 401,
82
+ },
83
+ }))
84
+ .expectClosed();
85
+ expect(count).toBe(1);
86
+ }));
87
+ it('should be able to send a message to all connection', () => __awaiter(void 0, void 0, void 0, function* () {
88
+ const endpoint = socket.createEndpoint('/api/:room', (req, res) => {
89
+ if (req.params.room === 'socket') {
90
+ res.accept();
91
+ const connections = endpoint.listConnections();
92
+ expect(connections).toHaveLength(1);
93
+ endpoint.broadcast('TEST', { test: 'test' });
94
+ }
95
+ else {
96
+ res.reject();
97
+ }
98
+ });
99
+ yield (0, superwstest_1.default)(server)
100
+ .ws('/api/socket')
101
+ .expectUpgrade((res) => expect(res.statusCode).toBe(101))
102
+ .expectMessage(expect.objectContaining({
103
+ event: 'TEST',
104
+ action: pondsocket_common_1.ServerActions.BROADCAST,
105
+ channelName: pondsocket_common_1.SystemSender.ENDPOINT,
106
+ payload: {
107
+ test: 'test',
108
+ },
109
+ }));
110
+ }));
111
+ it('should be able to accept connections on this handler', () => __awaiter(void 0, void 0, void 0, function* () {
112
+ const message = {
113
+ action: pondsocket_common_1.ClientActions.JOIN_CHANNEL,
114
+ channelName: '/test/socket',
115
+ event: 'TEST',
116
+ payload: {},
117
+ };
118
+ const endpoint = socket.createEndpoint('/api/:room', (req, res) => {
119
+ if (req.params.room === 'socket') {
120
+ res.accept();
121
+ }
122
+ else {
123
+ res.reject();
124
+ }
125
+ });
126
+ endpoint.createChannel('/test/:room', (req, res) => {
127
+ expect(req.event.params.room).toBeDefined();
128
+ res.accept({
129
+ assigns: {
130
+ status: 'online',
131
+ },
132
+ });
133
+ });
134
+ yield (0, superwstest_1.default)(server)
135
+ .ws('/api/socket')
136
+ .expectUpgrade((res) => expect(res.statusCode).toBe(101))
137
+ .sendJson(message)
138
+ .close()
139
+ .expectClosed();
140
+ yield (0, superwstest_1.default)(server)
141
+ .ws('/api/socket')
142
+ .expectUpgrade((res) => expect(res.statusCode).toBe(101))
143
+ .sendJson(Object.assign(Object.assign({}, message), { channelName: '/socket/socket' }))
144
+ .expectMessage(expect.objectContaining({
145
+ action: pondsocket_common_1.ServerActions.SYSTEM,
146
+ channelName: '/socket/socket',
147
+ event: pondsocket_common_1.Events.ACKNOWLEDGE,
148
+ payload: {},
149
+ }))
150
+ .close()
151
+ .expectClosed();
152
+ }));
153
+ it('should send an error when the channel exists but other things happen', () => __awaiter(void 0, void 0, void 0, function* () {
154
+ const message = {
155
+ action: pondsocket_common_1.ClientActions.JOIN_CHANNEL,
156
+ channelName: '/test/socket',
157
+ event: 'TEST',
158
+ payload: {},
159
+ };
160
+ const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
161
+ res.accept();
162
+ });
163
+ endpoint.createChannel('/test/:room', (req, res) => {
164
+ expect(req.event.params.room).toBeDefined();
165
+ res.reject('Something went wrong');
166
+ });
167
+ yield (0, superwstest_1.default)(server)
168
+ .ws('/api/socket')
169
+ .expectUpgrade((res) => expect(res.statusCode).toBe(101))
170
+ .sendJson(message)
171
+ .expectMessage(expect.objectContaining({
172
+ action: pondsocket_common_1.ServerActions.ERROR,
173
+ channelName: '/test/socket',
174
+ event: pondsocket_common_1.ErrorTypes.UNAUTHORIZED_JOIN_REQUEST,
175
+ payload: {
176
+ message: 'Request to join channel /test/socket rejected: Something went wrong',
177
+ code: 403,
178
+ },
179
+ }))
180
+ .close()
181
+ .expectClosed();
182
+ }));
183
+ it('should be able to track the presence of its users', () => __awaiter(void 0, void 0, void 0, function* () {
184
+ const message = {
185
+ action: pondsocket_common_1.ClientActions.JOIN_CHANNEL,
186
+ channelName: '/test/socket',
187
+ event: 'TEST',
188
+ payload: {},
189
+ };
190
+ const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
191
+ res.accept();
192
+ });
193
+ endpoint.createChannel('/test/:room', (req, res) => {
194
+ expect(req.event.params.room).toBeDefined();
195
+ res
196
+ .accept()
197
+ .trackPresence({
198
+ status: 'online',
199
+ });
200
+ });
201
+ yield (0, superwstest_1.default)(server)
202
+ .ws('/api/socket')
203
+ .expectUpgrade((res) => expect(res.statusCode).toBe(101))
204
+ .sendJson(message)
205
+ .expectMessage(expect.objectContaining({
206
+ action: pondsocket_common_1.ServerActions.SYSTEM,
207
+ channelName: '/test/socket',
208
+ event: pondsocket_common_1.Events.ACKNOWLEDGE,
209
+ payload: {},
210
+ }))
211
+ .close();
212
+ }));
213
+ it('should throw an error if accept, reject / send is called more than once', () => __awaiter(void 0, void 0, void 0, function* () {
214
+ socket.createEndpoint('/api/:room', (_, res) => {
215
+ res.send('hello', {
216
+ test: 'test',
217
+ });
218
+ expect(() => res.accept()).toThrowError('Cannot execute response more than once');
219
+ });
220
+ yield (0, superwstest_1.default)(server)
221
+ .ws('/api/socket')
222
+ .expectUpgrade((res) => expect(res.statusCode).toBe(101))
223
+ .expectMessage(expect.objectContaining({
224
+ action: pondsocket_common_1.ServerActions.BROADCAST,
225
+ channelName: pondsocket_common_1.SystemSender.ENDPOINT,
226
+ event: 'hello',
227
+ payload: {
228
+ test: 'test',
229
+ },
230
+ }));
231
+ }));
232
+ it('should be able to connect, join a channel and send a message', () => __awaiter(void 0, void 0, void 0, function* () {
233
+ const message = {
234
+ action: pondsocket_common_1.ClientActions.JOIN_CHANNEL,
235
+ channelName: '/test/socket',
236
+ event: 'TEST',
237
+ payload: {},
238
+ };
239
+ const endpoint = socket.createEndpoint('/api/:room', (_, res) => {
240
+ res.accept();
241
+ });
242
+ const channel = endpoint.createChannel('/test/:room', (req, res) => {
243
+ expect(req.event.params.room).toBeDefined();
244
+ res.accept();
245
+ });
246
+ channel.onEvent('echo', (req, res) => {
247
+ res.send('echo', req.event.payload);
248
+ });
249
+ channel.onEvent('broadcast', (req) => {
250
+ channel.broadcast('broadcast', Object.assign(Object.assign({}, req.event.payload), { broadcast: true }));
251
+ });
252
+ yield (0, superwstest_1.default)(server)
253
+ .ws('/api/socket')
254
+ .expectUpgrade((res) => expect(res.statusCode).toBe(101))
255
+ .sendJson(message)
256
+ .expectMessage(expect.objectContaining({
257
+ action: pondsocket_common_1.ServerActions.SYSTEM,
258
+ channelName: '/test/socket',
259
+ event: pondsocket_common_1.Events.ACKNOWLEDGE,
260
+ payload: {},
261
+ }))
262
+ .sendJson({
263
+ addresses: pondsocket_common_1.ChannelReceiver.ALL_EXCEPT_SENDER,
264
+ action: pondsocket_common_1.ClientActions.BROADCAST,
265
+ channelName: '/test/socket',
266
+ event: 'echo',
267
+ payload: {
268
+ test: 'test',
269
+ },
270
+ })
271
+ .expectMessage(expect.objectContaining({
272
+ action: pondsocket_common_1.ServerActions.SYSTEM,
273
+ channelName: '/test/socket',
274
+ event: 'echo',
275
+ payload: {
276
+ test: 'test',
277
+ },
278
+ }))
279
+ .sendJson({
280
+ action: pondsocket_common_1.ClientActions.BROADCAST,
281
+ channelName: '/test/socket',
282
+ event: 'broadcast',
283
+ payload: {
284
+ test: 'test',
285
+ },
286
+ })
287
+ .expectMessage(expect.objectContaining({
288
+ action: pondsocket_common_1.ServerActions.SYSTEM,
289
+ channelName: '/test/socket',
290
+ event: 'broadcast',
291
+ payload: {
292
+ test: 'test',
293
+ broadcast: true,
294
+ },
295
+ }));
296
+ }));
297
+ });