@budibase/server 1.0.151 → 1.0.152

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 (164) hide show
  1. package/builder/assets/{index.e05b34c9.js → index.4f24612c.js} +1 -1
  2. package/builder/index.html +1 -1
  3. package/coverage/clover.xml +2 -2
  4. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  5. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  6. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  7. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/index.html +1 -1
  14. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  20. package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  25. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  34. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  39. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  40. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  43. package/coverage/lcov-report/api/index.html +1 -1
  44. package/coverage/lcov-report/api/index.js.html +1 -1
  45. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  46. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  47. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  48. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  49. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/index.html +1 -1
  56. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  70. package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  73. package/coverage/lcov-report/automations/actions.js.html +1 -1
  74. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  75. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  76. package/coverage/lcov-report/automations/index.html +1 -1
  77. package/coverage/lcov-report/automations/index.js.html +1 -1
  78. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  79. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  80. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  81. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/index.html +1 -1
  85. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  95. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  96. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  97. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  98. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  100. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  101. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  104. package/coverage/lcov-report/constants/index.html +1 -1
  105. package/coverage/lcov-report/constants/index.js.html +1 -1
  106. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  107. package/coverage/lcov-report/constants/screens.js.html +1 -1
  108. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  109. package/coverage/lcov-report/db/index.html +1 -1
  110. package/coverage/lcov-report/db/index.js.html +1 -1
  111. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  112. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  113. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  114. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  115. package/coverage/lcov-report/db/newid.js.html +1 -1
  116. package/coverage/lcov-report/db/utils.js.html +1 -1
  117. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  118. package/coverage/lcov-report/events/index.html +1 -1
  119. package/coverage/lcov-report/events/index.js.html +1 -1
  120. package/coverage/lcov-report/events/utils.js.html +1 -1
  121. package/coverage/lcov-report/index.html +1 -1
  122. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  123. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  124. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  125. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  126. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  127. package/coverage/lcov-report/middleware/index.html +1 -1
  128. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  129. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  130. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  131. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  132. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  133. package/coverage/lcov-report/threads/automation.js.html +1 -1
  134. package/coverage/lcov-report/threads/index.html +1 -1
  135. package/coverage/lcov-report/threads/query.js.html +1 -1
  136. package/coverage/lcov-report/threads/utils.js.html +1 -1
  137. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  138. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  139. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  140. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  141. package/coverage/lcov-report/utilities/global.js.html +1 -1
  142. package/coverage/lcov-report/utilities/index.html +1 -1
  143. package/coverage/lcov-report/utilities/index.js.html +1 -1
  144. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
  145. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  146. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  147. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  148. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  149. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  150. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  151. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  152. package/coverage/lcov-report/utilities/security.js.html +1 -1
  153. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  154. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  155. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  156. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  157. package/coverage/lcov-report/utilities/users.js.html +1 -1
  158. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  159. package/dist/api/controllers/row/index.js +12 -17
  160. package/dist/package.json +4 -4
  161. package/dist/tsconfig.build.tsbuildinfo +1 -1
  162. package/package.json +5 -5
  163. package/src/api/controllers/row/index.ts +19 -15
  164. package/src/api/routes/tests/row.spec.js +87 -5
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "1.0.151",
4
+ "version": "1.0.152",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -69,10 +69,10 @@
69
69
  "license": "GPL-3.0",
70
70
  "dependencies": {
71
71
  "@apidevtools/swagger-parser": "^10.0.3",
72
- "@budibase/backend-core": "^1.0.151",
73
- "@budibase/client": "^1.0.151",
72
+ "@budibase/backend-core": "^1.0.152",
73
+ "@budibase/client": "^1.0.152",
74
74
  "@budibase/pro": "1.0.150",
75
- "@budibase/string-templates": "^1.0.151",
75
+ "@budibase/string-templates": "^1.0.152",
76
76
  "@bull-board/api": "^3.7.0",
77
77
  "@bull-board/koa": "^3.7.0",
78
78
  "@elastic/elasticsearch": "7.10.0",
@@ -181,5 +181,5 @@
181
181
  "optionalDependencies": {
182
182
  "oracledb": "^5.3.0"
183
183
  },
184
- "gitHead": "232c22305480c7f88b7c7d50342363ea3aa3461e"
184
+ "gitHead": "c63faedf44006c984a20b0b0621350f48788bc2d"
185
185
  }
