seatsio 65.0.0 → 65.4.0

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.
package/README.md CHANGED
@@ -38,10 +38,31 @@ seatsio-js follows semver since v54.4.0.
38
38
 
39
39
  Please note that any version below v2 is not production ready.
40
40
 
41
- ## Examples
41
+ ## Usage
42
+
43
+ ### General instructions
44
+
45
+ To use this library, you'll need to create a `SeatsioClient`:
46
+
47
+ ```js
48
+ import { SeatsioClient, Region } from 'seatsio'
49
+
50
+ let client = new SeatsioClient(Region.EU(), <WORKSPACE SECRET KEY>)
51
+ ...
52
+ ```
53
+
54
+ You can find your _workspace secret key_ in the [settings section of the workspace](https://app.seats.io/workspace-settings). It is important that you keep your _secret key_ private and not expose it in-browser calls unless it is password protected.
55
+
56
+ The region should correspond to the region of your account:
57
+
58
+ - `Region.EU()`: Europe
59
+ - `Region.NA()`: North-America
60
+ - `Region.SA()`: South-America
61
+ - `Region.OC()`: Oceania
62
+
63
+ If you're unsure about your region, have a look at your [company settings page](https://app.seats.io/company-settings).
42
64
 
43
65
  ### Creating a chart and an event
44
- Once you create a new `SeatsioClient` using your _secret key_, you can create _charts_ and then _events_. You can find your _secret key_ in the Settings section of your workspace: https://app.seats.io/workspace-settings. It is important that you keep your _secret key_ private and not expose it in-browser calls unless it is password protected.
45
66
 
46
67
  ```js
47
68
  import { SeatsioClient, Region } from 'seatsio'
@@ -257,10 +278,10 @@ When an API call results in an error, a rejected promise is returned with a valu
257
278
 
258
279
  ```json
259
280
  {
260
- errors: [{ code: 'RATE_LIMIT_EXCEEDED', message: 'Rate limit exceeded' }],
261
- messages: ['Rate limit exceeded'],
262
- requestId: '123456',
263
- status: 429
281
+ "errors": [{ "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded" }],
282
+ "messages": ["Rate limit exceeded"],
283
+ "requestId": "123456",
284
+ "status": 429
264
285
  }
265
286
  ```
266
287
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "seatsio",
3
- "version": "65.0.0",
3
+ "version": "65.4.0",
4
4
  "main": "index.js",
5
5
  "description": "Official JavaScript and Node.JS client library for the Seats.io REST API",
6
6
  "license": "MIT",
@@ -22,7 +22,7 @@
22
22
  "eslint-config-standard": "16.0.3",
23
23
  "eslint-plugin-import": "2.25.3",
24
24
  "eslint-plugin-node": "11.1.0",
25
- "eslint-plugin-promise": "5.2.0",
25
+ "eslint-plugin-promise": "6.0.0",
26
26
  "eslint-plugin-standard": "5.0.0",
27
27
  "gulp": "latest",
28
28
  "gulp-buffer": "latest",
@@ -30,8 +30,8 @@
30
30
  "gulp-tap": "latest",
31
31
  "gulp-uglify": "latest",
32
32
  "gulp-uglify-es": "latest",
33
- "jest": "27.4.3",
34
- "jest-cli": "27.4.3",
33
+ "jest": "27.4.5",
34
+ "jest-cli": "27.4.5",
35
35
  "uuid": "8.3.2"
36
36
  }
37
37
  }
@@ -31,7 +31,8 @@ class EventObjectInfo {
31
31
  this.displayedObjectType = report.displayedObjectType
32
32
  this.leftNeighbour = report.leftNeighbour
33
33
  this.rightNeighbour = report.rightNeighbour
34
- this.isSelectable = report.isSelectable
34
+ this.isAvailable = report.isAvailable
35
+ this.availabilityReason = report.availabilityReason
35
36
  this.isDisabledBySocialDistancing = report.isDisabledBySocialDistancing
36
37
  this.channel = report.channel
37
38
  this.distanceToFocalPoint = report.distanceToFocalPoint
@@ -272,9 +272,11 @@ class Events {
272
272
  * @param {?string[]} channelKeys
273
273
  * @param {?boolean} ignoreSocialDistancing
274
274
  * @returns {Promise<ChangeObjectStatusResult>}
275
+ * @param {?string[]} allowedPreviousStatuses
276
+ * @param {?string[]} rejectedPreviousStatuses
275
277
  */
276
- changeObjectStatus (eventKeyOrKeys, objectOrObjects, status, holdToken = null, orderId = null, keepExtraData = null, ignoreChannels = null, channelKeys = null, ignoreSocialDistancing = null) {
277
- const request = this.changeObjectStatusRequest(objectOrObjects, status, holdToken, orderId, keepExtraData, ignoreChannels, channelKeys, ignoreSocialDistancing)
278
+ changeObjectStatus (eventKeyOrKeys, objectOrObjects, status, holdToken = null, orderId = null, keepExtraData = null, ignoreChannels = null, channelKeys = null, ignoreSocialDistancing = null, allowedPreviousStatuses = null, rejectedPreviousStatuses = null) {
279
+ const request = this.changeObjectStatusRequest(objectOrObjects, status, holdToken, orderId, keepExtraData, ignoreChannels, channelKeys, ignoreSocialDistancing, allowedPreviousStatuses, rejectedPreviousStatuses)
278
280
  request.events = Array.isArray(eventKeyOrKeys) ? eventKeyOrKeys : [eventKeyOrKeys]
279
281
 
280
282
  return this.client.post('/events/groups/actions/change-object-status?expand=objects', request)
@@ -287,7 +289,18 @@ class Events {
287
289
  */
288
290
  changeObjectStatusInBatch (statusChangeRequests) {
289
291
  const requests = statusChangeRequests.map(r => {
290
- const json = this.changeObjectStatusRequest(r.objectOrObjects, r.status, r.holdToken, r.orderId, r.keepExtraData, r.ignoreChannels, r.channelKeys)
292
+ const json = this.changeObjectStatusRequest(
293
+ r.objectOrObjects,
294
+ r.status,
295
+ r.holdToken,
296
+ r.orderId,
297
+ r.keepExtraData,
298
+ r.ignoreChannels,
299
+ r.channelKeys,
300
+ null,
301
+ r.allowedPreviousStatuses,
302
+ r.rejectedPreviousStatuses
303
+ )
291
304
  json.event = r.eventKey
292
305
  return json
293
306
  })
@@ -297,7 +310,7 @@ class Events {
297
310
  .then((res) => res.data.results.map(r => new ChangeObjectStatusResult(r.objects)))
298
311
  }
299
312
 
300
- changeObjectStatusRequest (objectOrObjects, status, holdToken, orderId, keepExtraData, ignoreChannels, channelKeys, ignoreSocialDistancing) {
313
+ changeObjectStatusRequest (objectOrObjects, status, holdToken, orderId, keepExtraData, ignoreChannels, channelKeys, ignoreSocialDistancing, allowedPreviousStatuses, rejectedPreviousStatuses) {
301
314
  const request = {}
302
315
  request.objects = this.normalizeObjects(objectOrObjects)
303
316
  request.status = status
@@ -319,6 +332,12 @@ class Events {
319
332
  if (ignoreSocialDistancing !== null) {
320
333
  request.ignoreSocialDistancing = ignoreSocialDistancing
321
334
  }
335
+ if (allowedPreviousStatuses !== null) {
336
+ request.allowedPreviousStatuses = allowedPreviousStatuses
337
+ }
338
+ if (rejectedPreviousStatuses !== null) {
339
+ request.rejectedPreviousStatuses = rejectedPreviousStatuses
340
+ }
322
341
  return request
323
342
  }
324
343
 
@@ -13,6 +13,8 @@ class StatusChange {
13
13
  this.extraData = statusChange.extraData ? statusChange.extraData : null
14
14
  this.holdToken = statusChange.holdToken ? statusChange.holdToken : null
15
15
  this.origin = statusChange.origin
16
+ this.isPresentOnChart = statusChange.isPresentOnChart
17
+ this.displayedLabel = statusChange.displayedLabel ? statusChange.displayedLabel : null
16
18
  }
17
19
  }
18
20
 
@@ -8,8 +8,10 @@ class StatusChangeRequest {
8
8
  * @param {?boolean} keepExtraData
9
9
  * @param {?boolean} ignoreChannels
10
10
  * @param {?string[]} channelKeys
11
+ * @param {?string[]} allowedPreviousStatuses
12
+ * @param {?string[]} rejectedPreviousStatuses
11
13
  */
12
- constructor (eventKey, objectOrObjects, status, holdToken, orderId, keepExtraData, ignoreChannels, channelKeys) {
14
+ constructor (eventKey, objectOrObjects, status, holdToken, orderId, keepExtraData, ignoreChannels, channelKeys, allowedPreviousStatuses, rejectedPreviousStatuses) {
13
15
  this.eventKey = eventKey
14
16
  this.objectOrObjects = objectOrObjects
15
17
  this.status = status
@@ -18,6 +20,8 @@ class StatusChangeRequest {
18
20
  this.keepExtraData = keepExtraData
19
21
  this.ignoreChannels = ignoreChannels
20
22
  this.channelKeys = channelKeys
23
+ this.allowedPreviousStatuses = allowedPreviousStatuses
24
+ this.rejectedPreviousStatuses = rejectedPreviousStatuses
21
25
  }
22
26
  }
23
27
 
@@ -5,11 +5,6 @@ class ChartReports {
5
5
  this.client = client
6
6
  }
7
7
 
8
- fetchReport (reportType, eventKey, bookWholeTables) {
9
- return this.client.get(`/reports/charts/${encodeURIComponent(eventKey)}/${reportType}`, { params: { bookWholeTables } })
10
- .then((res) => utilities.createChartReport(res.data))
11
- }
12
-
13
8
  /**
14
9
  * @param {string} chartKey
15
10
  * @param {string} bookWholeTables
@@ -28,6 +23,15 @@ class ChartReports {
28
23
  return this.fetchReport('byObjectType', chartKey, bookWholeTables)
29
24
  }
30
25
 
26
+ /**
27
+ * @param {string} chartKey
28
+ * @param {string} bookWholeTables
29
+ * @returns {Object} JSON response from the server
30
+ */
31
+ summaryByObjectType (chartKey, bookWholeTables = undefined) {
32
+ return this.fetchSummaryReport('byObjectType', chartKey, bookWholeTables)
33
+ }
34
+
31
35
  /**
32
36
  * @param {string} chartKey
33
37
  * @param {string} bookWholeTables
@@ -37,6 +41,15 @@ class ChartReports {
37
41
  return this.fetchReport('byCategoryLabel', chartKey, bookWholeTables)
38
42
  }
39
43
 
44
+ /**
45
+ * @param {string} chartKey
46
+ * @param {string} bookWholeTables
47
+ * @returns {Object} JSON response from the server
48
+ */
49
+ summaryByCategoryLabel (chartKey, bookWholeTables = undefined) {
50
+ return this.fetchSummaryReport('byCategoryLabel', chartKey, bookWholeTables)
51
+ }
52
+
40
53
  /**
41
54
  * @param {string} chartKey
42
55
  * @param {string} bookWholeTables
@@ -45,6 +58,43 @@ class ChartReports {
45
58
  byCategoryKey (chartKey, bookWholeTables = undefined) {
46
59
  return this.fetchReport('byCategoryKey', chartKey, bookWholeTables)
47
60
  }
61
+
62
+ /**
63
+ * @param {string} chartKey
64
+ * @param {string} bookWholeTables
65
+ * @returns {Object} JSON response from the server
66
+ */
67
+ summaryByCategoryKey (chartKey, bookWholeTables = undefined) {
68
+ return this.fetchSummaryReport('byCategoryKey', chartKey, bookWholeTables)
69
+ }
70
+
71
+ /**
72
+ * @param {string} chartKey
73
+ * @param {string} bookWholeTables
74
+ * @returns {Object.<string, ChartObjectInfo[]>}
75
+ */
76
+ bySection (chartKey, bookWholeTables = undefined) {
77
+ return this.fetchReport('bySection', chartKey, bookWholeTables)
78
+ }
79
+
80
+ /**
81
+ * @param {string} chartKey
82
+ * @param {string} bookWholeTables
83
+ * @returns {Object} JSON response from the server
84
+ */
85
+ summaryBySection (chartKey, bookWholeTables = undefined) {
86
+ return this.fetchSummaryReport('bySection', chartKey, bookWholeTables)
87
+ }
88
+
89
+ fetchReport (reportType, chartKey, bookWholeTables) {
90
+ return this.client.get(`/reports/charts/${encodeURIComponent(chartKey)}/${reportType}`, { params: { bookWholeTables } })
91
+ .then((res) => utilities.createChartReport(res.data))
92
+ }
93
+
94
+ fetchSummaryReport (reportType, chartKey, bookWholeTables) {
95
+ return this.client.get(`/reports/charts/${encodeURIComponent(chartKey)}/${reportType}/summary`, { params: { bookWholeTables } })
96
+ .then((res) => res.data)
97
+ }
48
98
  }
49
99
 
50
100
  module.exports = ChartReports
@@ -167,11 +167,21 @@ class EventReports {
167
167
 
168
168
  /**
169
169
  * @param {string} eventKey
170
- * @param {?string} selectability
170
+ * @param {?string} availability
171
171
  * @returns {Object.<string, ObjectInfo[]>}
172
172
  */
173
- byAvailability (eventKey, selectability = null) {
174
- return this.client.get(EventReports.reportUrl('byAvailability', eventKey, selectability))
173
+ byAvailability (eventKey, availability = null) {
174
+ return this.client.get(EventReports.reportUrl('byAvailability', eventKey, availability))
175
+ .then((res) => utilities.createEventReport(res.data))
176
+ }
177
+
178
+ /**
179
+ * @param {string} eventKey
180
+ * @param {?string} availabilityReason
181
+ * @returns {Object.<string, ObjectInfo[]>}
182
+ */
183
+ byAvailabilityReason (eventKey, availabilityReason = null) {
184
+ return this.client.get(EventReports.reportUrl('byAvailabilityReason', eventKey, availabilityReason))
175
185
  .then((res) => utilities.createEventReport(res.data))
176
186
  }
177
187
 
@@ -184,6 +194,15 @@ class EventReports {
184
194
  .then((res) => res.data)
185
195
  }
186
196
 
197
+ /**
198
+ * @param {string} eventKey
199
+ * @returns {Object} JSON response from the server
200
+ */
201
+ summaryByAvailabilityReason (eventKey) {
202
+ return this.client.get(EventReports.summaryReportUrl('byAvailabilityReason', eventKey))
203
+ .then((res) => res.data)
204
+ }
205
+
187
206
  /**
188
207
  * @param {string} eventKey
189
208
  * @returns {Object} JSON response from the server
@@ -193,6 +212,15 @@ class EventReports {
193
212
  .then((res) => res.data)
194
213
  }
195
214
 
215
+ /**
216
+ * @param {string} eventKey
217
+ * @returns {Object} JSON response from the server
218
+ */
219
+ deepSummaryByAvailabilityReason (eventKey) {
220
+ return this.client.get(EventReports.deepSummaryReportUrl('byAvailabilityReason', eventKey))
221
+ .then((res) => res.data)
222
+ }
223
+
196
224
  /**
197
225
  * @param {string} eventKey
198
226
  * @param {?string} channel
@@ -119,3 +119,14 @@ test('get report byCategoryLabel', async () => {
119
119
  expect(report.Cat1.length).toBe(17)
120
120
  expect(report.Cat2.length).toBe(17)
121
121
  })
122
+
123
+ test('get report bySection', async () => {
124
+ const { client, user } = await testUtils.createTestUserAndClient()
125
+ const chartKey = testUtils.getChartKey()
126
+ await testUtils.createTestChartWithSections(chartKey, user.secretKey)
127
+
128
+ const report = await client.chartReports.bySection(chartKey)
129
+
130
+ expect(report['Section A'].length).toBe(36)
131
+ expect(report['Section B'].length).toBe(35)
132
+ })
@@ -0,0 +1,155 @@
1
+ const testUtils = require('../testUtils.js')
2
+
3
+ test('summaryByObjectType', async () => {
4
+ const { client, user } = await testUtils.createTestUserAndClient()
5
+ const chartKey = testUtils.getChartKey()
6
+ await testUtils.createTestChart(chartKey, user.secretKey)
7
+
8
+ const report = await client.chartReports.summaryByObjectType(chartKey)
9
+
10
+ expect(report).toEqual({
11
+ seat: {
12
+ count: 32,
13
+ bySection: { NO_SECTION: 32 },
14
+ byCategoryKey: { 9: 16, 10: 16 },
15
+ byCategoryLabel: { Cat1: 16, Cat2: 16 }
16
+ },
17
+ generalAdmission: {
18
+ count: 200,
19
+ bySection: { NO_SECTION: 200 },
20
+ byCategoryKey: { 9: 100, 10: 100 },
21
+ byCategoryLabel: { Cat2: 100, Cat1: 100 }
22
+ },
23
+ table: {
24
+ count: 0,
25
+ bySection: {},
26
+ byCategoryKey: {},
27
+ byCategoryLabel: {}
28
+ },
29
+ booth: {
30
+ count: 0,
31
+ bySection: {},
32
+ byCategoryKey: {},
33
+ byCategoryLabel: {}
34
+ }
35
+ })
36
+ })
37
+
38
+ test('summaryByObjectType_bookWholeTablesTrue', async () => {
39
+ const { client, user } = await testUtils.createTestUserAndClient()
40
+ const chartKey = testUtils.getChartKey()
41
+ await testUtils.createTestChartWithTables(chartKey, user.secretKey)
42
+
43
+ const report = await client.chartReports.summaryByObjectType(chartKey, 'true')
44
+
45
+ expect(report).toEqual({
46
+ seat: {
47
+ count: 0,
48
+ bySection: {},
49
+ byCategoryKey: {},
50
+ byCategoryLabel: {}
51
+ },
52
+ generalAdmission: {
53
+ count: 0,
54
+ bySection: {},
55
+ byCategoryKey: {},
56
+ byCategoryLabel: {}
57
+ },
58
+ table: {
59
+ count: 2,
60
+ bySection: { NO_SECTION: 2 },
61
+ byCategoryKey: { 9: 2 },
62
+ byCategoryLabel: { Cat1: 2 }
63
+ },
64
+ booth: {
65
+ count: 0,
66
+ bySection: {},
67
+ byCategoryKey: {},
68
+ byCategoryLabel: {}
69
+ }
70
+ })
71
+ })
72
+
73
+ test('summaryByCategoryKey', async () => {
74
+ const { client, user } = await testUtils.createTestUserAndClient()
75
+ const chartKey = testUtils.getChartKey()
76
+ await testUtils.createTestChart(chartKey, user.secretKey)
77
+
78
+ const report = await client.chartReports.summaryByCategoryKey(chartKey)
79
+
80
+ expect(report).toEqual({
81
+ 9: {
82
+ count: 116,
83
+ bySection: { NO_SECTION: 116 },
84
+ byObjectType: {
85
+ generalAdmission: 100,
86
+ seat: 16
87
+ }
88
+ },
89
+ 10: {
90
+ count: 116,
91
+ bySection: { NO_SECTION: 116 },
92
+ byObjectType: {
93
+ generalAdmission: 100,
94
+ seat: 16
95
+ }
96
+ },
97
+ NO_CATEGORY: {
98
+ count: 0,
99
+ bySection: {},
100
+ byObjectType: {}
101
+ }
102
+ })
103
+ })
104
+
105
+ test('summaryByCategoryLabel', async () => {
106
+ const { client, user } = await testUtils.createTestUserAndClient()
107
+ const chartKey = testUtils.getChartKey()
108
+ await testUtils.createTestChart(chartKey, user.secretKey)
109
+
110
+ const report = await client.chartReports.summaryByCategoryLabel(chartKey)
111
+
112
+ expect(report).toEqual({
113
+ Cat2: {
114
+ count: 116,
115
+ bySection: { NO_SECTION: 116 },
116
+ byObjectType: {
117
+ generalAdmission: 100,
118
+ seat: 16
119
+ }
120
+ },
121
+ Cat1: {
122
+ count: 116,
123
+ bySection: { NO_SECTION: 116 },
124
+ byObjectType: {
125
+ generalAdmission: 100,
126
+ seat: 16
127
+ }
128
+ },
129
+ NO_CATEGORY: {
130
+ count: 0,
131
+ bySection: {},
132
+ byObjectType: {}
133
+ }
134
+ })
135
+ })
136
+
137
+ test('summaryBySection', async () => {
138
+ const { client, user } = await testUtils.createTestUserAndClient()
139
+ const chartKey = testUtils.getChartKey()
140
+ await testUtils.createTestChart(chartKey, user.secretKey)
141
+
142
+ const report = await client.chartReports.summaryBySection(chartKey)
143
+
144
+ expect(report).toEqual({
145
+ NO_SECTION: {
146
+ count: 232,
147
+ byCategoryKey: { 9: 116, 10: 116 },
148
+ byCategoryLabel: { Cat2: 116, Cat1: 116 },
149
+ byObjectType: {
150
+ generalAdmission: 200,
151
+ seat: 32
152
+ }
153
+ }
154
+ })
155
+ })
@@ -103,13 +103,9 @@ test('listAll Charts with expandEvents parameters', async () => {
103
103
  test('listAll Charts with expandEvents parameters and eventsLimit', async () => {
104
104
  const { client } = await testUtils.createTestUserAndClient()
105
105
  const chart1 = await client.charts.create()
106
- const promises = [
107
- client.events.create(chart1.key),
108
- client.events.create(chart1.key),
109
- client.events.create(chart1.key)
110
- ]
111
- const events = await Promise.all(promises)
112
- const expectedEventKeys = [events[0].key, events[1].key]
106
+ const event1 = await client.events.create(chart1.key)
107
+ const event2 = await client.events.create(chart1.key)
108
+ const event3 = await client.events.create(chart1.key)
113
109
  const retrievedKeys = []
114
110
  const params = new ChartListParams().withExpandEvents(true).withEventsLimit(2)
115
111
 
@@ -119,7 +115,7 @@ test('listAll Charts with expandEvents parameters and eventsLimit', async () =>
119
115
  }
120
116
  }
121
117
 
122
- expect(retrievedKeys.sort()).toEqual(expectedEventKeys.sort())
118
+ expect(retrievedKeys).toEqual([event3.key, event2.key])
123
119
  })
124
120
 
125
121
  test('list all charts with validation', async () => {
@@ -37,7 +37,8 @@ test('report properties', async () => {
37
37
  expect(reportItem.displayedObjectType).toBe(undefined)
38
38
  expect(reportItem.leftNeighbour).toBe(undefined)
39
39
  expect(reportItem.rightNeighbour).toBe('A-2')
40
- expect(reportItem.isSelectable).toBe(false)
40
+ expect(reportItem.isAvailable).toBe(false)
41
+ expect(reportItem.availabilityReason).toBe('booked')
41
42
  expect(reportItem.isDisabledBySocialDistancing).toBe(false)
42
43
  expect(reportItem.bookAsAWhole).toBe(undefined)
43
44
  expect(reportItem.distanceToFocalPoint).toBeTruthy()
@@ -281,6 +282,35 @@ test('report by specific availability', async () => {
281
282
  expect(report.available.length).toBe(31)
282
283
  })
283
284
 
285
+ test('report by availability reason', async () => {
286
+ const { client, user } = await testUtils.createTestUserAndClient()
287
+ const chartKey = testUtils.getChartKey()
288
+ await testUtils.createTestChart(chartKey, user.secretKey)
289
+ const event = await client.events.create(chartKey)
290
+ await client.events.book(event.key, 'A-1', null, 'order1')
291
+ await client.events.book(event.key, 'A-2', null, 'order1')
292
+ await client.events.book(event.key, 'A-3', null, 'order2')
293
+
294
+ const report = await client.eventReports.byAvailabilityReason(event.key)
295
+
296
+ expect(report.available.length).toBe(31)
297
+ expect(report.booked.length).toBe(3)
298
+ })
299
+
300
+ test('report by specific availability reason', async () => {
301
+ const { client, user } = await testUtils.createTestUserAndClient()
302
+ const chartKey = testUtils.getChartKey()
303
+ await testUtils.createTestChart(chartKey, user.secretKey)
304
+ const event = await client.events.create(chartKey)
305
+ await client.events.book(event.key, 'A-1', null, 'order1')
306
+ await client.events.book(event.key, 'A-2', null, 'order1')
307
+ await client.events.book(event.key, 'A-3', null, 'order2')
308
+
309
+ const report = await client.eventReports.byAvailabilityReason(event.key, 'booked')
310
+
311
+ expect(report.booked.length).toBe(3)
312
+ })
313
+
284
314
  test('report by channel', async () => {
285
315
  const { client, user } = await testUtils.createTestUserAndClient()
286
316
  const chartKey = testUtils.getChartKey()
@@ -84,6 +84,20 @@ test('deepSummaryByAvailability', async () => {
84
84
  expect(report.not_available.byCategoryLabel.Cat1.bySection.NO_SECTION).toEqual(1)
85
85
  })
86
86
 
87
+ test('deepSummaryByAvailabilityReason', async () => {
88
+ const { client, user } = await testUtils.createTestUserAndClient()
89
+ const chartKey = testUtils.getChartKey()
90
+ await testUtils.createTestChart(chartKey, user.secretKey)
91
+ const event = await client.events.create(chartKey)
92
+ await client.events.book(event.key, (new ObjectProperties('A-1')))
93
+
94
+ const report = await client.eventReports.deepSummaryByAvailabilityReason(event.key)
95
+
96
+ expect(report.booked.count).toEqual(1)
97
+ expect(report.booked.byCategoryLabel.Cat1.count).toEqual(1)
98
+ expect(report.booked.byCategoryLabel.Cat1.bySection.NO_SECTION).toEqual(1)
99
+ })
100
+
87
101
  test('deepSummaryByChannel', async () => {
88
102
  const { client, user } = await testUtils.createTestUserAndClient()
89
103
  const chartKey = testUtils.getChartKey()
@@ -18,6 +18,7 @@ test('summaryByStatus', async () => {
18
18
  byCategoryKey: { 9: 1 },
19
19
  bySelectability: { not_selectable: 1 },
20
20
  byAvailability: { not_available: 1 },
21
+ byAvailabilityReason: { booked: 1 },
21
22
  byCategoryLabel: { Cat1: 1 },
22
23
  byChannel: { NO_CHANNEL: 1 }
23
24
  },
@@ -28,6 +29,7 @@ test('summaryByStatus', async () => {
28
29
  byCategoryKey: { 9: 115, 10: 116 },
29
30
  bySelectability: { selectable: 231 },
30
31
  byAvailability: { available: 231 },
32
+ byAvailabilityReason: { available: 231 },
31
33
  byCategoryLabel: { Cat2: 116, Cat1: 115 },
32
34
  byChannel: { NO_CHANNEL: 231 }
33
35
  }
@@ -50,6 +52,7 @@ test('summaryByObjectType', async () => {
50
52
  byCategoryKey: { 9: 16, 10: 16 },
51
53
  bySelectability: { selectable: 32 },
52
54
  byAvailability: { available: 32 },
55
+ byAvailabilityReason: { available: 32 },
53
56
  byCategoryLabel: { Cat1: 16, Cat2: 16 },
54
57
  byChannel: { NO_CHANNEL: 32 }
55
58
  },
@@ -60,28 +63,31 @@ test('summaryByObjectType', async () => {
60
63
  byCategoryKey: { 9: 100, 10: 100 },
61
64
  bySelectability: { selectable: 200 },
62
65
  byAvailability: { available: 200 },
66
+ byAvailabilityReason: { available: 200 },
63
67
  byCategoryLabel: { Cat2: 100, Cat1: 100 },
64
68
  byChannel: { NO_CHANNEL: 200 }
65
69
  },
66
70
  table: {
67
71
  count: 0,
68
- bySection: { },
72
+ bySection: {},
69
73
  byStatus: {},
70
74
  byCategoryKey: {},
71
- bySelectability: { },
72
- byAvailability: { },
75
+ bySelectability: {},
76
+ byAvailability: {},
77
+ byAvailabilityReason: {},
73
78
  byCategoryLabel: {},
74
- byChannel: { }
79
+ byChannel: {}
75
80
  },
76
81
  booth: {
77
82
  count: 0,
78
- bySection: { },
83
+ bySection: {},
79
84
  byStatus: {},
80
85
  byCategoryKey: {},
81
- bySelectability: { },
82
- byAvailability: { },
86
+ bySelectability: {},
87
+ byAvailability: {},
88
+ byAvailabilityReason: {},
83
89
  byCategoryLabel: {},
84
- byChannel: { }
90
+ byChannel: {}
85
91
  }
86
92
  })
87
93
  })
@@ -101,6 +107,7 @@ test('summaryByCategoryKey', async () => {
101
107
  bySection: { NO_SECTION: 116 },
102
108
  bySelectability: { selectable: 115, not_selectable: 1 },
103
109
  byAvailability: { available: 115, not_available: 1 },
110
+ byAvailabilityReason: { available: 115, booked: 1 },
104
111
  byStatus: { booked: 1, free: 115 },
105
112
  byChannel: { NO_CHANNEL: 116 },
106
113
  byObjectType: {
@@ -113,6 +120,7 @@ test('summaryByCategoryKey', async () => {
113
120
  bySection: { NO_SECTION: 116 },
114
121
  bySelectability: { selectable: 116 },
115
122
  byAvailability: { available: 116 },
123
+ byAvailabilityReason: { available: 116 },
116
124
  byStatus: { free: 116 },
117
125
  byChannel: { NO_CHANNEL: 116 },
118
126
  byObjectType: {
@@ -124,7 +132,8 @@ test('summaryByCategoryKey', async () => {
124
132
  count: 0,
125
133
  bySection: {},
126
134
  bySelectability: {},
127
- byAvailability: { },
135
+ byAvailability: {},
136
+ byAvailabilityReason: { },
128
137
  byStatus: {},
129
138
  byChannel: {},
130
139
  byObjectType: {}
@@ -147,6 +156,7 @@ test('summaryByCategoryLabel', async () => {
147
156
  bySection: { NO_SECTION: 116 },
148
157
  bySelectability: { selectable: 116 },
149
158
  byAvailability: { available: 116 },
159
+ byAvailabilityReason: { available: 116 },
150
160
  byStatus: { free: 116 },
151
161
  byChannel: { NO_CHANNEL: 116 },
152
162
  byObjectType: {
@@ -159,6 +169,7 @@ test('summaryByCategoryLabel', async () => {
159
169
  bySection: { NO_SECTION: 116 },
160
170
  bySelectability: { selectable: 115, not_selectable: 1 },
161
171
  byAvailability: { available: 115, not_available: 1 },
172
+ byAvailabilityReason: { available: 115, booked: 1 },
162
173
  byStatus: { booked: 1, free: 115 },
163
174
  byChannel: { NO_CHANNEL: 116 },
164
175
  byObjectType: {
@@ -171,6 +182,7 @@ test('summaryByCategoryLabel', async () => {
171
182
  bySection: {},
172
183
  bySelectability: {},
173
184
  byAvailability: {},
185
+ byAvailabilityReason: { },
174
186
  byStatus: {},
175
187
  byChannel: {},
176
188
  byObjectType: {}
@@ -192,6 +204,7 @@ test('summaryBySection', async () => {
192
204
  byCategoryKey: { 9: 116, 10: 116 },
193
205
  bySelectability: { selectable: 231, not_selectable: 1 },
194
206
  byAvailability: { available: 231, not_available: 1 },
207
+ byAvailabilityReason: { available: 231, booked: 1 },
195
208
  byStatus: { booked: 1, free: 231 },
196
209
  byCategoryLabel: { Cat2: 116, Cat1: 116 },
197
210
  byChannel: { NO_CHANNEL: 232 },
@@ -218,6 +231,7 @@ test('summaryByAvailability', async () => {
218
231
  count: 231,
219
232
  byCategoryKey: { 9: 115, 10: 116 },
220
233
  bySelectability: { selectable: 231 },
234
+ byAvailabilityReason: { available: 231 },
221
235
  byStatus: { free: 231 },
222
236
  byCategoryLabel: { Cat2: 116, Cat1: 115 },
223
237
  byChannel: { NO_CHANNEL: 231 },
@@ -231,12 +245,86 @@ test('summaryByAvailability', async () => {
231
245
  count: 1,
232
246
  byCategoryKey: { 9: 1 },
233
247
  bySelectability: { not_selectable: 1 },
248
+ byAvailabilityReason: { booked: 1 },
249
+ byStatus: { booked: 1 },
250
+ byCategoryLabel: { Cat1: 1 },
251
+ byChannel: { NO_CHANNEL: 1 },
252
+ byObjectType: {
253
+ seat: 1
254
+ }
255
+ }
256
+ })
257
+ })
258
+
259
+ test('summaryByAvailabilityReason', async () => {
260
+ const { client, user } = await testUtils.createTestUserAndClient()
261
+ const chartKey = testUtils.getChartKey()
262
+ await testUtils.createTestChart(chartKey, user.secretKey)
263
+ const event = await client.events.create(chartKey)
264
+ await client.events.book(event.key, (new ObjectProperties('A-1')))
265
+
266
+ const report = await client.eventReports.summaryByAvailabilityReason(event.key)
267
+
268
+ expect(report).toEqual({
269
+ available: {
270
+ bySection: { NO_SECTION: 231 },
271
+ count: 231,
272
+ byCategoryKey: { 9: 115, 10: 116 },
273
+ bySelectability: { selectable: 231 },
274
+ byAvailability: { available: 231 },
275
+ byStatus: { free: 231 },
276
+ byCategoryLabel: { Cat2: 116, Cat1: 115 },
277
+ byChannel: { NO_CHANNEL: 231 },
278
+ byObjectType: {
279
+ generalAdmission: 200,
280
+ seat: 31
281
+ }
282
+ },
283
+ booked: {
284
+ bySection: { NO_SECTION: 1 },
285
+ count: 1,
286
+ byCategoryKey: { 9: 1 },
287
+ bySelectability: { not_selectable: 1 },
288
+ byAvailability: { not_available: 1 },
234
289
  byStatus: { booked: 1 },
235
290
  byCategoryLabel: { Cat1: 1 },
236
291
  byChannel: { NO_CHANNEL: 1 },
237
292
  byObjectType: {
238
293
  seat: 1
239
294
  }
295
+ },
296
+ disabled_by_social_distancing: {
297
+ count: 0,
298
+ bySection: { },
299
+ byCategoryKey: { },
300
+ bySelectability: { },
301
+ byAvailability: { },
302
+ byStatus: { },
303
+ byCategoryLabel: { },
304
+ byChannel: { },
305
+ byObjectType: {}
306
+ },
307
+ not_for_sale: {
308
+ count: 0,
309
+ bySection: { },
310
+ byCategoryKey: { },
311
+ bySelectability: { },
312
+ byAvailability: { },
313
+ byStatus: { },
314
+ byCategoryLabel: { },
315
+ byChannel: { },
316
+ byObjectType: {}
317
+ },
318
+ reservedByToken: {
319
+ count: 0,
320
+ bySection: { },
321
+ byCategoryKey: { },
322
+ bySelectability: { },
323
+ byAvailability: { },
324
+ byStatus: { },
325
+ byCategoryLabel: { },
326
+ byChannel: { },
327
+ byObjectType: {}
240
328
  }
241
329
  })
242
330
  })
@@ -261,6 +349,7 @@ test('summaryByChannel', async () => {
261
349
  byStatus: { free: 230 },
262
350
  byCategoryLabel: { Cat2: 116, Cat1: 114 },
263
351
  bySelectability: { selectable: 230 },
352
+ byAvailabilityReason: { available: 230 },
264
353
  byAvailability: { available: 230 },
265
354
  byObjectType: {
266
355
  generalAdmission: 200,
@@ -275,6 +364,7 @@ test('summaryByChannel', async () => {
275
364
  byCategoryLabel: { Cat1: 2 },
276
365
  bySelectability: { selectable: 2 },
277
366
  byAvailability: { available: 2 },
367
+ byAvailabilityReason: { available: 2 },
278
368
  byObjectType: {
279
369
  seat: 2
280
370
  }
@@ -26,7 +26,8 @@ test('should change object status', async () => {
26
26
  hasRestrictedView: false,
27
27
  isCompanionSeat: false,
28
28
  rightNeighbour: 'A-2',
29
- isSelectable: false,
29
+ isAvailable: false,
30
+ availabilityReason: 'lolzor',
30
31
  isDisabledBySocialDistancing: false,
31
32
  distanceToFocalPoint: 79.43847425150014
32
33
  }
@@ -228,3 +229,33 @@ test('should accept ignoreSocialDistancing', async () => {
228
229
  const objectInfo = await client.events.retrieveObjectInfo(event.key, 'A-1')
229
230
  expect(objectInfo.status).toBe(EventObjectInfo.BOOKED)
230
231
  })
232
+
233
+ test('should accept allowedPreviousStatuses', async () => {
234
+ const { client, user } = await testUtils.createTestUserAndClient()
235
+ const chartKey = testUtils.getChartKey()
236
+ await testUtils.createTestChart(chartKey, user.secretKey)
237
+ const event = await client.events.create(chartKey)
238
+
239
+ try {
240
+ await client.events.changeObjectStatus(event.key, ['A-1'], EventObjectInfo.BOOKED, null, null, null, null, null, true, ['MustBeThisStatus'], null)
241
+ throw new Error('Should have failed')
242
+ } catch (e) {
243
+ expect(e.errors.length).toEqual(1)
244
+ expect(e.errors[0].code).toBe('ILLEGAL_STATUS_CHANGE')
245
+ }
246
+ })
247
+
248
+ test('should accept rejectedPreviousStatuses', async () => {
249
+ const { client, user } = await testUtils.createTestUserAndClient()
250
+ const chartKey = testUtils.getChartKey()
251
+ await testUtils.createTestChart(chartKey, user.secretKey)
252
+ const event = await client.events.create(chartKey)
253
+
254
+ try {
255
+ await client.events.changeObjectStatus(event.key, ['A-1'], EventObjectInfo.BOOKED, null, null, null, null, null, true, null, ['free'])
256
+ throw new Error('Should have failed')
257
+ } catch (e) {
258
+ expect(e.errors.length).toEqual(1)
259
+ expect(e.errors[0].code).toBe('ILLEGAL_STATUS_CHANGE')
260
+ }
261
+ })
@@ -71,3 +71,37 @@ test('should accept ignoreChannels', async () => {
71
71
 
72
72
  expect(result[0].objects['A-1'].status).toBe('lolzor')
73
73
  })
74
+
75
+ test('should accept allowedPreviousStatuses', async () => {
76
+ const { client, user } = await testUtils.createTestUserAndClient()
77
+ const chartKey = testUtils.getChartKey()
78
+ await testUtils.createTestChart(chartKey, user.secretKey)
79
+ const event = await client.events.create(chartKey)
80
+
81
+ try {
82
+ await client.events.changeObjectStatusInBatch([
83
+ new StatusChangeRequest(event.key, ['A-1'], 'lolzor', null, null, null, null, null, ['MustBeThisStatus'], null)
84
+ ])
85
+ throw new Error('Should have failed')
86
+ } catch (e) {
87
+ expect(e.errors.length).toEqual(1)
88
+ expect(e.errors[0].code).toBe('ILLEGAL_STATUS_CHANGE')
89
+ }
90
+ })
91
+
92
+ test('should accept rejectedPreviousStatuses', async () => {
93
+ const { client, user } = await testUtils.createTestUserAndClient()
94
+ const chartKey = testUtils.getChartKey()
95
+ await testUtils.createTestChart(chartKey, user.secretKey)
96
+ const event = await client.events.create(chartKey)
97
+
98
+ try {
99
+ await client.events.changeObjectStatusInBatch([
100
+ new StatusChangeRequest(event.key, ['A-1'], 'lolzor', null, null, null, true, null, null, ['free'])
101
+ ])
102
+ throw new Error('Should have failed')
103
+ } catch (e) {
104
+ expect(e.errors.length).toEqual(1)
105
+ expect(e.errors[0].code).toBe('ILLEGAL_STATUS_CHANGE')
106
+ }
107
+ })
@@ -174,6 +174,8 @@ test('properties of status changes', async () => {
174
174
  expect(statusChange.value.eventId).toBe(event.id)
175
175
  expect(statusChange.value.extraData).toEqual({ foo: 'bar' })
176
176
  expect(statusChange.value.origin.type).toBe('API_CALL')
177
+ expect(statusChange.value.displayedLabel).toBe('A-1')
178
+ expect(statusChange.value.isPresentOnChart).toBe(true)
177
179
  })
178
180
 
179
181
  test('should list status changes with hold token', async () => {
@@ -2,13 +2,13 @@ const Region = require('../src/Region')
2
2
  const { SeatsioClient } = require('../index.js')
3
3
 
4
4
  test('aborts eventually if server keeps returning 429', async () => {
5
- const client = new SeatsioClient(new Region('https://mockbin.org'))
5
+ const client = new SeatsioClient(new Region('https://httpbin.org'))
6
6
  const start = new Date()
7
7
  try {
8
- await client.client.get('/bin/0381d6f4-0155-4b8c-937b-73d3d88b2a3f')
8
+ await client.client.get('/status/429')
9
9
  throw new Error('Should have failed')
10
10
  } catch (e) {
11
- expect(e).toEqual({ errors: [{ code: 'RATE_LIMIT_EXCEEDED', message: 'Rate limit exceeded' }], messages: [], requestId: '123456', status: 429 })
11
+ expect(e).toBe('get /status/429 resulted in 429 TOO MANY REQUESTS error')
12
12
  const waitTime = new Date().getTime() - start.getTime()
13
13
  expect(waitTime).toBeGreaterThan(10000)
14
14
  expect(waitTime).toBeLessThan(20000)
@@ -16,26 +16,26 @@ test('aborts eventually if server keeps returning 429', async () => {
16
16
  })
17
17
 
18
18
  test('aborts directly if server returns error other than 429', async () => {
19
- const client = new SeatsioClient(new Region('https://mockbin.org'))
19
+ const client = new SeatsioClient(new Region('https://httpbin.org'))
20
20
  const start = new Date()
21
21
  try {
22
- await client.client.get('/bin/1eea3aab-2bb2-4f92-99c2-50d942fb6294')
22
+ await client.client.get('/status/400')
23
23
  throw new Error('Should have failed')
24
24
  } catch (e) {
25
- expect(e).toBe('get /bin/1eea3aab-2bb2-4f92-99c2-50d942fb6294 resulted in 400 Bad Request error')
25
+ expect(e).toBe('get /status/400 resulted in 400 BAD REQUEST error')
26
26
  const waitTime = new Date().getTime() - start.getTime()
27
27
  expect(waitTime).toBeLessThan(2000)
28
28
  }
29
29
  })
30
30
 
31
31
  test('aborts directly if server returns 429 but max retries 0', async () => {
32
- const client = new SeatsioClient(new Region('https://mockbin.org')).setMaxRetries(0)
32
+ const client = new SeatsioClient(new Region('https://httpbin.org')).setMaxRetries(0)
33
33
  const start = new Date()
34
34
  try {
35
- await client.client.get('/bin/0381d6f4-0155-4b8c-937b-73d3d88b2a3f')
35
+ await client.client.get('/status/429')
36
36
  throw new Error('Should have failed')
37
37
  } catch (e) {
38
- expect(e).toEqual({ errors: [{ code: 'RATE_LIMIT_EXCEEDED', message: 'Rate limit exceeded' }], messages: [], requestId: '123456', status: 429 })
38
+ expect(e).toBe('get /status/429 resulted in 429 TOO MANY REQUESTS error')
39
39
  const waitTime = new Date().getTime() - start.getTime()
40
40
  expect(waitTime).toBeLessThan(2000)
41
41
  }