@tscircuit/fake-snippets 0.0.35 → 0.0.37

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.
@@ -24,8 +24,5 @@ jobs:
24
24
  - name: Install dependencies
25
25
  run: bun install
26
26
 
27
- - name: Set environment variable
28
- run: echo "BUN_TEST=true" >> $GITHUB_ENV
29
-
30
27
  - name: Run tests
31
28
  run: bun test
@@ -4,6 +4,7 @@ import { startServer } from "./start-server"
4
4
  import { DbClient } from "fake-snippets-api/lib/db/db-client"
5
5
  import getPort from "get-port"
6
6
 
7
+ process.env.BUN_TEST = "true"
7
8
  interface TestFixture {
8
9
  url: string
9
10
  server: any
@@ -0,0 +1,575 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { expect, test } from "bun:test"
3
+
4
+ test("create new package file with content_text", async () => {
5
+ const { axios } = await getTestServer()
6
+
7
+ const packageResponse = await axios.post("/api/packages/create", {
8
+ name: "@test/package-files-create-or-update",
9
+ description: "A test package for creating or updating files",
10
+ })
11
+ expect(packageResponse.status).toBe(200)
12
+ const createdPackage = packageResponse.data.package
13
+
14
+ const releaseResponse = await axios.post("/api/package_releases/create", {
15
+ package_id: createdPackage.package_id,
16
+ version: "1.0.0",
17
+ is_latest: true,
18
+ })
19
+ expect(releaseResponse.status).toBe(200)
20
+ const createdRelease = releaseResponse.data.package_release
21
+
22
+ const fileContent = "console.log('Hello, world!');"
23
+ const filePath = "/index.js"
24
+ const createResponse = await axios.post(
25
+ "/api/package_files/create_or_update",
26
+ {
27
+ package_release_id: createdRelease.package_release_id,
28
+ file_path: filePath,
29
+ content_text: fileContent,
30
+ },
31
+ )
32
+
33
+ expect(createResponse.status).toBe(200)
34
+ const responseBody = createResponse.data
35
+ expect(responseBody.ok).toBe(true)
36
+ expect(responseBody.package_file).toBeDefined()
37
+ expect(responseBody.package_file.package_release_id).toBe(
38
+ createdRelease.package_release_id,
39
+ )
40
+ expect(responseBody.package_file.file_path).toBe(filePath)
41
+ expect(responseBody.package_file.content_text).toBe(fileContent)
42
+
43
+ const getResponse = await axios.post("/api/package_files/get", {
44
+ package_file_id: responseBody.package_file.package_file_id,
45
+ })
46
+ expect(getResponse.status).toBe(200)
47
+ expect(getResponse.data.package_file.file_path).toBe(filePath)
48
+ })
49
+
50
+ test("update existing package file with content_text", async () => {
51
+ const { axios } = await getTestServer()
52
+
53
+ const packageResponse = await axios.post("/api/packages/create", {
54
+ name: "@test/package-files-update",
55
+ description: "A test package for updating files",
56
+ })
57
+ expect(packageResponse.status).toBe(200)
58
+ const createdPackage = packageResponse.data.package
59
+
60
+ const releaseResponse = await axios.post("/api/package_releases/create", {
61
+ package_id: createdPackage.package_id,
62
+ version: "1.0.0",
63
+ is_latest: true,
64
+ })
65
+ expect(releaseResponse.status).toBe(200)
66
+ const createdRelease = releaseResponse.data.package_release
67
+
68
+ const initialContent = "console.log('Initial content');"
69
+ const filePath = "/script.js"
70
+ const createResponse = await axios.post(
71
+ "/api/package_files/create_or_update",
72
+ {
73
+ package_release_id: createdRelease.package_release_id,
74
+ file_path: filePath,
75
+ content_text: initialContent,
76
+ },
77
+ )
78
+ expect(createResponse.status).toBe(200)
79
+ const initialFile = createResponse.data.package_file
80
+
81
+ const updatedContent = "console.log('Updated content');"
82
+ const updateResponse = await axios.post(
83
+ "/api/package_files/create_or_update",
84
+ {
85
+ package_release_id: createdRelease.package_release_id,
86
+ file_path: filePath,
87
+ content_text: updatedContent,
88
+ },
89
+ )
90
+
91
+ expect(updateResponse.status).toBe(200)
92
+ const responseBody = updateResponse.data
93
+ expect(responseBody.ok).toBe(true)
94
+ expect(responseBody.package_file).toBeDefined()
95
+ expect(responseBody.package_file.package_file_id).toBe(
96
+ initialFile.package_file_id,
97
+ )
98
+ expect(responseBody.package_file.package_release_id).toBe(
99
+ createdRelease.package_release_id,
100
+ )
101
+ expect(responseBody.package_file.file_path).toBe(filePath)
102
+ expect(responseBody.package_file.content_text).toBe(updatedContent)
103
+
104
+ const getResponse = await axios.post("/api/package_files/get", {
105
+ package_file_id: responseBody.package_file.package_file_id,
106
+ })
107
+ expect(getResponse.status).toBe(200)
108
+ expect(getResponse.data.package_file.file_path).toBe(filePath)
109
+ })
110
+
111
+ test("create package file with content_base64", async () => {
112
+ const { axios } = await getTestServer()
113
+
114
+ const packageResponse = await axios.post("/api/packages/create", {
115
+ name: "@test/package-files-create-or-update-base64",
116
+ description: "A test package for creating files with base64",
117
+ })
118
+ expect(packageResponse.status).toBe(200)
119
+ const createdPackage = packageResponse.data.package
120
+
121
+ const releaseResponse = await axios.post("/api/package_releases/create", {
122
+ package_id: createdPackage.package_id,
123
+ version: "1.0.0",
124
+ is_latest: true,
125
+ })
126
+ expect(releaseResponse.status).toBe(200)
127
+ const createdRelease = releaseResponse.data.package_release
128
+
129
+ const fileContent = "export const sum = (a, b) => a + b;"
130
+ const base64Content = Buffer.from(fileContent).toString("base64")
131
+ const filePath = "/utils.js"
132
+ const createResponse = await axios.post(
133
+ "/api/package_files/create_or_update",
134
+ {
135
+ package_release_id: createdRelease.package_release_id,
136
+ file_path: filePath,
137
+ content_base64: base64Content,
138
+ },
139
+ )
140
+
141
+ expect(createResponse.status).toBe(200)
142
+ const responseBody = createResponse.data
143
+ expect(responseBody.ok).toBe(true)
144
+ expect(responseBody.package_file).toBeDefined()
145
+ expect(responseBody.package_file.file_path).toBe(filePath)
146
+ expect(responseBody.package_file.content_text).toBe(fileContent)
147
+
148
+ const getResponse = await axios.post("/api/package_files/get", {
149
+ package_file_id: responseBody.package_file.package_file_id,
150
+ })
151
+ expect(getResponse.status).toBe(200)
152
+ expect(getResponse.data.package_file.file_path).toBe(filePath)
153
+ })
154
+
155
+ test("create package file using package_name_with_version", async () => {
156
+ const { axios } = await getTestServer()
157
+
158
+ const packageName = "@test/package-files-create-or-update-by-name"
159
+ const version = "2.0.0"
160
+ const packageResponse = await axios.post("/api/packages/create", {
161
+ name: packageName,
162
+ description: "A test package for creating files by name",
163
+ })
164
+ expect(packageResponse.status).toBe(200)
165
+ const createdPackage = packageResponse.data.package
166
+
167
+ const releaseResponse = await axios.post("/api/package_releases/create", {
168
+ package_id: createdPackage.package_id,
169
+ version,
170
+ is_latest: true,
171
+ })
172
+ expect(releaseResponse.status).toBe(200)
173
+
174
+ const fileContent = "# README\nThis is a test package."
175
+ const filePath = "/README.md"
176
+ const createResponse = await axios.post(
177
+ "/api/package_files/create_or_update",
178
+ {
179
+ package_name_with_version: `${packageName}@${version}`,
180
+ file_path: filePath,
181
+ content_text: fileContent,
182
+ },
183
+ )
184
+
185
+ expect(createResponse.status).toBe(200)
186
+ const responseBody = createResponse.data
187
+ expect(responseBody.ok).toBe(true)
188
+ expect(responseBody.package_file).toBeDefined()
189
+ expect(responseBody.package_file.file_path).toBe(filePath)
190
+ expect(responseBody.package_file.content_text).toBe(fileContent)
191
+
192
+ const listResponse = await axios.post("/api/package_files/list", {
193
+ package_name_with_version: `${packageName}@${version}`,
194
+ })
195
+ expect(listResponse.status).toBe(200)
196
+ expect(listResponse.data.ok).toBe(true)
197
+ expect(listResponse.data.package_files.length).toBeGreaterThan(0)
198
+ const foundFile = listResponse.data.package_files.find(
199
+ (file: any) => file.file_path === filePath,
200
+ )
201
+ expect(foundFile).toBeDefined()
202
+ })
203
+
204
+ test("create release tarball package file", async () => {
205
+ const { axios } = await getTestServer()
206
+
207
+ const packageResponse = await axios.post("/api/packages/create", {
208
+ name: "@test/package-files-create-or-update-tarball",
209
+ description: "A test package for creating tarball files",
210
+ })
211
+ expect(packageResponse.status).toBe(200)
212
+ const createdPackage = packageResponse.data.package
213
+
214
+ const releaseResponse = await axios.post("/api/package_releases/create", {
215
+ package_id: createdPackage.package_id,
216
+ version: "1.0.0",
217
+ is_latest: true,
218
+ })
219
+ expect(releaseResponse.status).toBe(200)
220
+ const createdRelease = releaseResponse.data.package_release
221
+
222
+ const npmPackOutput = { filename: "test-1.0.0.tgz", size: 1024 }
223
+ const createResponse = await axios.post(
224
+ "/api/package_files/create_or_update",
225
+ {
226
+ package_release_id: createdRelease.package_release_id,
227
+ file_path: "/test-1.0.0.tgz",
228
+ content_text: "tarball content",
229
+ is_release_tarball: true,
230
+ npm_pack_output: npmPackOutput,
231
+ },
232
+ )
233
+
234
+ expect(createResponse.status).toBe(200)
235
+ const responseBody = createResponse.data
236
+ expect(responseBody.ok).toBe(true)
237
+ expect(responseBody.package_file).toBeDefined()
238
+ expect(responseBody.package_file.package_release_id).toBe(
239
+ createdRelease.package_release_id,
240
+ )
241
+ expect(responseBody.package_file.file_path).toBe("/test-1.0.0.tgz")
242
+ expect(responseBody.package_file.content_text).toBe("tarball content")
243
+ expect(responseBody.package_file.is_release_tarball).toBe(true)
244
+ expect(responseBody.package_file.npm_pack_output).toEqual(npmPackOutput)
245
+ })
246
+
247
+ test("create_or_update - 404 for non-existent package release", async () => {
248
+ const { axios } = await getTestServer()
249
+
250
+ try {
251
+ await axios.post("/api/package_files/create_or_update", {
252
+ package_release_id: "non-existent-id",
253
+ file_path: "/test.js",
254
+ content_text: "console.log('test');",
255
+ })
256
+ throw new Error("Expected request to fail")
257
+ } catch (error: any) {
258
+ expect(error.status).toBe(404)
259
+ expect(error.data.error.error_code).toBe("package_release_not_found")
260
+ expect(error.data.error.message).toBe("Package release not found")
261
+ }
262
+ })
263
+
264
+ test("create_or_update - 404 for non-existent package", async () => {
265
+ const { axios } = await getTestServer()
266
+
267
+ try {
268
+ await axios.post("/api/package_files/create_or_update", {
269
+ package_name_with_version: "non-existent-package@1.0.0",
270
+ file_path: "/test.js",
271
+ content_text: "console.log('test');",
272
+ })
273
+ throw new Error("Expected request to fail")
274
+ } catch (error: any) {
275
+ expect(error.status).toBe(404)
276
+ expect(error.data.error.error_code).toBe("package_release_not_found")
277
+ expect(error.data.error.message).toBe("Package release not found")
278
+ }
279
+ })
280
+
281
+ test("create_or_update - 400 for missing content", async () => {
282
+ const { axios } = await getTestServer()
283
+
284
+ const packageResponse = await axios.post("/api/packages/create", {
285
+ name: "@test/package-files-create-or-update-error",
286
+ description: "A test package for error cases",
287
+ })
288
+ const createdPackage = packageResponse.data.package
289
+
290
+ const releaseResponse = await axios.post("/api/package_releases/create", {
291
+ package_id: createdPackage.package_id,
292
+ version: "1.0.0",
293
+ })
294
+ const createdRelease = releaseResponse.data.package_release
295
+
296
+ try {
297
+ await axios.post("/api/package_files/create_or_update", {
298
+ package_release_id: createdRelease.package_release_id,
299
+ file_path: "/test.js",
300
+ })
301
+ throw new Error("Expected request to fail")
302
+ } catch (error: any) {
303
+ expect(error.status).toBe(400)
304
+ expect(error.data.message).toContain("content")
305
+ }
306
+ })
307
+
308
+ test("create_or_update - 400 for both content_text and content_base64", async () => {
309
+ const { axios } = await getTestServer()
310
+
311
+ const packageResponse = await axios.post("/api/packages/create", {
312
+ name: "@test/package-files-create-or-update-error-2",
313
+ description: "Another test package for error cases",
314
+ })
315
+ const createdPackage = packageResponse.data.package
316
+
317
+ const releaseResponse = await axios.post("/api/package_releases/create", {
318
+ package_id: createdPackage.package_id,
319
+ version: "1.0.0",
320
+ })
321
+ const createdRelease = releaseResponse.data.package_release
322
+
323
+ try {
324
+ await axios.post("/api/package_files/create_or_update", {
325
+ package_release_id: createdRelease.package_release_id,
326
+ file_path: "/test.js",
327
+ content_text: "console.log('test');",
328
+ content_base64: "Y29uc29sZS5sb2coJ3Rlc3QnKTs=",
329
+ })
330
+ throw new Error("Expected request to fail")
331
+ } catch (error: any) {
332
+ expect(error.status).toBe(400)
333
+ expect(error.data.message).toContain("content")
334
+ }
335
+ })
336
+
337
+ test("create_or_update - 400 for release tarball without npm_pack_output", async () => {
338
+ const { axios } = await getTestServer()
339
+
340
+ const packageResponse = await axios.post("/api/packages/create", {
341
+ name: "@test/package-files-create-or-update-tarball-error",
342
+ description: "Test package for tarball error cases",
343
+ })
344
+ const createdPackage = packageResponse.data.package
345
+
346
+ const releaseResponse = await axios.post("/api/package_releases/create", {
347
+ package_id: createdPackage.package_id,
348
+ version: "1.0.0",
349
+ })
350
+ const createdRelease = releaseResponse.data.package_release
351
+
352
+ try {
353
+ await axios.post("/api/package_files/create_or_update", {
354
+ package_release_id: createdRelease.package_release_id,
355
+ file_path: "/test-1.0.0.tgz",
356
+ content_text: "tarball content",
357
+ is_release_tarball: true,
358
+ })
359
+ throw new Error("Expected request to fail")
360
+ } catch (error: any) {
361
+ expect(error.status).toBe(400)
362
+ expect(error.data.error.error_code).toBe("missing_options")
363
+ expect(error.data.error.message).toBe(
364
+ "npm_pack_output is required for release tarballs",
365
+ )
366
+ }
367
+ })
368
+
369
+ test("create_or_update - 404 for npm_pack_output without is_release_tarball", async () => {
370
+ const { axios } = await getTestServer()
371
+
372
+ const packageResponse = await axios.post("/api/packages/create", {
373
+ name: "@test/package-files-create-or-update-tarball-error-2",
374
+ description: "Test package for tarball error cases",
375
+ })
376
+ const createdPackage = packageResponse.data.package
377
+
378
+ const releaseResponse = await axios.post("/api/package_releases/create", {
379
+ package_id: createdPackage.package_id,
380
+ version: "1.0.0",
381
+ })
382
+ const createdRelease = releaseResponse.data.package_release
383
+
384
+ try {
385
+ await axios.post("/api/package_files/create_or_update", {
386
+ package_release_id: createdRelease.package_release_id,
387
+ file_path: "/test.js",
388
+ content_text: "console.log('test');",
389
+ npm_pack_output: { filename: "test.tgz", size: 1024 },
390
+ })
391
+ throw new Error("Expected request to fail")
392
+ } catch (error: any) {
393
+ expect(error.status).toBe(404)
394
+ expect(error.data.error.error_code).toBe("invalid_options")
395
+ expect(error.data.error.message).toBe(
396
+ "npm_pack_output is only valid for release tarballs",
397
+ )
398
+ }
399
+ })
400
+
401
+ test("update package file with content_base64", async () => {
402
+ const { axios } = await getTestServer()
403
+
404
+ const packageResponse = await axios.post("/api/packages/create", {
405
+ name: "@test/package-files-update-base64",
406
+ description: "A test package for updating files with base64",
407
+ })
408
+ expect(packageResponse.status).toBe(200)
409
+ const createdPackage = packageResponse.data.package
410
+
411
+ const releaseResponse = await axios.post("/api/package_releases/create", {
412
+ package_id: createdPackage.package_id,
413
+ version: "1.0.0",
414
+ is_latest: true,
415
+ })
416
+ expect(releaseResponse.status).toBe(200)
417
+ const createdRelease = releaseResponse.data.package_release
418
+
419
+ const initialContent = "console.log('Initial content');"
420
+ const filePath = "/script.js"
421
+ const createResponse = await axios.post(
422
+ "/api/package_files/create_or_update",
423
+ {
424
+ package_release_id: createdRelease.package_release_id,
425
+ file_path: filePath,
426
+ content_text: initialContent,
427
+ },
428
+ )
429
+ expect(createResponse.status).toBe(200)
430
+ const initialFile = createResponse.data.package_file
431
+
432
+ const updatedContent = "console.log('Updated with base64');"
433
+ const base64Content = Buffer.from(updatedContent).toString("base64")
434
+ const updateResponse = await axios.post(
435
+ "/api/package_files/create_or_update",
436
+ {
437
+ package_release_id: createdRelease.package_release_id,
438
+ file_path: filePath,
439
+ content_base64: base64Content,
440
+ },
441
+ )
442
+
443
+ expect(updateResponse.status).toBe(200)
444
+ const responseBody = updateResponse.data
445
+ expect(responseBody.ok).toBe(true)
446
+ expect(responseBody.package_file).toBeDefined()
447
+ expect(responseBody.package_file.package_file_id).toBe(
448
+ initialFile.package_file_id,
449
+ )
450
+ expect(responseBody.package_file.content_text).toBe(updatedContent)
451
+
452
+ const getResponse = await axios.post("/api/package_files/get", {
453
+ package_file_id: responseBody.package_file.package_file_id,
454
+ })
455
+ expect(getResponse.status).toBe(200)
456
+ expect(getResponse.data.package_file.file_path).toBe(filePath)
457
+ })
458
+
459
+ test("create_or_update detects correct content mimetype", async () => {
460
+ const { axios } = await getTestServer()
461
+
462
+ const packageResponse = await axios.post("/api/packages/create", {
463
+ name: "@test/package-files-mimetype",
464
+ description: "A test package for testing mimetypes",
465
+ })
466
+ expect(packageResponse.status).toBe(200)
467
+ const createdPackage = packageResponse.data.package
468
+
469
+ const releaseResponse = await axios.post("/api/package_releases/create", {
470
+ package_id: createdPackage.package_id,
471
+ version: "1.0.0",
472
+ is_latest: true,
473
+ })
474
+ expect(releaseResponse.status).toBe(200)
475
+ const createdRelease = releaseResponse.data.package_release
476
+
477
+ const testCases = [
478
+ { ext: ".ts", path: "/file.ts", expected: "text/typescript" },
479
+ { ext: ".tsx", path: "/file.tsx", expected: "text/typescript" },
480
+ { ext: ".js", path: "/file.js", expected: "application/javascript" },
481
+ { ext: ".json", path: "/file.json", expected: "application/json" },
482
+ { ext: ".md", path: "/file.md", expected: "text/markdown" },
483
+ { ext: ".html", path: "/file.html", expected: "text/html" },
484
+ { ext: ".css", path: "/file.css", expected: "text/css" },
485
+ {
486
+ ext: ".unknown",
487
+ path: "/file.unknown",
488
+ expected: "application/octet-stream",
489
+ },
490
+ ]
491
+
492
+ for (const testCase of testCases) {
493
+ const createResponse = await axios.post(
494
+ "/api/package_files/create_or_update",
495
+ {
496
+ package_release_id: createdRelease.package_release_id,
497
+ file_path: testCase.path,
498
+ content_text: `Test content for ${testCase.ext} file`,
499
+ },
500
+ )
501
+
502
+ expect(createResponse.status).toBe(200)
503
+ expect(createResponse.data.package_file.content_mimetype).toBe(
504
+ testCase.expected,
505
+ )
506
+ }
507
+ })
508
+
509
+ test("create_or_update respects provided content_mimetype", async () => {
510
+ const { axios } = await getTestServer()
511
+
512
+ const packageResponse = await axios.post("/api/packages/create", {
513
+ name: "@test/package-files-custom-mimetype",
514
+ description: "A test package for custom mimetypes",
515
+ })
516
+ expect(packageResponse.status).toBe(200)
517
+ const createdPackage = packageResponse.data.package
518
+
519
+ const releaseResponse = await axios.post("/api/package_releases/create", {
520
+ package_id: createdPackage.package_id,
521
+ version: "1.0.0",
522
+ is_latest: true,
523
+ })
524
+ expect(releaseResponse.status).toBe(200)
525
+ const createdRelease = releaseResponse.data.package_release
526
+
527
+ const customMimetype = "application/custom+json"
528
+ const createResponse = await axios.post(
529
+ "/api/package_files/create_or_update",
530
+ {
531
+ package_release_id: createdRelease.package_release_id,
532
+ file_path: "/data.json",
533
+ content_text: '{"custom":true}',
534
+ content_mimetype: customMimetype,
535
+ },
536
+ )
537
+
538
+ expect(createResponse.status).toBe(200)
539
+ expect(createResponse.data.package_file.content_mimetype).toBe(customMimetype)
540
+ })
541
+
542
+ test("create_or_update - 403 for unauthorized user", async () => {
543
+ const { axios, db } = await getTestServer()
544
+
545
+ const pkg = {
546
+ name: "@test/package-files-create-or-update-unauthorized",
547
+ owner_org_id: "different-org",
548
+ created_at: "2023-01-01T00:00:00Z",
549
+ updated_at: "2023-01-01T00:00:00Z",
550
+ description: "A test package for unauthorized create/update",
551
+ }
552
+ const addedPackage: any = db.addPackage(pkg as any)
553
+
554
+ const releaseResponse = await axios.post("/api/package_releases/create", {
555
+ package_id: addedPackage.package_id,
556
+ version: "1.0.0",
557
+ })
558
+ expect(releaseResponse.status).toBe(200)
559
+ const createdRelease = releaseResponse.data.package_release
560
+
561
+ try {
562
+ await axios.post("/api/package_files/create_or_update", {
563
+ package_release_id: createdRelease.package_release_id,
564
+ file_path: "/test.js",
565
+ content_text: "console.log('test');",
566
+ })
567
+ throw new Error("Expected request to fail")
568
+ } catch (error: any) {
569
+ expect(error.status).toBe(403)
570
+ expect(error.data.error.error_code).toBe("forbidden")
571
+ expect(error.data.error.message).toBe(
572
+ "You don't have permission to modify files in this package",
573
+ )
574
+ }
575
+ })