@lullabot/playwright-testing 1.0.0 → 1.1.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.
Files changed (68) hide show
  1. package/bin/github-a11y-summary +2 -2
  2. package/bin/github-failure-summary +4 -4
  3. package/lib/accessibility-baseline-file.d.ts +6 -6
  4. package/lib/accessibility-baseline-file.js +29 -23
  5. package/lib/accessibility-baseline.js +5 -3
  6. package/lib/accessible-screenshot.d.ts +4 -4
  7. package/lib/accessible-screenshot.js +110 -88
  8. package/lib/focus.js +4 -1
  9. package/lib/frames.js +4 -4
  10. package/lib/github/a11y-summary.js +74 -79
  11. package/lib/github/attachments.d.ts +1 -1
  12. package/lib/github/attachments.js +36 -34
  13. package/lib/github/failure-summary.d.ts +4 -4
  14. package/lib/github/failure-summary.js +140 -108
  15. package/lib/github/index.d.ts +6 -6
  16. package/lib/github/report-paths.js +17 -9
  17. package/lib/hover.js +17 -17
  18. package/lib/images.js +15 -12
  19. package/lib/index.d.ts +13 -13
  20. package/lib/interaction-states.d.ts +2 -2
  21. package/lib/interaction-states.js +7 -7
  22. package/lib/mock/index.d.ts +1 -1
  23. package/lib/mock/youtube.d.ts +1 -1
  24. package/lib/mock/youtube.js +1 -1
  25. package/lib/pseudo-state.d.ts +2 -2
  26. package/lib/pseudo-state.js +15 -7
  27. package/lib/videos.js +21 -10
  28. package/lib/visualdiff.d.ts +4 -4
  29. package/lib/visualdiff.js +35 -27
  30. package/package.json +3 -3
  31. package/src/accessibility-baseline-file.test.ts +190 -154
  32. package/src/accessibility-baseline-file.ts +107 -83
  33. package/src/accessibility-baseline.test.ts +869 -433
  34. package/src/accessibility-baseline.ts +41 -21
  35. package/src/accessible-screenshot.test.ts +551 -423
  36. package/src/accessible-screenshot.ts +358 -251
  37. package/src/focus.test.ts +23 -23
  38. package/src/focus.ts +7 -2
  39. package/src/fonts.test.ts +13 -13
  40. package/src/fonts.ts +1 -1
  41. package/src/frames.test.ts +10 -8
  42. package/src/frames.ts +5 -5
  43. package/src/github/a11y-summary.test.ts +436 -332
  44. package/src/github/a11y-summary.ts +189 -179
  45. package/src/github/attachments.test.ts +228 -167
  46. package/src/github/attachments.ts +144 -121
  47. package/src/github/failure-summary.test.ts +660 -445
  48. package/src/github/failure-summary.ts +376 -274
  49. package/src/github/index.test.ts +14 -14
  50. package/src/github/index.ts +6 -6
  51. package/src/github/report-paths.test.ts +211 -156
  52. package/src/github/report-paths.ts +75 -61
  53. package/src/hover.test.ts +50 -46
  54. package/src/hover.ts +18 -18
  55. package/src/images.test.ts +251 -206
  56. package/src/images.ts +52 -43
  57. package/src/index.ts +13 -13
  58. package/src/interaction-states.test.ts +72 -42
  59. package/src/interaction-states.ts +43 -29
  60. package/src/mock/index.ts +1 -1
  61. package/src/mock/youtube.test.ts +26 -26
  62. package/src/mock/youtube.ts +4 -6
  63. package/src/pseudo-state.test.ts +58 -51
  64. package/src/pseudo-state.ts +32 -27
  65. package/src/videos.test.ts +559 -399
  66. package/src/videos.ts +68 -44
  67. package/src/visualdiff.test.ts +416 -315
  68. package/src/visualdiff.ts +140 -99
@@ -1,248 +1,309 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest'
2
- import * as fs from 'fs'
3
- import * as os from 'os'
4
- import * as path from 'path'
5
- import { AttachmentUploader, mimeTypeFor, FetchLike } from './attachments'
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import * as fs from "fs";
3
+ import * as os from "os";
4
+ import * as path from "path";
5
+ import { AttachmentUploader, mimeTypeFor, FetchLike } from "./attachments";
6
6
 
7
- let tmpDir: string
7
+ let tmpDir: string;
8
8
 
9
9
  beforeEach(() => {
10
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'attachments-test-'))
11
- })
10
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "attachments-test-"));
11
+ });
12
12
 
