mobility-toolbox-js 2.0.0 → 2.0.1-beta.13

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.
Files changed (102) hide show
  1. package/api/RoutingAPI.js +15 -0
  2. package/api/RoutingAPI.test.js +25 -0
  3. package/api/StopsAPI.js +12 -0
  4. package/api/StopsAPI.test.js +22 -0
  5. package/api/TralisAPI.js +359 -0
  6. package/api/TralisAPI.test.js +67 -0
  7. package/api/{tralis/TralisAPIUtils.js → TralisAPIUtils.js} +2 -32
  8. package/api/index.js +3 -3
  9. package/{ol/README.md → api/typedefs.js} +0 -0
  10. package/common/Tracker.js +14 -118
  11. package/common/api/HttpAPI.js +30 -0
  12. package/common/api/HttpAPI.test.js +50 -0
  13. package/common/api/WebSocketAPI.js +175 -0
  14. package/{api/tralis/WebSocketConnector.test.js → common/api/WebSocketAPI.test.js} +100 -145
  15. package/common/controls/Control.js +26 -91
  16. package/common/controls/Control.test.js +32 -43
  17. package/common/index.js +4 -0
  18. package/common/layers/Layer.js +53 -244
  19. package/common/layers/Layer.test.js +185 -244
  20. package/common/mixins/CopyrightMixin.js +20 -44
  21. package/common/mixins/SearchMixin.js +100 -166
  22. package/common/mixins/TralisLayerMixin.js +443 -894
  23. package/common/styles/index.js +4 -4
  24. package/common/styles/trackerDefaultStyle.js +39 -175
  25. package/common/styles/trackerDelayStyle.js +2 -11
  26. package/common/styles/trackerSimpleStyle.js +4 -8
  27. package/common/trackerConfig.js +61 -99
  28. package/common/trackerConfig.test.js +15 -17
  29. package/common/typedefs.js +0 -23
  30. package/common/utils/createTrackerFilters.js +10 -41
  31. package/common/utils/createTrackerFilters.test.js +40 -56
  32. package/common/utils/getMapboxMapCopyrights.js +3 -16
  33. package/common/utils/getMapboxMapCopyrights.test.js +32 -39
  34. package/common/utils/getMapboxStyleUrl.js +3 -13
  35. package/common/utils/getVehiclePosition.js +3 -33
  36. package/common/utils/index.js +5 -6
  37. package/common/utils/removeDuplicate.js +3 -17
  38. package/common/utils/removeDuplicate.test.js +17 -20
  39. package/common/utils/sortByDelay.js +2 -7
  40. package/common/utils/timeUtils.js +8 -32
  41. package/common/utils/timeUtils.test.js +7 -13
  42. package/index.js +8 -2
  43. package/mapbox/controls/CopyrightControl.js +9 -38
  44. package/mapbox/controls/index.js +1 -0
  45. package/mapbox/index.js +4 -3
  46. package/mapbox/layers/Layer.js +15 -76
  47. package/mapbox/layers/Layer.test.js +81 -101
  48. package/mapbox/layers/TralisLayer.js +46 -193
  49. package/mapbox/layers/TralisLayer.test.js +12 -14
  50. package/mapbox/layers/index.js +2 -0
  51. package/mapbox/utils.js +7 -21
  52. package/mbt.js +50444 -0
  53. package/mbt.js.map +7 -0
  54. package/mbt.min.js +1005 -0
  55. package/mbt.min.js.map +7 -0
  56. package/ol/controls/CopyrightControl.js +8 -46
  57. package/ol/controls/CopyrightControl.test.js +75 -121
  58. package/ol/controls/RoutingControl.js +167 -532
  59. package/ol/controls/RoutingControl.test.js +99 -164
  60. package/ol/controls/StopFinderControl.js +3 -31
  61. package/ol/controls/StopFinderControl.test.js +18 -29
  62. package/ol/controls/index.js +3 -0
  63. package/ol/index.js +5 -13
  64. package/ol/layers/Layer.js +23 -128
  65. package/ol/layers/Layer.test.js +79 -102
  66. package/ol/layers/MapboxLayer.js +62 -237
  67. package/ol/layers/MapboxLayer.test.js +58 -84
  68. package/ol/layers/MapboxStyleLayer.js +38 -268
  69. package/ol/layers/MapboxStyleLayer.test.js +97 -128
  70. package/ol/layers/MaplibreLayer.js +46 -187
  71. package/ol/layers/RoutingLayer.js +21 -51
  72. package/ol/layers/RoutingLayer.test.js +15 -24
  73. package/ol/layers/TralisLayer.js +102 -276
  74. package/ol/layers/TralisLayer.test.js +32 -50
  75. package/ol/layers/VectorLayer.js +3 -24
  76. package/ol/layers/VectorLayer.test.js +34 -45
  77. package/ol/layers/WMSLayer.js +15 -57
  78. package/ol/layers/WMSLayer.test.js +35 -43
  79. package/ol/layers/index.js +8 -0
  80. package/ol/styles/fullTrajectoryDelayStyle.js +11 -15
  81. package/ol/styles/fullTrajectoryStyle.js +17 -25
  82. package/ol/styles/index.js +2 -2
  83. package/package.json +35 -62
  84. package/api/routing/RoutingAPI.js +0 -44
  85. package/api/routing/RoutingAPI.test.js +0 -41
  86. package/api/stops/StopsAPI.js +0 -41
  87. package/api/stops/StopsAPI.test.js +0 -34
  88. package/api/tralis/TralisAPI.js +0 -731
  89. package/api/tralis/TralisAPI.test.js +0 -75
  90. package/api/tralis/WebSocketConnector.js +0 -338
  91. package/api/tralis/typedefs.js +0 -81
  92. package/common/api/api.js +0 -64
  93. package/common/api/api.test.js +0 -68
  94. package/index.js.map +0 -1
  95. package/module.js +0 -23
  96. package/ol/controls/snapshots/RoutingControlRouteGen10.json +0 -58
  97. package/ol/controls/snapshots/RoutingControlRouteGen100.json +0 -292
  98. package/ol/controls/snapshots/RoutingControlRouteGen30.json +0 -69
  99. package/ol/controls/snapshots/RoutingControlRouteGen5.json +0 -58
  100. package/ol/controls/snapshots/RoutingControlRouteOSM.json +0 -759
  101. package/ol/controls/snapshots/RoutingControlStation1.json +0 -60
  102. package/ol/controls/snapshots/RoutingControlStation2.json +0 -49
