1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240 | /**
* Executable full-coverage inventory: one entry per API operation (161
* total). Each entry invokes the client function against a recording
* transport and asserts the exact HTTP method and URL, so a renamed path or
* missing function fails loudly.
*/
import assert from 'node:assert/strict';
import { test } from 'node:test';
import type { Client } from '../src/client.js';
import {
auth,
credits,
dns,
domains,
ipfs,
jobs,
p2p,
pins,
registrations as reg,
sharing,
support,
transfers,
tunnels,
vps,
} from '../src/index.js';
import { captureClient } from './helpers.js';
const B = 'https://api.ird.ro';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnyFn = (client: Client, ...args: any[]) => Promise<unknown>;
type Op = readonly [description: string, fn: AnyFn, method: string, url: string, ...args: unknown[]];
const operations: readonly Op[] = [
// auth + api-keys (6)
['POST /auth/device/start', auth.deviceStart, 'POST', `${B}/auth/device/start`],
['POST /auth/device/poll', auth.devicePoll, 'POST', `${B}/auth/device/poll`, 'dc'],
['POST /auth/device/complete', auth.deviceComplete, 'POST', `${B}/auth/device/complete`, 'dc', 'cc'],
['GET /auth/api-keys', auth.listApiKeys, 'GET', `${B}/auth/api-keys`],
['POST /auth/api-keys', auth.createApiKey, 'POST', `${B}/auth/api-keys`, { name: 'ci' }],
['POST /auth/api-keys/{id}/revoke', auth.revokeApiKey, 'POST', `${B}/auth/api-keys/ak1/revoke`, 'ak1'],
// credits (3)
['GET /credits/balance', credits.balance, 'GET', `${B}/credits/balance`],
['GET /credits/ledger', credits.ledger, 'GET', `${B}/credits/ledger`],
['GET /credits/prices', credits.prices, 'GET', `${B}/credits/prices`],
// support (4)
['GET /contact/threads', support.listThreads, 'GET', `${B}/contact/threads`],
['POST /contact/threads', support.createThread, 'POST', `${B}/contact/threads`, { title: 't', service: 'general', message: 'm' }],
['GET /contact/threads/{id}', support.getThread, 'GET', `${B}/contact/threads/t1`, 't1'],
['POST /contact/threads/{id}/messages', support.reply, 'POST', `${B}/contact/threads/t1/messages`, 't1', { message: 'm' }],
// domains + directory (9)
['GET /domains/check', domains.check, 'GET', `${B}/domains/check?domain=x.ro`, 'x.ro'],
['GET /domains/info', domains.info, 'GET', `${B}/domains/info?domain=x.ro`, 'x.ro'],
['GET /domains/preflight', domains.preflight, 'GET', `${B}/domains/preflight?domain=x.ro`, 'x.ro'],
['GET /domains/dns-snapshot', domains.dnsSnapshot, 'GET', `${B}/domains/dns-snapshot?domain=x.ro`, 'x.ro'],
['GET /domains/search', domains.search, 'GET', `${B}/domains/search?q=shop`, 'shop'],
['POST /domains/search', domains.searchDescriptions, 'POST', `${B}/domains/search`, { q: 'an online shop' }],
['GET /domains/example', domains.example, 'GET', `${B}/domains/example`],
['GET /domains/directory', domains.directory, 'GET', `${B}/domains/directory`],
['GET /domains/directory/{domain}', domains.directoryEntry, 'GET', `${B}/domains/directory/x.ro`, 'x.ro'],
// registrations (27)
['GET /domains/registrations', reg.list, 'GET', `${B}/domains/registrations`],
['POST /domains/registrations', reg.register, 'POST', `${B}/domains/registrations`, { domain: 'x.ro' }],
['GET /domains/registrations/{id}', reg.get, 'GET', `${B}/domains/registrations/r1`, 'r1'],
['POST /domains/registrations/{id}/renew', reg.renew, 'POST', `${B}/domains/registrations/r1/renew`, 'r1'],
['PUT /domains/registrations/{id}/auto-renew', reg.setAutoRenew, 'PUT', `${B}/domains/registrations/r1/auto-renew`, 'r1', { enabled: true }],
['PUT /domains/registrations/{id}/sensitive', reg.setSensitive, 'PUT', `${B}/domains/registrations/r1/sensitive`, 'r1', { enabled: true }],
['PUT /domains/registrations/{id}/nameservers', reg.setNameservers, 'PUT', `${B}/domains/registrations/r1/nameservers`, 'r1', { nameservers: ['ns1.x.ro'] }],
['GET /domains/registrations/{id}/hosts', reg.listHosts, 'GET', `${B}/domains/registrations/r1/hosts`, 'r1'],
['POST /domains/registrations/{id}/hosts', reg.createHost, 'POST', `${B}/domains/registrations/r1/hosts`, 'r1', { host: 'ns1', ips: ['1.2.3.4'] }],
['PUT /domains/registrations/{id}/hosts/{host}', reg.setHostIps, 'PUT', `${B}/domains/registrations/r1/hosts/ns1.x.ro`, 'r1', 'ns1.x.ro', { ips: ['1.2.3.4'] }],
['DELETE /domains/registrations/{id}/hosts/{host}', reg.deleteHost, 'DELETE', `${B}/domains/registrations/r1/hosts/ns1.x.ro`, 'r1', 'ns1.x.ro'],
['GET /domains/registrations/{id}/dsdata', reg.listDsData, 'GET', `${B}/domains/registrations/r1/dsdata`, 'r1'],
['POST /domains/registrations/{id}/dsdata', reg.publishDsData, 'POST', `${B}/domains/registrations/r1/dsdata`, 'r1', { keytag: 1, alg: 13, digest_type: 2, digest: 'ab' }],
['DELETE /domains/registrations/{id}/dsdata', reg.withdrawDsData, 'DELETE', `${B}/domains/registrations/r1/dsdata`, 'r1', { keytag: 1, alg: 13, digest_type: 2, digest: 'ab' }],
['POST /domains/registrations/{id}/transfer-out', reg.transferOut, 'POST', `${B}/domains/registrations/r1/transfer-out`, 'r1'],
['PUT /domains/registrations/{id}/registrant', reg.updateRegistrant, 'PUT', `${B}/domains/registrations/r1/registrant`, 'r1', { email: 'a@b.ro' }],
['POST /domains/registrations/{id}/registrant-email/start', reg.startRegistrantEmailVerification, 'POST', `${B}/domains/registrations/r1/registrant-email/start`, 'r1'],
['POST /domains/registrations/{id}/registrant-email/confirm', reg.confirmRegistrantEmail, 'POST', `${B}/domains/registrations/r1/registrant-email/confirm`, 'r1', { token: 't', code: 'c' }],
['POST /domains/registrations/{id}/registrant-email/adopt', reg.adoptRegistrantEmail, 'POST', `${B}/domains/registrations/r1/registrant-email/adopt`, 'r1', { email: 'a@b.ro' }],
['GET /domains/registrations/{id}/trade', reg.quoteTrade, 'GET', `${B}/domains/registrations/r1/trade`, 'r1'],
['POST /domains/registrations/{id}/trade', reg.trade, 'POST', `${B}/domains/registrations/r1/trade`, 'r1', { auth_key: 'k' }],
['POST /domains/transfers-in', reg.transferIn, 'POST', `${B}/domains/transfers-in`, { domain: 'x.ro', auth_key: 'k' }],
['POST /domains/trades-in', reg.tradeIn, 'POST', `${B}/domains/trades-in`, { domain: 'x.ro', auth_key: 'k' }],
['POST /domains/adoptions', reg.adopt, 'POST', `${B}/domains/adoptions`, { domain: 'x.ro' }],
['GET /domains/actions', reg.listActions, 'GET', `${B}/domains/actions`],
['GET /domains/actions/{id}', reg.getAction, 'GET', `${B}/domains/actions/a1`, 'a1'],
['POST /domains/actions/{id}/cancel', reg.cancelAction, 'POST', `${B}/domains/actions/a1/cancel`, 'a1'],
// dns (18)
['POST /domains/registrations/{id}/dns', dns.enableHosting, 'POST', `${B}/domains/registrations/r1/dns`, 'r1'],
['DELETE /domains/registrations/{id}/dns', dns.disableHosting, 'DELETE', `${B}/domains/registrations/r1/dns`, 'r1'],
['GET /domains/registrations/{id}/dns/dnssec', dns.getDnssec, 'GET', `${B}/domains/registrations/r1/dns/dnssec`, 'r1'],
['POST /domains/registrations/{id}/dns/dnssec', dns.enableDnssec, 'POST', `${B}/domains/registrations/r1/dns/dnssec`, 'r1'],
['DELETE /domains/registrations/{id}/dns/dnssec', dns.disableDnssec, 'DELETE', `${B}/domains/registrations/r1/dns/dnssec`, 'r1'],
['GET /domains/registrations/{id}/dns/nameservers', dns.hostedNameservers, 'GET', `${B}/domains/registrations/r1/dns/nameservers`, 'r1'],
['POST /domains/registrations/{id}/dns/nameservers', dns.setHostedNameservers, 'POST', `${B}/domains/registrations/r1/dns/nameservers`, 'r1', { mode: 'labels' }],
['GET /dns/domains', dns.listZones, 'GET', `${B}/dns/domains`],
['GET /dns/domains/{domain}', dns.getZone, 'GET', `${B}/dns/domains/x.ro`, 'x.ro'],
['PUT /dns/domains/{domain}/records', dns.setRecord, 'PUT', `${B}/dns/domains/x.ro/records`, 'x.ro', { record: { name: 'www', type: 'A', value: '1.2.3.4' } }],
['DELETE /dns/domains/{domain}/records', dns.deleteRecord, 'DELETE', `${B}/dns/domains/x.ro/records`, 'x.ro', { name: 'www', type: 'A' }],
['GET /dns/claims', dns.listClaims, 'GET', `${B}/dns/claims`],
['POST /dns/claims', dns.createClaim, 'POST', `${B}/dns/claims`, { domain: 'example.com' }],
['GET /dns/claims/{id}', dns.getClaim, 'GET', `${B}/dns/claims/c1`, 'c1'],
['DELETE /dns/claims/{id}', dns.releaseClaim, 'DELETE', `${B}/dns/claims/c1`, 'c1'],
['PUT /dns/claims/{id}/seed', dns.seedClaim, 'PUT', `${B}/dns/claims/c1/seed`, 'c1', { snapshot_id: 's1' }],
['DELETE /dns/claims/{id}/seed', dns.unseedClaim, 'DELETE', `${B}/dns/claims/c1/seed`, 'c1'],
['POST /dns/claims/{id}/verify', dns.verifyClaim, 'POST', `${B}/dns/claims/c1/verify`, 'c1'],
// sharing (7)
['GET /domains/registrations/{id}/grants', sharing.listDomainGrants, 'GET', `${B}/domains/registrations/r1/grants`, 'r1'],
['POST /domains/registrations/{id}/grants', sharing.invite, 'POST', `${B}/domains/registrations/r1/grants`, 'r1', { email: 'a@b.ro', scopes: ['dns'] }],
['DELETE /domains/registrations/{id}/grants/{grant-id}', sharing.revokeGrant, 'DELETE', `${B}/domains/registrations/r1/grants/g1`, 'r1', 'g1'],
['GET /grants', sharing.listGrants, 'GET', `${B}/grants`],
['POST /grants/{id}/accept', sharing.acceptGrant, 'POST', `${B}/grants/g1/accept`, 'g1'],
['POST /grants/{id}/decline', sharing.declineGrant, 'POST', `${B}/grants/g1/decline`, 'g1'],
['POST /grants/{id}/leave', sharing.leaveGrant, 'POST', `${B}/grants/g1/leave`, 'g1'],
// vps (34)
['GET /vps/tiers', vps.listTiers, 'GET', `${B}/vps/tiers`],
['GET /vps/system-images', vps.listSystemImages, 'GET', `${B}/vps/system-images`],
['GET /vps/ssh-keys', vps.listSshKeys, 'GET', `${B}/vps/ssh-keys`],
['POST /vps/ssh-keys', vps.addSshKey, 'POST', `${B}/vps/ssh-keys`, { name: 'k', public_key: 'ssh-ed25519 AAA' }],
['DELETE /vps/ssh-keys/{id}', vps.deleteSshKey, 'DELETE', `${B}/vps/ssh-keys/k1`, 'k1'],
['GET /vps/availability', vps.availability, 'GET', `${B}/vps/availability`],
['GET /vps/instances', vps.listInstances, 'GET', `${B}/vps/instances`],
['POST /vps/instances', vps.createInstance, 'POST', `${B}/vps/instances`, { tier_id: 't1', image_ref: 'ubuntu' }],
['GET /vps/apps', vps.appCatalog, 'GET', `${B}/vps/apps`],
['GET /vps/apps/deployments', vps.listAppDeployments, 'GET', `${B}/vps/apps/deployments`],
['POST /vps/apps/deployments', vps.deployApp, 'POST', `${B}/vps/apps/deployments`, { app_id: 'a1', tier_id: 't1' }],
['GET /vps/apps/deployments/{id}', vps.getAppDeployment, 'GET', `${B}/vps/apps/deployments/d1`, 'd1'],
['POST /vps/apps/deployments/{id}/reveal-password', vps.revealAppPassword, 'POST', `${B}/vps/apps/deployments/d1/reveal-password`, 'd1'],
['GET /vps/instances/{id}', vps.getInstance, 'GET', `${B}/vps/instances/i1`, 'i1'],
['DELETE /vps/instances/{id}', vps.destroyInstance, 'DELETE', `${B}/vps/instances/i1`, 'i1'],
['GET /vps/instances/{id}/metrics', vps.getMetrics, 'GET', `${B}/vps/instances/i1/metrics`, 'i1'],
['POST /vps/instances/{id}/queue-notify', vps.setQueueNotify, 'POST', `${B}/vps/instances/i1/queue-notify`, 'i1', { enabled: true }],
['POST /vps/instances/{id}/images', vps.createSnapshot, 'POST', `${B}/vps/instances/i1/images`, 'i1'],
['POST /vps/instances/{id}/restart', vps.restart, 'POST', `${B}/vps/instances/i1/restart`, 'i1'],
['POST /vps/instances/{id}/reset', vps.reset, 'POST', `${B}/vps/instances/i1/reset`, 'i1'],
['POST /vps/instances/{id}/shutdown', vps.shutdown, 'POST', `${B}/vps/instances/i1/shutdown`, 'i1'],
['POST /vps/instances/{id}/power-off', vps.powerOff, 'POST', `${B}/vps/instances/i1/power-off`, 'i1'],
['POST /vps/instances/{id}/power-on', vps.powerOn, 'POST', `${B}/vps/instances/i1/power-on`, 'i1'],
['PUT /vps/instances/{id}/rdns', vps.setRdns, 'PUT', `${B}/vps/instances/i1/rdns`, 'i1', { hostname: 'srv.x.ro' }],
['GET /vps/instances/{id}/domains', vps.listInstanceDomains, 'GET', `${B}/vps/instances/i1/domains`, 'i1'],
['POST /vps/instances/{id}/domains', vps.connectDomain, 'POST', `${B}/vps/instances/i1/domains`, 'i1', { zone: 'x.ro', subdomain: 'www' }],
['DELETE /vps/instances/{id}/domains/{connection-id}', vps.disconnectDomain, 'DELETE', `${B}/vps/instances/i1/domains/c1`, 'i1', 'c1'],
['GET /vps/volumes', vps.listVolumes, 'GET', `${B}/vps/volumes`],
['POST /vps/volumes', vps.createVolume, 'POST', `${B}/vps/volumes`, { name: 'v', size_gb: 10 }],
['DELETE /vps/volumes/{id}', vps.deleteVolume, 'DELETE', `${B}/vps/volumes/v1`, 'v1'],
['GET /vps/images', vps.listImages, 'GET', `${B}/vps/images`],
['DELETE /vps/images/{id}', vps.deleteImage, 'DELETE', `${B}/vps/images/img1`, 'img1'],
['GET /vps/actions/{id}', vps.getAction, 'GET', `${B}/vps/actions/a1`, 'a1'],
['GET /vps/activity', vps.listActivity, 'GET', `${B}/vps/activity`],
// transfers (9)
['POST /vps/instances/{id}/transfer', transfers.offerInstance, 'POST', `${B}/vps/instances/i1/transfer`, 'i1', { email: 'a@b.ro' }],
['DELETE /vps/instances/{id}/transfer', transfers.withdrawInstanceOffer, 'DELETE', `${B}/vps/instances/i1/transfer`, 'i1'],
['POST /vps/volumes/{id}/transfer', transfers.offerVolume, 'POST', `${B}/vps/volumes/v1/transfer`, 'v1', { email: 'a@b.ro' }],
['DELETE /vps/volumes/{id}/transfer', transfers.withdrawVolumeOffer, 'DELETE', `${B}/vps/volumes/v1/transfer`, 'v1'],
['POST /vps/images/{id}/transfer', transfers.offerImage, 'POST', `${B}/vps/images/img1/transfer`, 'img1', { email: 'a@b.ro' }],
['DELETE /vps/images/{id}/transfer', transfers.withdrawImageOffer, 'DELETE', `${B}/vps/images/img1/transfer`, 'img1'],
['GET /vps/transfers', transfers.list, 'GET', `${B}/vps/transfers`],
['POST /vps/transfers/{id}/accept', transfers.accept, 'POST', `${B}/vps/transfers/tr1/accept`, 'tr1'],
['POST /vps/transfers/{id}/decline', transfers.decline, 'POST', `${B}/vps/transfers/tr1/decline`, 'tr1'],
// tunnels (6)
['GET /tunnels', tunnels.list, 'GET', `${B}/tunnels`],
['POST /tunnels', tunnels.create, 'POST', `${B}/tunnels`, { hostname: 'dev.x.ro' }],
['GET /tunnels/{id}', tunnels.get, 'GET', `${B}/tunnels/tn1`, 'tn1'],
['DELETE /tunnels/{id}', tunnels.remove, 'DELETE', `${B}/tunnels/tn1`, 'tn1'],
['PATCH /tunnels/{id}', tunnels.update, 'PATCH', `${B}/tunnels/tn1`, 'tn1', { settings: {} }],
['POST /tunnels/{id}/verify-dns', tunnels.verifyDns, 'POST', `${B}/tunnels/tn1/verify-dns`, 'tn1'],
// ipfs (18)
['GET /ipfs/pins', ipfs.listPins, 'GET', `${B}/ipfs/pins`],
['POST /ipfs/pins', ipfs.pin, 'POST', `${B}/ipfs/pins`, { cid: 'bafy1' }],
['GET /ipfs/pins/{id}', ipfs.getPin, 'GET', `${B}/ipfs/pins/p1`, 'p1'],
['DELETE /ipfs/pins/{id}', ipfs.unpin, 'DELETE', `${B}/ipfs/pins/p1`, 'p1'],
['POST /ipfs/uploads', ipfs.startUpload, 'POST', `${B}/ipfs/uploads`],
['GET /ipfs/uploads/{id}', ipfs.getUpload, 'GET', `${B}/ipfs/uploads/u1`, 'u1'],
['GET /ipfs/names', ipfs.listNames, 'GET', `${B}/ipfs/names`],
['POST /ipfs/names', ipfs.createName, 'POST', `${B}/ipfs/names`],
['GET /ipfs/names/{id}', ipfs.getName, 'GET', `${B}/ipfs/names/n1`, 'n1'],
['DELETE /ipfs/names/{id}', ipfs.deleteName, 'DELETE', `${B}/ipfs/names/n1`, 'n1'],
['PUT /ipfs/names/{id}/target', ipfs.publishTarget, 'PUT', `${B}/ipfs/names/n1/target`, 'n1', { cid: 'bafy1' }],
['GET /ipfs/domains', ipfs.listDomains, 'GET', `${B}/ipfs/domains`],
['POST /ipfs/domains', ipfs.attachDomain, 'POST', `${B}/ipfs/domains`, { domain: 'gw.x.ro' }],
['GET /ipfs/domains/{id}', ipfs.getDomain, 'GET', `${B}/ipfs/domains/d1`, 'd1'],
['GET /ipfs/domains/{id}/pins', ipfs.listDomainPins, 'GET', `${B}/ipfs/domains/d1/pins`, 'd1'],
['POST /ipfs/domains/{id}/pins', ipfs.updateDomainPins, 'POST', `${B}/ipfs/domains/d1/pins`, 'd1', { add: ['p1'] }],
['DELETE /ipfs/domains/{id}', ipfs.detachDomain, 'DELETE', `${B}/ipfs/domains/d1`, 'd1'],
['GET /ipfs/usage', ipfs.usage, 'GET', `${B}/ipfs/usage`],
// pins — Pinning Service API (5)
['GET /pins', pins.list, 'GET', `${B}/pins`],
['POST /pins', pins.add, 'POST', `${B}/pins`, { cid: 'bafy1' }],
['GET /pins/{requestid}', pins.get, 'GET', `${B}/pins/rq1`, 'rq1'],
['POST /pins/{requestid}', pins.replace, 'POST', `${B}/pins/rq1`, 'rq1', { cid: 'bafy2' }],
['DELETE /pins/{requestid}', pins.remove, 'DELETE', `${B}/pins/rq1`, 'rq1'],
// p2p (12)
['GET /p2p/apps', p2p.listApps, 'GET', `${B}/p2p/apps`],
['POST /p2p/apps', p2p.createApp, 'POST', `${B}/p2p/apps`, { name: 'app' }],
['GET /p2p/apps/{id}', p2p.getApp, 'GET', `${B}/p2p/apps/a1`, 'a1'],
['DELETE /p2p/apps/{id}', p2p.deleteApp, 'DELETE', `${B}/p2p/apps/a1`, 'a1'],
['PATCH /p2p/apps/{id}', p2p.updateApp, 'PATCH', `${B}/p2p/apps/a1`, 'a1', { origins: ['https://x.ro'] }],
['POST /p2p/apps/{id}/turn-credentials', p2p.mintTurnCredentials, 'POST', `${B}/p2p/apps/a1/turn-credentials`, 'a1'],
['POST /p2p/apps/{id}/mailbox-credentials', p2p.mintMailboxCredentials, 'POST', `${B}/p2p/apps/a1/mailbox-credentials`, 'a1'],
['GET /p2p/apps/{id}/domains', p2p.listAppDomains, 'GET', `${B}/p2p/apps/a1/domains`, 'a1'],
['POST /p2p/apps/{id}/domains', p2p.attachDomain, 'POST', `${B}/p2p/apps/a1/domains`, 'a1', { hostname: 'p2p.x.ro' }],
['DELETE /p2p/apps/{id}/domains/{domain-id}', p2p.detachDomain, 'DELETE', `${B}/p2p/apps/a1/domains/d1`, 'a1', 'd1'],
['POST /p2p/apps/{id}/domains/{domain-id}/verify-dns', p2p.verifyDomainDns, 'POST', `${B}/p2p/apps/a1/domains/d1/verify-dns`, 'a1', 'd1'],
['GET /p2p/usage', p2p.usage, 'GET', `${B}/p2p/usage`],
// jobs (3)
['POST /jobs', jobs.enqueue, 'POST', `${B}/jobs`, { type: 'embedding', input: 'x' }],
['GET /jobs/{id}', jobs.get, 'GET', `${B}/jobs/j1`, 'j1'],
['GET /jobs/{id}/result', jobs.getResult, 'GET', `${B}/jobs/j1/result`, 'j1'],
];
test('the inventory covers every one of the spec 161 operations', () => {
assert.equal(operations.length, 161);
assert.equal(new Set(operations.map(([description]) => description)).size, 161, 'no duplicate entries');
});
test('every operation hits the exact method and URL', async (t) => {
for (const [description, fn, method, url, ...args] of operations) {
await t.test(description, async () => {
const { client, calls } = captureClient({ apiKey: 'ird_k' });
await fn(client, ...args);
assert.equal(calls.length, 1, 'exactly one request');
assert.equal(calls[0]!.method, method);
assert.equal(calls[0]!.url, url);
});
}
});
|