13
13
  afterEach(() => {
14
- fs.rmSync(tmpDir, { recursive: true, force: true })
15
- })
14
+ fs.rmSync(tmpDir, { recursive: true, force: true });
15
+ });
16
16
 
17
17
  /** Write a file of a given size and return its path. */
18
18
  function writeFile(name: string, bytes = 16): string {
19
- const filePath = path.join(tmpDir, name)
20
- fs.writeFileSync(filePath, Buffer.alloc(bytes, 1))
21
- return filePath
19
+ const filePath = path.join(tmpDir, name);
20
+ fs.writeFileSync(filePath, Buffer.alloc(bytes, 1));
21
+ return filePath;
22
22
  }
23
23
 
24
24
  /** A fetch stub that records calls and replays canned responses. */
25
- function stubFetch(responses: Array<{ ok: boolean; status: number; body: string }>) {
26
- const calls: string[] = []
27
- const headers: Array<Record<string, string>> = []
25
+ function stubFetch(
26
+ responses: Array<{ ok: boolean; status: number; body: string }>,
27
+ ) {
28
+ const calls: string[] = [];
29
+ const headers: Array<Record<string, string>> = [];
28
30
  const impl: FetchLike = async (url, init) => {
29
- calls.push(url)
30
- headers.push(init.headers)
31
- const next = responses.shift() ?? { ok: true, status: 201, body: '{"url":"https://example.test/a"}' }
31
+ calls.push(url);
32
+ headers.push(init.headers);
33
+ const next = responses.shift() ?? {
34
+ ok: true,
35
+ status: 201,
36
+ body: '{"url":"https://example.test/a"}',
37
+ };
32
38
  return {
33
39
  ok: next.ok,
34
40
  status: next.status,
35
41
  text: async () => next.body,
36
- }
37
- }
38
- return { impl, calls, headers }
42
+ };
43
+ };
44
+ return { impl, calls, headers };
39
45
  }
40
46
 