@@ -1,75 +0,0 @@
1
- import { TralisAPI, TralisModes } from '..';
2
-
3
- describe('TralisAPI', () => {
4
- let tralisAPI;
5
- let get;
6
-
7
- beforeEach(() => {
8
- get = jest.fn((params, cb) => {
9
- cb({ content: 'content' });
10
- });
11
- tralisAPI = new TralisAPI();
12
- tralisAPI.conn = {
13
- get,
14
- };
15
- });
16
-
17
- describe('#getFullTrajectory() calls fullTrajectory channel', () => {
18
- test('without parameters', (done) => {
19
- tralisAPI.getFullTrajectory().then(() => {
20
- expect(get.mock.calls.length).toBe(1);
21
- expect(get.mock.calls[0][0]).toEqual({
22
- channel: 'full_trajectory',
23
- });
24
- done();
25
- });
26
- });
27
-
28
- [null, TralisModes.TOPOGRAPHIC].forEach((mode) => {
29
- describe(`using mode ${mode}`, () => {
30
- test('using id', (done) => {
31
- tralisAPI.getFullTrajectory('foo', mode).then(() => {
32
- expect(get.mock.calls.length).toBe(1);
33
- expect(get.mock.calls[0][0]).toEqual({
34
- channel: 'full_trajectory_foo',
35
- });
36
- done();
37
- });
38
- });
39
-
40
- test('using id and generalizationLevel param', (done) => {
41
- tralisAPI.getFullTrajectory('foo', mode, 5).then(() => {
42
- expect(get.mock.calls.length).toBe(1);
43
- expect(get.mock.calls[0][0]).toEqual({
44
- channel: 'full_trajectory_foo_gen5',
45
- });
46
- done();
47
- });
48
- });
49
- });
50
- });
51
-
52
- describe('using schematic mode ', () => {
53
- test('using id', (done) => {
54
- tralisAPI.getFullTrajectory('foo', TralisModes.SCHEMATIC).then(() => {
55
- expect(get.mock.calls.length).toBe(1);
56
- expect(get.mock.calls[0][0]).toEqual({
57
- channel: 'full_trajectory_schematic_foo',
58
- });
59
- done();
60
- });
61
- });
62
- test("doesn't use generalizationLevel param", (done) => {
63
- tralisAPI
64
- .getFullTrajectory('foo', TralisModes.SCHEMATIC, 10)
65
- .then(() => {
66
- expect(get.mock.calls.length).toBe(1);
67
- expect(get.mock.calls[0][0]).toEqual({
68
- channel: 'full_trajectory_schematic_foo',
69
- });
70
- done();
71
- });
72
- });
73
- });
74
- });
75
- });
@@ -1,338 +0,0 @@
1
- /**
2
- * Class used to facilitate connection to a WebSocket and
3
- * also to manage properly messages send to the WebSocket.
4
- * This class must not contain any specific implementation.
5
- *
6
- * @private
7
- */
8
- class WebSocketConnector {
9
- constructor() {
10
- this.defineProperties();
11
- }
12
-
13
- defineProperties() {
14
- Object.defineProperties(this, {
15
- closed: {
16
- get: () =>
17
- !!(
18
- this.websocket &&
19
- this.websocket.readyState === this.websocket.CLOSED
20
- ),
21
- },
22
- closing: {
23
- get: () =>
24
- !!(
25
- this.websocket &&
26
- this.websocket.readyState === this.websocket.CLOSING
27
- ),
28
- },
29
- connecting: {
30
- get: () =>
31
- !!(
32
- this.websocket &&
33
- this.websocket.readyState === this.websocket.CONNECTING
34
- ),
35
- },
36
- open: {
37
- get: () =>
38
- !!(
39
- this.websocket && this.websocket.readyState === this.websocket.OPEN
40
- ),
41
- },
42
- /**
43
- * Array of message to send on open.
44
- * @type {Array<string>}
45
- * @private
46
- */
47
- messagesOnOpen: {
48
- value: [],
49
- writable: true,
50
- },
51
- /**
52
- * Array of subscriptions.
53
- * @type {Array<subscription>}
54
- * @private
55
- */
56
- subscriptions: {
57
- value: [],
58
- writable: true,
59
- },
60
-
61
- /**
62
- * List of channels subscribed.
63
- * @type {Array<subscription>}
64
- * @private
65
- */
66
- subscribed: {
67
- value: {},
68
- writable: true,
69
- },
70
- });
71
- }
72
-
73
- /**
74
- * Get the websocket request string.
75
- *
76
- * @param {string} method Request mehtod {GET, SUB}.
77
- * @param {Object} params Request parameters.
78
- * @param {string} params.channel Channel name
79
- * @param {string} [params.args] Request arguments
80
- * @param {Number} [params.id] Request identifier
81
- * @return {string} request string
82
- * @private
83
- */
84
- static getRequestString(method, params) {
85
- let reqStr = `${method} ${params.channel}`;
86
- reqStr += params.args ? ` ${params.args}` : '';
87
- reqStr += params.id ? ` ${params.id}` : '';
88
- return reqStr.trim();
89
- }
90
-
91
- /**
92
- * (Re)connect the websocket.
93
- *
94
- * @param {strin} url Websocket url.
95
- * @param {function} onOpen Callback called when the websocket connection is opened and before subscriptions of previous subscriptions.
96
- * @private
97
- */
98
- connect(url, onOpen = () => {}) {
99
- if (this.websocket && !this.closed) {
100
- this.websocket.close();
101
- }
102
-
103
- /** @ignore */
104
- this.websocket = new WebSocket(url);
105
-
106
- if (!this.open) {
107
- this.websocket.addEventListener('open', () => {
108
- onOpen();
109
- this.subscribePreviousSubscriptions();
110
- });
111
- } else {
112
- onOpen();
113
- this.subscribePreviousSubscriptions();
114
- }
115
- }
116
-
117
- /**
118
- * Close the websocket definitively.
119
- *
120
- * @private
121
- */
122
- close() {
123
- if (this.websocket) {
124
- this.websocket.onclose = null;
125
- this.websocket.close();
126
- this.websocket = null;
127
- this.messagesOnOpen = [];
128
- }
129
- }
130
-
131
- /**
132
- * Sends a message to the websocket.
133
- *
134
- * @param {message} message Message to send.
135
- * @private
136
- */
137
- send(message) {
138
- if (!this.websocket) {
139
- return;
140
- }
141
- const send = () => {
142
- this.websocket.send(message);
143
- };
144
- if (!this.open) {
145
- // This 'if' avoid sending 2 identical BBOX message on open,
146
- if (!this.messagesOnOpen.includes(message)) {
147
- this.messagesOnOpen.push(message);
148
- this.websocket.addEventListener('open', () => {
149
- this.messagesOnOpen = [];
150
- send();
151
- });
152
- this.websocket.addEventListener('close', () => {
153
- this.messagesOnOpen = [];
154
- });
155
- }
156
- } else if (!this.messagesOnOpen.includes(message)) {
157
- send();
158
- }
159
- }
160
-
161
- /**
162
- * Listen to websocket messages.
163
- *
164
- * @param {Object} params Parameters for the websocket get request
165
- * @param {function} cb callback on listen
166
- * @param {function} errorCb Callback on error
167
- * @return {{onMessage: function, errorCb: function}} Object with onMessage and error callbacks
168
- * @private
169
- */
170
- listen(params, cb, errorCb) {
171
- // Remove the previous identical callback
172
- this.unlisten(params, cb);
173
-
174
- const onMessage = (evt) => {
175
- let data = {};
176
- try {
177
- data = JSON.parse(evt.data);
178
- } catch (err) {
179
- // eslint-disable-next-line no-console
180
- console.error('WebSocket: unable to parse JSON data', err, evt.data);
181
- }
182
- let source = params.channel;
183
- source += params.args ? ` ${params.args}` : '';
184
-
185
- // Buffer channel message return a list of other channels to propagate to proper callbacks.
186
- const contents = data.source === 'buffer' ? data.content : [data];
187
- contents.forEach((content) => {
188
- // Because of backend optimization, the last content is null.
189
- if (
190
- content?.source === source &&
191
- (!params.id || params.id === data.client_reference)
192
- ) {
193
- cb(content);
194
- }
195
- });
196
- };
197
-
198
- if (this.websocket) {
199
- this.websocket.addEventListener('message', onMessage);
200
-
201
- if (errorCb) {
202
- this.websocket.addEventListener('error', errorCb);
203
- this.websocket.addEventListener('close', errorCb);
204
- }
205
- }
206
-
207
- return { onMessageCb: onMessage, onErrorCb: errorCb };
208
- }
209
-
210
- /**
211
- * Unlisten websocket messages.
212
- *
213
- * @param {Object} params Parameters for the websocket get request.
214
- * @param {function} cb Callback used when listen.
215
- * @private
216
- */
217
- unlisten(params, cb) {
218
- if (!this.websocket) {
219
- return;
220
- }
221
- this.subscriptions
222
- .filter(
223
- (s) => s.params.channel === params.channel && (!cb || s.cb === cb),
224
- )
225
- .forEach(({ onMessageCb, onErrorCb }) => {
226
- if (this.websocket) {
227
- this.websocket.removeEventListener('message', onMessageCb);
228
- if (onErrorCb) {
229
- this.websocket.removeEventListener('error', onErrorCb);
230
- this.websocket.removeEventListener('close', onErrorCb);
231
- }
232
- }
233
- });
234
- }
235
-
236
- /**
237
- * Sends a get request to the websocket.
238
- *
239
- * @param {Object} params Parameters for the websocket get request
240
- * @param {function} cb callback on listen
241
- * @param {function} errorCb Callback on error
242
- * @private
243
- */
244
- get(params, cb, errorCb) {
245
- const reqStr = WebSocketConnector.getRequestString('GET', params);
246
- this.send(reqStr);
247
- this.listen(params, cb, errorCb);
248
- }
249
-
250
- /**
251
- * Subscribe to a given channel.
252
- *
253
- * @param {Object} params Parameters for the websocket get request
254
- * @param {function} cb callback on listen
255
- * @param {function} errorCb Callback on error
256
- * @param {boolean} quiet if false, no GET or SUB requests are send, only the callback is registered.
257
- * @private
258
- */
259
- subscribe(params, cb, errorCb, quiet = false) {
260
- const { onMessageCb, onErrorCb } = this.listen(params, cb, errorCb);
261
- const reqStr = WebSocketConnector.getRequestString('', params);
262
-
263
- const index = this.subscriptions.findIndex(
264
- (subcr) => params.channel === subcr.params.channel && cb === subcr.cb,
265
- );
266
- const newSubscr = { params, cb, errorCb, onMessageCb, onErrorCb, quiet };
267
- if (index > -1) {
268
- this.subscriptions[index] = newSubscr;
269
- } else {
270
- this.subscriptions.push(newSubscr);
271
- }
272
-
273
- if (!this.subscribed[reqStr]) {
274
- if (!newSubscr.quiet) {
275
- this.send(`GET ${reqStr}`);
276
- this.send(`SUB ${reqStr}`);
277
- }
278
- this.subscribed[reqStr] = true;
279
- }
280
- }
281
-
282
- /**
283
- * Unsubscribe from a channel.
284
- * @param {string} source source to unsubscribe from
285
- * @param {function} cb Callback function to unsubscribe. If null all subscriptions for the channel will be unsubscribed.
286
- * @private
287
- */
288
- unsubscribe(source, cb) {
289
- const toRemove = this.subscriptions.filter(
290
- (s) => s.params.channel === source && (!cb || s.cb === cb),
291
- );
292
-
293
- toRemove.forEach(({ onMessageCb, onErrorCb }) => {
294
- if (this.websocket) {
295
- this.websocket.removeEventListener('message', onMessageCb);
296
- if (onErrorCb) {
297
- this.websocket.removeEventListener('error', onErrorCb);
298
- this.websocket.removeEventListener('close', onErrorCb);
299
- }
300
- }
301
- });
302
-
303
- this.subscriptions = this.subscriptions.filter(
304
- (s) => s.params.channel !== source || (cb && s.cb !== cb),
305
- );
306
-
307
- // If there is no more subscriptions to this channel, and the removed subscriptions didn't register quietly,
308
- // we DEL it.
309
- if (
310
- source &&
311
- this.subscribed[source] &&
312
- !this.subscriptions.find((s) => s.params.channel === source) &&
313
- toRemove.find((subscr) => !subscr.quiet)
314
- ) {
315
- this.send(`DEL ${source}`);
316
- this.subscribed[source] = false;
317
- }
318
- }
319
-
320
- /**
321
- * After an auto reconnection we need to re-subscribe to the channels.
322
- */
323
- subscribePreviousSubscriptions() {
324
- // Before to subscribe previous subscriptions we make sure they
325
- // are all defined as unsubscribed, because this code is asynchrone
326
- // and a subscription could have been added in between.
327
- Object.keys(this.subscribed).forEach((key) => {
328
- this.subscribed[key] = false;
329
- });
330
-
331
- // Subscribe all previous subscriptions.
332
- [...this.subscriptions].forEach((s) => {
333
- this.subscribe(s.params, s.cb, s.errorCb, s.quiet);
334
- });
335
- }
336
- }
337
-
338
- export default WebSocketConnector;
@@ -1,81 +0,0 @@
1
- /**
2
- * @typedef {Object} Departure
3
- * @property {number} time Timestamp in ms.
4
- * @property {boolean} no_stop_between
5
- * @property {number} train_number
6
- * @property {string[]} to
7
- * @property {number} ris_aimed_time Timestamp in ms.
8
- * @property {number} updated_at Timestamp in ms.
9
- * @property {boolean} new_to
10
- * @property {number} min_arrival_time Timestamp in ms.
11
- * @property {string[]} next_stoppoints List of next stops. Like value in at_station_ds100.
12
- * @property {number} ris_estimated_time Timestamp in ms.
13
- * @property {NetworkLine} line
14
- * @property {boolean} has_fzo if true this departure has realtime data.
15
- * @property {number} train_id
16
- * @property {string} platform
17
- * @property {?*} state
18
- * @property {number} fzo_estimated_time Timestamp in ms.
19
- * @property {?*} formation
20
- * @property {?*} no_stop_till
21
- * @property {number} train_type
22
- * @property {number} call_id
23
- * @property {string} created_at Timestamp in ms.
24
- * @property {string} at_station_ds100
25
- * @property {number} timediff Timestamp in ms.
26
- *
27
- */
28
-
29
- /**
30
- * @typedef {GeoJSONFeature} Station
31
- * @property {StationProperties} properties Returns the station's properties.
32
- * @property {GeoJSONPoint} geometry Returns a point.
33
- */
34
-
35
- /**
36
- * @typedef {Object} StationProperties
37
- * @property {Transfer[]} transfers
38
- * @property {boolean} elevatorOutOfOrder
39
- * @property {number} uic
40
- * @property {string} name
41
- * @property {NetworkLine[]} networkLines
42
- * @property {boolean} hasElevator
43
- * @property {boolean} hasZOB
44
- * @property {boolean} hasAccessibility
45
- * @property {string} type
46
- */
47
-
48
- /**
49
- * @typedef {Object} NetworkLine
50
- * @property {number} id Identifier of the line.
51
- * @property {string} color Color of the line (CSS color string).
52
- * @property {string} stroke Stroke color of the line (CSS color string).
53
- * @property {string} name Name of the line.
54
- * @property {string} text_color Text color of the line (CSS color string).
55
- */
56
-
57
- /**
58
- * @typedef {Object} Transfer
59
- * @property {string} mot Mode of transportation (ex: U-Bahn).
60
- * @property {string[]} lines Array of lines name (ex: ["U4", "U5"]).
61
- */
62
-
63
- /**
64
- * @typedef {GeoJSONFeature} StopSequence
65
- */
66
-
67
- /**
68
- * @typedef {GeoJSONFeature} TralisTrajectory
69
- */
70
-
71
- /**
72
- * @typedef {GeoJSONFeature} FullTrajectory
73
- */
74
-
75
- /**
76
- * @typedef {GeoJSONFeature} Vehicle
77
- */
78
-
79
- /**
80
- * @typedef {GeoJSONFeature} ExtraGeom
81
- */
package/common/api/api.js DELETED
@@ -1,64 +0,0 @@
1
- import qs from 'query-string';
2
- import BaseObject from 'ol/Object';
3
-
4
- /**
5
- * Common class to access to a geOps api.
6
- *
7
- * @example
8
- * import { API } from 'mobility-toolbox-js/api';
9
- *
10
- * const api = new API({
11
- * url: [yourUrl],
12
- * apiKey: [yourApiKey]
13
- * });
14
- *
15
- * @classproperty {string} url Url of the service.
16
- * @classproperty {string} apiKey Api key to access the service.
17
- */
18
- class API extends BaseObject {
19
- constructor(options = {}) {
20
- super();
21
- /** @ignore */
22
- this.url = options.url;
23
-
24
- /** @ignore */
25
- this.apiKey = options.apiKey;
26
- }
27
-
28
- /**
29
- * Append the apiKey before sending the request.
30
- * @ignore
31
- */
32
- fetch(path, params, config) {
33
- // Clean requets parameters, removing undefined and null values.
34
- const urlParams = { ...(params || {}), key: this.apiKey };
35
- const clone = { ...urlParams };
36
- Object.keys(urlParams).forEach(
37
- (key) =>
38
- (clone[key] === undefined || clone[key] === null) && delete clone[key],
39
- );
40
- if (!this.apiKey) {
41
- // eslint-disable-next-line no-console
42
- return Promise.reject(
43
- new Error(`No apiKey defined for request to ${this.url}`),
44
- );
45
- }
46
- return fetch(
47
- `${this.url}${path || ''}?${qs.stringify(clone)}`,
48
- config,
49
- ).then((response) => {
50
- try {
51
- return response.json().then((data) => {
52
- if (data.error) {
53
- throw new Error(data.error);
54
- }
55
- return data;
56
- });
57
- } catch (err) {
58
- return Promise.reject(new Error(err));
59
- }
60
- });
61
- }
62
- }
63
-
64
- export default API;
@@ -1,68 +0,0 @@
1
- import fetch from 'jest-fetch-mock';
2
- import API from './api';
3
-
4
- let api;
5
-
6
- describe('API', () => {
7
- beforeEach(() => {
8
- global.fetch = fetch;
9
- fetch.resetMocks();
10
-
11
- api = new API({ url: 'https://foo.ch', apiKey: 'apiKey' });
12
- });
13
-
14
- describe('#fetch', () => {
15
- test('should success', () => {
16
- fetch.mockResponseOnce(JSON.stringify({ foo: 'bar' }));
17
-
18
- return api
19
- .fetch('/path', {
20
- q: 'Bern',
21
- fooUndefined: undefined,
22
- fooNull: null,
23
- fooEmpty: '',
24
- })
25
- .then((response) => {
26
- // Correct url
27
- expect(fetch.mock.calls[0][0]).toEqual(
28
- 'https://foo.ch/path?fooEmpty=&key=apiKey&q=Bern',
29
- );
30
-
31
- // Correct search result
32
- expect(response).toEqual({ foo: 'bar' });
33
- });
34
- });
35
-
36
- describe('should display error message', () => {
37
- test('reject error', (done) => {
38
- fetch.mockRejectOnce(new Error('Fake error message'));
39
- return api.fetch().catch((err) => {
40
- expect(err.name).toEqual('Error');
41
- expect(err.message).toEqual('Fake error message');
42
- done();
43
- });
44
- });
45
-
46
- test('if the response is invalid json', (done) => {
47
- fetch.mockResponseOnce('invalid json');
48
-
49
- api.fetch().catch((err) => {
50
- expect(err.name).toEqual('FetchError');
51
- expect(err.message).toEqual(
52
- 'invalid json response body at reason: Unexpected token i in JSON at position 0',
53
- );
54
- done();
55
- });
56
- });
57
-
58
- test('if the response contains an error message', (done) => {
59
- fetch.mockResponseOnce('{"error":"foo2"}');
60
- api.fetch().catch((err) => {
61
- expect(err.name).toEqual('Error');
62
- expect(err.message).toEqual('foo2');
63
- done();
64
- });
65
- });
66
- });
67
- });
68
- });