@@ -31,7 +31,9 @@ export async function patch(ctx: any): Promise<any> {
31
31
  return save(ctx)
32
32
  }
33
33
  try {
34
- const { row, table } = await pickApi(tableId).patch(ctx)
34
+ const { row, table } = await quotas.addQuery(() =>
35
+ pickApi(tableId).patch(ctx)
36
+ )
35
37
  ctx.status = 200
36
38
  ctx.eventEmitter &&
37
39
  ctx.eventEmitter.emitRow(`row:update`, appId, row, table)
@@ -42,7 +44,7 @@ export async function patch(ctx: any): Promise<any> {
42
44
  }
43
45
  }
44
46
 
45
- const saveRow = async (ctx: any) => {
47
+ export const save = async (ctx: any) => {
46
48
  const appId = ctx.appId
47
49
  const tableId = getTableId(ctx)
48
50
  const body = ctx.request.body
@@ -51,7 +53,9 @@ const saveRow = async (ctx: any) => {
51
53
  return patch(ctx)
52
54
  }
53
55
  try {
54
- const { row, table } = await pickApi(tableId).save(ctx)
56
+ const { row, table } = await quotas.addRow(() =>
57
+ quotas.addQuery(() => pickApi(tableId).save(ctx))
58
+ )
55
59
  ctx.status = 200
56
60
  ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:save`, appId, row, table)
57
61
  ctx.message = `${table.name} saved successfully`
@@ -61,14 +65,10 @@ const saveRow = async (ctx: any) => {
61
65
  }
62
66
  }
63
67
 
64
- export async function save(ctx: any) {
65
- await quotas.addRow(() => saveRow(ctx))
66
- }
67
-
68
68
  export async function fetchView(ctx: any) {
69
69
  const tableId = getTableId(ctx)
70
70
  try {
71
- ctx.body = await pickApi(tableId).fetchView(ctx)
71
+ ctx.body = await quotas.addQuery(() => pickApi(tableId).fetchView(ctx))
72
72
  } catch (err) {
73
73
  ctx.throw(400, err)
74
74
  }
@@ -77,7 +77,7 @@ export async function fetchView(ctx: any) {
77
77
  export async function fetch(ctx: any) {
78
78
  const tableId = getTableId(ctx)
79
79
  try {
80
- ctx.body = await pickApi(tableId).fetch(ctx)
80
+ ctx.body = await quotas.addQuery(() => pickApi(tableId).fetch(ctx))
81
81
  } catch (err) {
82
82
  ctx.throw(400, err)
83
83
  }
@@ -86,7 +86,7 @@ export async function fetch(ctx: any) {
86
86
  export async function find(ctx: any) {
87
87
  const tableId = getTableId(ctx)
88
88
  try {
89
- ctx.body = await pickApi(tableId).find(ctx)
89
+ ctx.body = await quotas.addQuery(() => pickApi(tableId).find(ctx))
90
90
  } catch (err) {
91
91
  ctx.throw(400, err)
92
92
  }
@@ -98,14 +98,16 @@ export async function destroy(ctx: any) {
98
98
  const tableId = getTableId(ctx)
99
99
  let response, row
100
100
  if (inputs.rows) {
101
- let { rows } = await pickApi(tableId).bulkDestroy(ctx)
101
+ let { rows } = await quotas.addQuery(() =>
102
+ pickApi(tableId).bulkDestroy(ctx)
103
+ )
102
104
  await quotas.removeRows(rows.length)
103
105
  response = rows
104
106
  for (let row of rows) {
105
107
  ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row)
106
108
  }
107
109
  } else {
108
- let resp = await pickApi(tableId).destroy(ctx)
110
+ let resp = await quotas.addQuery(() => pickApi(tableId).destroy(ctx))
109
111
  await quotas.removeRow()
110
112
  response = resp.response
111
113
  row = resp.row
@@ -121,7 +123,7 @@ export async function search(ctx: any) {
121
123
  const tableId = getTableId(ctx)
122
124
  try {
123
125
  ctx.status = 200
124
- ctx.body = await pickApi(tableId).search(ctx)
126
+ ctx.body = await quotas.addQuery(() => pickApi(tableId).search(ctx))
125
127
  } catch (err) {
126
128
  ctx.throw(400, err)
127
129
  }
@@ -139,7 +141,9 @@ export async function validate(ctx: any) {
139
141
  export async function fetchEnrichedRow(ctx: any) {
140
142
  const tableId = getTableId(ctx)
141
143
  try {
142
- ctx.body = await pickApi(tableId).fetchEnrichedRow(ctx)
144
+ ctx.body = await quotas.addQuery(() =>
145
+ pickApi(tableId).fetchEnrichedRow(ctx)
146
+ )
143
147
  } catch (err) {
144
148
  ctx.throw(400, err)
145
149
  }
@@ -148,7 +152,7 @@ export async function fetchEnrichedRow(ctx: any) {
148
152
  export const exportRows = async (ctx: any) => {
149
153
  const tableId = getTableId(ctx)
150
154
  try {
151
- ctx.body = await pickApi(tableId).exportRows(ctx)
155
+ ctx.body = await quotas.addQuery(() => pickApi(tableId).exportRows(ctx))
152
156
  } catch (err) {
153
157
  ctx.throw(400, err)
154
158
  }
@@ -3,6 +3,7 @@ const setup = require("./utilities")
3
3
  const { basicRow } = setup.structures
4
4
  const { doInAppContext } = require("@budibase/backend-core/context")
5
5
  const { doInTenant } = require("@budibase/backend-core/tenancy")
6
+ const { quotas, QuotaUsageType, StaticQuotaName, MonthlyQuotaName } = require("@budibase/pro")
6
7
 
7
8
  // mock the fetch for the search system
8
9
  jest.mock("node-fetch")
@@ -28,9 +29,29 @@ describe("/rows", () => {
28
29
  .expect('Content-Type', /json/)
29
30
  .expect(status)
30
31
 
32
+ const getRowUsage = async () => {
33
+ return config.doInContext(null, () => quotas.getCurrentUsageValue(QuotaUsageType.STATIC, StaticQuotaName.ROWS))
34
+ }
35
+
36
+ const getQueryUsage = async () => {
37
+ return config.doInContext(null, () => quotas.getCurrentUsageValue(QuotaUsageType.MONTHLY, MonthlyQuotaName.QUERIES))
38
+ }
39
+
40
+ const assertRowUsage = async (expected) => {
41
+ const usage = await getRowUsage()
42
+ expect(usage).toBe(expected)
43
+ }
44
+
45
+ const assertQueryUsage = async (expected) => {
46
+ const usage = await getQueryUsage()
47
+ expect(usage).toBe(expected)
48
+ }
31
49
 
32
50
  describe("save, load, update", () => {
33
51
  it("returns a success message when the row is created", async () => {
52
+ const rowUsage = await getRowUsage()
53
+ const queryUsage = await getQueryUsage()
54
+
34
55
  const res = await request
35
56
  .post(`/api/${row.tableId}/rows`)
36
57
  .send(row)
@@ -40,10 +61,14 @@ describe("/rows", () => {
40
61
  expect(res.res.statusMessage).toEqual(`${table.name} saved successfully`)
41
62
  expect(res.body.name).toEqual("Test Contact")
42
63
  expect(res.body._rev).toBeDefined()
64
+ await assertRowUsage(rowUsage + 1)
65
+ await assertQueryUsage(queryUsage + 1)
43
66
  })
44
67
 
45
68
  it("updates a row successfully", async () => {
46
69
  const existing = await config.createRow()
70
+ const rowUsage = await getRowUsage()
71
+ const queryUsage = await getQueryUsage()
47
72
 
48
73
  const res = await request
49
74
  .post(`/api/${table._id}/rows`)
@@ -59,10 +84,13 @@ describe("/rows", () => {
59
84
 
60
85
  expect(res.res.statusMessage).toEqual(`${table.name} updated successfully.`)
61
86
  expect(res.body.name).toEqual("Updated Name")
87
+ await assertRowUsage(rowUsage)
88
+ await assertQueryUsage(queryUsage + 1)
62
89
  })
63
90
 
64
91
  it("should load a row", async () => {
65
92
  const existing = await config.createRow()
93
+ const queryUsage = await getQueryUsage()
66
94
 
67
95
  const res = await request
68
96
  .get(`/api/${table._id}/rows/${existing._id}`)
@@ -76,6 +104,7 @@ describe("/rows", () => {
76
104
  _rev: existing._rev,
77
105
  type: "row",
78
106
  })
107
+ await assertQueryUsage(queryUsage + 1)
79
108
  })
80
109
 
81
110
  it("should list all rows for given tableId", async () => {
@@ -86,6 +115,7 @@ describe("/rows", () => {
86
115
  }
87
116
  await config.createRow()
88
117
  await config.createRow(newRow)
118
+ const queryUsage = await getQueryUsage()
89
119
 
90
120
  const res = await request
91
121
  .get(`/api/${table._id}/rows`)
@@ -96,15 +126,19 @@ describe("/rows", () => {
96
126
  expect(res.body.length).toBe(2)
97
127
  expect(res.body.find(r => r.name === newRow.name)).toBeDefined()
98
128
  expect(res.body.find(r => r.name === row.name)).toBeDefined()
129
+ await assertQueryUsage(queryUsage + 1)
99
130
  })
100
131
 
101
132
  it("load should return 404 when row does not exist", async () => {
102
133
  await config.createRow()
134
+ const queryUsage = await getQueryUsage()
135
+
103
136
  await request
104
137
  .get(`/api/${table._id}/rows/not-a-valid-id`)
105
138
  .set(config.defaultHeaders())
106
139
  .expect('Content-Type', /json/)
107
140
  .expect(404)
141
+ await assertQueryUsage(queryUsage) // no change
108
142
  })
109
143
 
110
144
  it("row values are coerced", async () => {
@@ -202,6 +236,9 @@ describe("/rows", () => {
202
236
  it("should update only the fields that are supplied", async () => {
203
237
  const existing = await config.createRow()
204
238
 
239
+ const rowUsage = await getRowUsage()
240
+ const queryUsage = await getQueryUsage()
241
+
205
242
  const res = await request
206
243
  .patch(`/api/${table._id}/rows`)
207
244
  .send({
@@ -222,10 +259,15 @@ describe("/rows", () => {
222
259
 
223
260
  expect(savedRow.body.description).toEqual(existing.description)
224
261
  expect(savedRow.body.name).toEqual("Updated Name")
262
+ await assertRowUsage(rowUsage)
263
+ await assertQueryUsage(queryUsage + 2) // account for the second load
225
264
  })
226
265
 
227
266
  it("should throw an error when given improper types", async () => {
228
267
  const existing = await config.createRow()
268
+ const rowUsage = await getRowUsage()
269
+ const queryUsage = await getQueryUsage()
270
+
229
271
  await request
230
272
  .patch(`/api/${table._id}/rows`)
231
273
  .send({
@@ -236,12 +278,18 @@ describe("/rows", () => {
236
278
  })
237
279
  .set(config.defaultHeaders())
238
280
  .expect(400)
281
+
282
+ await assertRowUsage(rowUsage)
283
+ await assertQueryUsage(queryUsage)
239
284
  })
240
285
  })
241
286
 
242
287
  describe("destroy", () => {
243
288
  it("should be able to delete a row", async () => {
244
289
  const createdRow = await config.createRow(row)
290
+ const rowUsage = await getRowUsage()
291
+ const queryUsage = await getQueryUsage()
292
+
245
293
  const res = await request
246
294
  .delete(`/api/${table._id}/rows`)
247
295
  .send({
@@ -253,11 +301,16 @@ describe("/rows", () => {
253
301
  .expect('Content-Type', /json/)
254
302
  .expect(200)
255
303
  expect(res.body[0]._id).toEqual(createdRow._id)
304
+ await assertRowUsage(rowUsage -1)
305
+ await assertQueryUsage(queryUsage +1)
256
306
  })
257
307
  })
258
308
 
259
309
  describe("validate", () => {
260
310
  it("should return no errors on valid row", async () => {
311
+ const rowUsage = await getRowUsage()
312
+ const queryUsage = await getQueryUsage()
313
+
261
314
  const res = await request
262
315
  .post(`/api/${table._id}/rows/validate`)
263
316
  .send({ name: "ivan" })
@@ -267,9 +320,14 @@ describe("/rows", () => {
267
320
 
268
321
  expect(res.body.valid).toBe(true)
269
322
  expect(Object.keys(res.body.errors)).toEqual([])
323
+ await assertRowUsage(rowUsage)
324
+ await assertQueryUsage(queryUsage)
270
325
  })
271
326
 
272
327
  it("should errors on invalid row", async () => {
328
+ const rowUsage = await getRowUsage()
329
+ const queryUsage = await getQueryUsage()
330
+
273
331
  const res = await request
274
332
  .post(`/api/${table._id}/rows/validate`)
275
333
  .send({ name: 1 })
@@ -279,7 +337,8 @@ describe("/rows", () => {
279
337
 
280
338
  expect(res.body.valid).toBe(false)
281
339
  expect(Object.keys(res.body.errors)).toEqual(["name"])
282
-
340
+ await assertRowUsage(rowUsage)
341
+ await assertQueryUsage(queryUsage)
283
342
  })
284
343
  })
285
344
 
@@ -287,6 +346,9 @@ describe("/rows", () => {
287
346
  it("should be able to delete a bulk set of rows", async () => {
288
347
  const row1 = await config.createRow()
289
348
  const row2 = await config.createRow()
349
+ const rowUsage = await getRowUsage()
350
+ const queryUsage = await getQueryUsage()
351
+
290
352
  const res = await request
291
353
  .delete(`/api/${table._id}/rows`)
292
354
  .send({
@@ -298,14 +360,20 @@ describe("/rows", () => {
298
360
  .set(config.defaultHeaders())
299
361
  .expect('Content-Type', /json/)
300
362
  .expect(200)
363
+
301
364
  expect(res.body.length).toEqual(2)
302
365
  await loadRow(row1._id, 404)
366
+ await assertRowUsage(rowUsage - 2)
367
+ await assertQueryUsage(queryUsage +1)
303
368
  })
304
369
  })
305
370
 
306
371
  describe("fetchView", () => {
307
372
  it("should be able to fetch tables contents via 'view'", async () => {
308
373
  const row = await config.createRow()
374
+ const rowUsage = await getRowUsage()
375
+ const queryUsage = await getQueryUsage()
376
+
309
377
  const res = await request
310
378
  .get(`/api/views/${table._id}`)
311
379
  .set(config.defaultHeaders())
@@ -313,18 +381,29 @@ describe("/rows", () => {
313
381
  .expect(200)
314
382
  expect(res.body.length).toEqual(1)
315
383
  expect(res.body[0]._id).toEqual(row._id)
384
+ await assertRowUsage(rowUsage)
385
+ await assertQueryUsage(queryUsage +1)
316
386
  })
317
387
 
318
388
  it("should throw an error if view doesn't exist", async () => {
389
+ const rowUsage = await getRowUsage()
390
+ const queryUsage = await getQueryUsage()
391
+
319
392
  await request
320
393
  .get(`/api/views/derp`)
321
394
  .set(config.defaultHeaders())
322
395
  .expect(404)
396
+
397
+ await assertRowUsage(rowUsage)
398
+ await assertQueryUsage(queryUsage)
323
399
  })
324
400
 
325
401
  it("should be able to run on a view", async () => {
326
402
  const view = await config.createView()
327
403
  const row = await config.createRow()
404
+ const rowUsage = await getRowUsage()
405
+ const queryUsage = await getQueryUsage()
406
+
328
407
  const res = await request
329
408
  .get(`/api/views/${view.name}`)
330
409
  .set(config.defaultHeaders())
@@ -332,11 +411,10 @@ describe("/rows", () => {
332
411
  .expect(200)
333
412
  expect(res.body.length).toEqual(1)
334
413
  expect(res.body[0]._id).toEqual(row._id)
335
- })
336
- })
337
-
338
- describe("user testing", () => {
339
414
 
415
+ await assertRowUsage(rowUsage)
416
+ await assertQueryUsage(queryUsage + 1)
417
+ })
340
418
  })
341
419
 
342
420
  describe("fetchEnrichedRows", () => {
@@ -356,6 +434,8 @@ describe("/rows", () => {
356
434
  })
357
435
  return { table, firstRow, secondRow }
358
436
  })
437
+ const rowUsage = await getRowUsage()
438
+ const queryUsage = await getQueryUsage()
359
439
 
360
440
  // test basic enrichment
361
441
  const resBasic = await request
@@ -376,6 +456,8 @@ describe("/rows", () => {
376
456
  expect(resEnriched.body.link[0]._id).toBe(firstRow._id)
377
457
  expect(resEnriched.body.link[0].name).toBe("Test Contact")
378
458
  expect(resEnriched.body.link[0].description).toBe("original description")
459
+ await assertRowUsage(rowUsage)
460
+ await assertQueryUsage(queryUsage +2)
379
461
  })
380
462
  })
381
463