41
- describe('mimeTypeFor', () => {
42
- it('maps the image types GitHub renders inline', () => {
43
- expect(mimeTypeFor('a/b/diff.png')).toBe('image/png')
44
- expect(mimeTypeFor('shot.JPEG')).toBe('image/jpeg')
45
- expect(mimeTypeFor('clip.webm')).toBe('video/webm')
46
- expect(mimeTypeFor('icon.svg')).toBe('image/svg+xml')
47
- expect(mimeTypeFor('clip.MOV')).toBe('video/quicktime')
48
- })
49
-
50
- it('falls back to a generic type for anything else', () => {
51
- expect(mimeTypeFor('report.txt')).toBe('application/octet-stream')
52
- })
53
- })
54
-
55
- describe('AttachmentUploader', () => {
56
- it('is off without a token, which is the normal case', async () => {
57
- const uploader = new AttachmentUploader({ repositoryId: '1' })
58
- expect(uploader.enabled).toBe(false)
59
- expect(uploader.disabledReason).toMatch(/no upload token/)
60
- expect(await uploader.upload(writeFile('a.png'))).toBeNull()
61
- })
62
-
63
- it('is off without a repository ID', () => {
64
- const uploader = new AttachmentUploader({ token: 't' })
65
- expect(uploader.enabled).toBe(false)
66
- expect(uploader.disabledReason).toMatch(/repository ID/)
67
- })
68
-
69
- it('returns the asset URL and passes the endpoint what it needs', async () => {
47
+ describe("mimeTypeFor", () => {
48
+ it("maps the image types GitHub renders inline", () => {
49
+ expect(mimeTypeFor("a/b/diff.png")).toBe("image/png");
50
+ expect(mimeTypeFor("shot.JPEG")).toBe("image/jpeg");
51
+ expect(mimeTypeFor("clip.webm")).toBe("video/webm");
52
+ expect(mimeTypeFor("icon.svg")).toBe("image/svg+xml");
53
+ expect(mimeTypeFor("clip.MOV")).toBe("video/quicktime");
54
+ });
55
+
56
+ it("falls back to a generic type for anything else", () => {
57
+ expect(mimeTypeFor("report.txt")).toBe("application/octet-stream");
58
+ });
59
+ });
60
+
61
+ describe("AttachmentUploader", () => {
62
+ it("is off without a token, which is the normal case", async () => {
63
+ const uploader = new AttachmentUploader({ repositoryId: "1" });
64
+ expect(uploader.enabled).toBe(false);
65
+ expect(uploader.disabledReason).toMatch(/no upload token/);
66
+ expect(await uploader.upload(writeFile("a.png"))).toBeNull();
67
+ });
68
+
69
+ it("is off without a repository ID", () => {
70
+ const uploader = new AttachmentUploader({ token: "t" });
71
+ expect(uploader.enabled).toBe(false);
72
+ expect(uploader.disabledReason).toMatch(/repository ID/);
73
+ });
74
+
75
+ it("returns the asset URL and passes the endpoint what it needs", async () => {
70
76
  const { impl, calls } = stubFetch([
71
- { ok: true, status: 201, body: '{"url":"https://github.com/user-attachments/assets/abc"}' },
72
- ])
73
- const uploader = new AttachmentUploader({ token: 't', repositoryId: '42', fetchImpl: impl })
77
+ {
78
+ ok: true,
79
+ status: 201,
80
+ body: '{"url":"https://github.com/user-attachments/assets/abc"}',
81
+ },
82
+ ]);
83
+ const uploader = new AttachmentUploader({
84
+ token: "t",
85
+ repositoryId: "42",
86
+ fetchImpl: impl,
87
+ });
74
88
 
75
- const url = await uploader.upload(writeFile('diff.png'))
89
+ const url = await uploader.upload(writeFile("diff.png"));
76
90
 
77
- expect(url).toBe('https://github.com/user-attachments/assets/abc')
78
- expect(calls[0]).toContain('repository_id=42')
79
- expect(calls[0]).toContain('content_type=image%2Fpng')
80
- expect(calls[0]).toContain('name=diff.png')
81
- expect(uploader.getStats().uploaded).toBe(1)
82
- })
91
+ expect(url).toBe("https://github.com/user-attachments/assets/abc");
92
+ expect(calls[0]).toContain("repository_id=42");
93
+ expect(calls[0]).toContain("content_type=image%2Fpng");
94
+ expect(calls[0]).toContain("name=diff.png");
95
+ expect(uploader.getStats().uploaded).toBe(1);
96
+ });
83
97
 
84
- it('sends a Content-Type, which the endpoint rejects the request without', async () => {
98
+ it("sends a Content-Type, which the endpoint rejects the request without", async () => {
85
99
  // Node's fetch sends no Content-Type for a Buffer body, and the endpoint
86
100
  // answers 400 "Invalid Content-Type" when it is missing.
87
- const { impl, headers } = stubFetch([])
88
- const uploader = new AttachmentUploader({ token: 't', repositoryId: '1', fetchImpl: impl })
101
+ const { impl, headers } = stubFetch([]);
102
+ const uploader = new AttachmentUploader({
103
+ token: "t",
104
+ repositoryId: "1",
105
+ fetchImpl: impl,
106
+ });
89
107
 
90
- await uploader.upload(writeFile('diff.png'))
108
+ await uploader.upload(writeFile("diff.png"));
91
109
 
92
- expect(headers[0]['Content-Type']).toBe('image/png')
93
- })
110
+ expect(headers[0]["Content-Type"]).toBe("image/png");
111
+ });
94
112
 
95
- it('reports the response body when the endpoint refuses', async () => {
113
+ it("reports the response body when the endpoint refuses", async () => {
96
114
  const { impl } = stubFetch([
97
115
  { ok: false, status: 400, body: '{"message":"Invalid Content-Type"}' },
98
- ])
99
- const uploader = new AttachmentUploader({ token: 't', repositoryId: '1', fetchImpl: impl })
116
+ ]);
117
+ const uploader = new AttachmentUploader({
118
+ token: "t",
119
+ repositoryId: "1",
120
+ fetchImpl: impl,
121
+ });
100
122
 
101
- await uploader.upload(writeFile('a.png'))
123
+ await uploader.upload(writeFile("a.png"));
102
124
 
103
- expect(uploader.disabledReason).toContain('Invalid Content-Type')
104
- })
125
+ expect(uploader.disabledReason).toContain("Invalid Content-Type");
126
+ });
105
127
 
106
- it('accepts href as well as url, since write-ups disagree', async () => {
107
- const { impl } = stubFetch([{ ok: true, status: 201, body: '{"href":"https://example.test/h"}' }])
108
- const uploader = new AttachmentUploader({ token: 't', repositoryId: '1', fetchImpl: impl })
128
+ it("accepts href as well as url, since write-ups disagree", async () => {
129
+ const { impl } = stubFetch([
130
+ { ok: true, status: 201, body: '{"href":"https://example.test/h"}' },
131
+ ]);
132
+ const uploader = new AttachmentUploader({
133
+ token: "t",
134
+ repositoryId: "1",
135
+ fetchImpl: impl,
136
+ });
109
137
 
110
- expect(await uploader.upload(writeFile('a.png'))).toBe('https://example.test/h')
111
- })
138
+ expect(await uploader.upload(writeFile("a.png"))).toBe(
139
+ "https://example.test/h",
140
+ );
141
+ });
112
142
 
113
- it('stops for the rest of the run after one failure', async () => {
114
- const { impl, calls } = stubFetch([{ ok: false, status: 404, body: '{"message":"Not Found"}' }])
115
- const uploader = new AttachmentUploader({ token: 't', repositoryId: '1', fetchImpl: impl })
143
+ it("stops for the rest of the run after one failure", async () => {
144
+ const { impl, calls } = stubFetch([
145
+ { ok: false, status: 404, body: '{"message":"Not Found"}' },
146
+ ]);
147
+ const uploader = new AttachmentUploader({
148
+ token: "t",
149
+ repositoryId: "1",
150
+ fetchImpl: impl,
151
+ });
116
152
 
117
- expect(await uploader.upload(writeFile('one.png'))).toBeNull()
118
- expect(uploader.enabled).toBe(false)
119
- expect(uploader.disabledReason).toMatch(/HTTP 404/)
153
+ expect(await uploader.upload(writeFile("one.png"))).toBeNull();
154
+ expect(uploader.enabled).toBe(false);
155
+ expect(uploader.disabledReason).toMatch(/HTTP 404/);
120
156
 
121
157
  // The second attempt must not reach the endpoint at all.
122
- expect(await uploader.upload(writeFile('two.png'))).toBeNull()
123
- expect(calls).toHaveLength(1)
124
- })
158
+ expect(await uploader.upload(writeFile("two.png"))).toBeNull();
159
+ expect(calls).toHaveLength(1);
160
+ });
125
161
 
126
- it('stops when the endpoint answers without a URL', async () => {
127
- const { impl } = stubFetch([{ ok: true, status: 200, body: 'not json' }])
128
- const uploader = new AttachmentUploader({ token: 't', repositoryId: '1', fetchImpl: impl })
162
+ it("stops when the endpoint answers without a URL", async () => {
163
+ const { impl } = stubFetch([{ ok: true, status: 200, body: "not json" }]);
164
+ const uploader = new AttachmentUploader({
165
+ token: "t",
166
+ repositoryId: "1",
167
+ fetchImpl: impl,
168
+ });
129
169
 
130
- expect(await uploader.upload(writeFile('a.png'))).toBeNull()
131
- expect(uploader.disabledReason).toMatch(/no URL/)
132
- })
170
+ expect(await uploader.upload(writeFile("a.png"))).toBeNull();
171
+ expect(uploader.disabledReason).toMatch(/no URL/);
172
+ });
133
173
 
134
- it('stops rather than throwing when fetch rejects', async () => {
174
+ it("stops rather than throwing when fetch rejects", async () => {
135
175
  const impl: FetchLike = async () => {
136
- throw new Error('socket hang up')
137
- }
138
- const uploader = new AttachmentUploader({ token: 't', repositoryId: '1', fetchImpl: impl })
176
+ throw new Error("socket hang up");
177
+ };
178
+ const uploader = new AttachmentUploader({
179
+ token: "t",
180
+ repositoryId: "1",
181
+ fetchImpl: impl,
182
+ });
139
183
 
140
- expect(await uploader.upload(writeFile('a.png'))).toBeNull()
141
- expect(uploader.disabledReason).toMatch(/socket hang up/)
142
- })
184
+ expect(await uploader.upload(writeFile("a.png"))).toBeNull();
185
+ expect(uploader.disabledReason).toMatch(/socket hang up/);
186
+ });
143
187
 
144
- it('enforces the upload count budget and says so', async () => {
145
- const { impl } = stubFetch([])
188
+ it("enforces the upload count budget and says so", async () => {
189
+ const { impl } = stubFetch([]);
146
190
  const uploader = new AttachmentUploader({
147
- token: 't',
148
- repositoryId: '1',
191
+ token: "t",
192
+ repositoryId: "1",
149
193
  maxUploads: 1,
150
194
  fetchImpl: impl,
151
- })
195
+ });
152
196
 
153
- expect(await uploader.upload(writeFile('one.png'))).not.toBeNull()
154
- expect(await uploader.upload(writeFile('two.png'))).toBeNull()
155
- expect(uploader.disabledReason).toMatch(/upload limit of 1/)
156
- })
197
+ expect(await uploader.upload(writeFile("one.png"))).not.toBeNull();
198
+ expect(await uploader.upload(writeFile("two.png"))).toBeNull();
199
+ expect(uploader.disabledReason).toMatch(/upload limit of 1/);
200
+ });
157
201
 
158
- it('skips a file over GitHub\'s size limit and keeps going', async () => {
202
+ it("skips a file over GitHub's size limit and keeps going", async () => {
159
203
  // GitHub refuses an image over 10 MB, and a rejection would otherwise
160
204
  // switch uploading off for every image behind it.
161
- const { impl, calls } = stubFetch([])
205
+ const { impl, calls } = stubFetch([]);
162
206
  const uploader = new AttachmentUploader({
163
- token: 't',
164
- repositoryId: '1',
207
+ token: "t",
208
+ repositoryId: "1",
165
209
  maxFileBytes: 100,
166
210
  fetchImpl: impl,
167
- })
211
+ });
168
212
 
169
- expect(await uploader.upload(writeFile('huge.png', 200))).toBeNull()
170
- expect(uploader.enabled).toBe(true)
171
- expect(uploader.lastSkipReason).toBe('too-large')
213
+ expect(await uploader.upload(writeFile("huge.png", 200))).toBeNull();
214
+ expect(uploader.enabled).toBe(true);
215
+ expect(uploader.lastSkipReason).toBe("too-large");
172
216
  // Nothing was sent for it: the limit is checked before the request.
173
- expect(calls).toHaveLength(0)
217
+ expect(calls).toHaveLength(0);
174
218
 
175
- expect(await uploader.upload(writeFile('small.png', 10))).not.toBeNull()
176
- expect(uploader.lastSkipReason).toBeNull()
177
- expect(uploader.getStats()).toEqual({ uploaded: 1, skipped: 1, bytes: 10 })
178
- })
219
+ expect(await uploader.upload(writeFile("small.png", 10))).not.toBeNull();
220
+ expect(uploader.lastSkipReason).toBeNull();
221
+ expect(uploader.getStats()).toEqual({ uploaded: 1, skipped: 1, bytes: 10 });
222
+ });
179
223
 
180
- it('skips a file that does not fit the byte budget, rather than stopping', async () => {
181
- const { impl } = stubFetch([])
224
+ it("skips a file that does not fit the byte budget, rather than stopping", async () => {
225
+ const { impl } = stubFetch([]);
182
226
  const uploader = new AttachmentUploader({
183
- token: 't',
184
- repositoryId: '1',
227
+ token: "t",
228
+ repositoryId: "1",
185
229
  maxTotalBytes: 100,
186
230
  fetchImpl: impl,
187
- })
231
+ });
188
232
 
189
- expect(await uploader.upload(writeFile('first.png', 60))).not.toBeNull()
190
- expect(await uploader.upload(writeFile('big.png', 60))).toBeNull()
191
- expect(uploader.lastSkipReason).toBe('budget')
233
+ expect(await uploader.upload(writeFile("first.png", 60))).not.toBeNull();
234
+ expect(await uploader.upload(writeFile("big.png", 60))).toBeNull();
235
+ expect(uploader.lastSkipReason).toBe("budget");
192
236
 
193
237
  // The budget is a ceiling on the total, not a stop: what still fits goes.
194
- expect(await uploader.upload(writeFile('last.png', 30))).not.toBeNull()
195
- expect(uploader.enabled).toBe(true)
196
- expect(uploader.getStats().bytes).toBe(90)
197
- })
238
+ expect(await uploader.upload(writeFile("last.png", 30))).not.toBeNull();
239
+ expect(uploader.enabled).toBe(true);
240
+ expect(uploader.getStats().bytes).toBe(90);
241
+ });
198
242
 
199
- it('tells an unreadable file apart from one the limits refused', async () => {
200
- const { impl } = stubFetch([{ ok: false, status: 404, body: '{"message":"Not Found"}' }])
243
+ it("tells an unreadable file apart from one the limits refused", async () => {
244
+ const { impl } = stubFetch([
245
+ { ok: false, status: 404, body: '{"message":"Not Found"}' },
246
+ ]);
201
247
  const uploader = new AttachmentUploader({
202
- token: 't',
203
- repositoryId: '1',
248
+ token: "t",
249
+ repositoryId: "1",
204
250
  maxFileBytes: 100,
205
251
  fetchImpl: impl,
206
- })
252
+ });
207
253
 
208
- await uploader.upload(path.join(tmpDir, 'missing.png'))
209
- expect(uploader.lastSkipReason).toBe('unreadable')
254
+ await uploader.upload(path.join(tmpDir, "missing.png"));
255
+ expect(uploader.lastSkipReason).toBe("unreadable");
210
256
 
211
- await uploader.upload(writeFile('huge.png', 200))
212
- expect(uploader.lastSkipReason).toBe('too-large')
257
+ await uploader.upload(writeFile("huge.png", 200));
258
+ expect(uploader.lastSkipReason).toBe("too-large");
213
259
 
214
260
  // A dead endpoint is the run's problem rather than any one file's.
215
- await uploader.upload(writeFile('fine.png', 10))
216
- expect(uploader.lastSkipReason).toBe('disabled')
217
- expect(uploader.enabled).toBe(false)
218
- })
261
+ await uploader.upload(writeFile("fine.png", 10));
262
+ expect(uploader.lastSkipReason).toBe("disabled");
263
+ expect(uploader.enabled).toBe(false);
264
+ });
219
265
 
220
- it('skips an unreadable file without giving up on the rest', async () => {
221
- const { impl } = stubFetch([])
222
- const uploader = new AttachmentUploader({ token: 't', repositoryId: '1', fetchImpl: impl })
266
+ it("skips an unreadable file without giving up on the rest", async () => {
267
+ const { impl } = stubFetch([]);
268
+ const uploader = new AttachmentUploader({
269
+ token: "t",
270
+ repositoryId: "1",
271
+ fetchImpl: impl,
272
+ });
223
273
 
224
- expect(await uploader.upload(path.join(tmpDir, 'missing.png'))).toBeNull()
225
- expect(uploader.enabled).toBe(true)
226
- expect(await uploader.upload(writeFile('present.png'))).not.toBeNull()
227
- })
274
+ expect(await uploader.upload(path.join(tmpDir, "missing.png"))).toBeNull();
275
+ expect(uploader.enabled).toBe(true);
276
+ expect(await uploader.upload(writeFile("present.png"))).not.toBeNull();
277
+ });
228
278
 
229
- it('reduces a name of nothing but dashes to a usable one', async () => {
279
+ it("reduces a name of nothing but dashes to a usable one", async () => {
230
280
  // Trimming these with /^-+|-+$/ backtracks quadratically, so the trim is an
231
281
  // index scan instead. Long runs of dashes are the shape that provokes it.
232
- const { impl, calls } = stubFetch([])
233
- const uploader = new AttachmentUploader({ token: 't', repositoryId: '1', fetchImpl: impl })
282
+ const { impl, calls } = stubFetch([]);
283
+ const uploader = new AttachmentUploader({
284
+ token: "t",
285
+ repositoryId: "1",
286
+ fetchImpl: impl,
287
+ });
234
288
 
235
- await uploader.upload(writeFile('a.png'), `${'-'.repeat(50000)}b.png`)
289
+ await uploader.upload(writeFile("a.png"), `${"-".repeat(50000)}b.png`);
236
290
 
237
- expect(calls[0]).toContain('name=attachment')
238
- })
291
+ expect(calls[0]).toContain("name=attachment");
292
+ });
239
293
 
240
- it('reduces awkward file names to something a query string can carry', async () => {
241
- const { impl, calls } = stubFetch([])
242
- const uploader = new AttachmentUploader({ token: 't', repositoryId: '1', fetchImpl: impl })
294
+ it("reduces awkward file names to something a query string can carry", async () => {
295
+ const { impl, calls } = stubFetch([]);
296
+ const uploader = new AttachmentUploader({
297
+ token: "t",
298
+ repositoryId: "1",
299
+ fetchImpl: impl,
300
+ });
243
301
 
244
- await uploader.upload(writeFile('weird.png'), 'homepage renders "correctly" & fast.png')
302
+ await uploader.upload(
303
+ writeFile("weird.png"),
304
+ 'homepage renders "correctly" & fast.png',
305
+ );
245
306
 
246
- expect(calls[0]).toContain('name=homepage-renders-correctly-fast.png')
247
- })
248
- })
307
+ expect(calls[0]).toContain("name=homepage-renders-correctly-fast.png");
308
+ });
309
+ });