q5 2.9.22 → 2.9.23

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 (69) hide show
  1. package/.vscode/launch.json +26 -0
  2. package/bun.lockb +0 -0
  3. package/p5-tests/js/chai_helpers.js +20 -0
  4. package/p5-tests/js/mocha_setup.js +2 -0
  5. package/p5-tests/js/modernizr.js +5 -0
  6. package/p5-tests/js/p5_helpers.js +135 -0
  7. package/p5-tests/js/sinon.js +5949 -0
  8. package/p5-tests/mocha.css +289 -0
  9. package/p5-tests/test.html +71 -0
  10. package/p5-tests/unit/color/color_conversion.js +68 -0
  11. package/p5-tests/unit/color/creating_reading.js +217 -0
  12. package/p5-tests/unit/color/p5.Color.js +1000 -0
  13. package/p5-tests/unit/color/setting.js +289 -0
  14. package/p5-tests/unit/core/2d_primitives.js +490 -0
  15. package/p5-tests/unit/core/attributes.js +115 -0
  16. package/p5-tests/unit/core/curves.js +139 -0
  17. package/p5-tests/unit/core/environment.js +248 -0
  18. package/p5-tests/unit/core/error_helpers.js +1158 -0
  19. package/p5-tests/unit/core/main.js +340 -0
  20. package/p5-tests/unit/core/p5.Element.js +773 -0
  21. package/p5-tests/unit/core/p5.Graphics.js +179 -0
  22. package/p5-tests/unit/core/preload.js +285 -0
  23. package/p5-tests/unit/core/rendering.js +116 -0
  24. package/p5-tests/unit/core/structure.js +293 -0
  25. package/p5-tests/unit/core/transform.js +144 -0
  26. package/p5-tests/unit/core/version.js +28 -0
  27. package/p5-tests/unit/core/vertex.js +137 -0
  28. package/p5-tests/unit/dom/dom.js +2146 -0
  29. package/p5-tests/unit/events/acceleration.js +213 -0
  30. package/p5-tests/unit/events/keyboard.js +179 -0
  31. package/p5-tests/unit/events/mouse.js +487 -0
  32. package/p5-tests/unit/events/touch.js +180 -0
  33. package/p5-tests/unit/image/downloading.js +379 -0
  34. package/p5-tests/unit/image/filters.js +92 -0
  35. package/p5-tests/unit/image/loading.js +413 -0
  36. package/p5-tests/unit/image/p5.Image.js +201 -0
  37. package/p5-tests/unit/image/pixels.js +234 -0
  38. package/p5-tests/unit/io/files.js +378 -0
  39. package/p5-tests/unit/io/loadBytes.js +149 -0
  40. package/p5-tests/unit/io/loadImage.js +123 -0
  41. package/p5-tests/unit/io/loadJSON.js +185 -0
  42. package/p5-tests/unit/io/loadModel.js +215 -0
  43. package/p5-tests/unit/io/loadShader.js +176 -0
  44. package/p5-tests/unit/io/loadStrings.js +140 -0
  45. package/p5-tests/unit/io/loadTable.js +183 -0
  46. package/p5-tests/unit/io/loadXML.js +127 -0
  47. package/p5-tests/unit/io/saveModel.js +113 -0
  48. package/p5-tests/unit/io/saveTable.js +142 -0
  49. package/p5-tests/unit/math/calculation.js +452 -0
  50. package/p5-tests/unit/math/noise.js +66 -0
  51. package/p5-tests/unit/math/p5.Vector.js +1886 -0
  52. package/p5-tests/unit/math/random.js +177 -0
  53. package/p5-tests/unit/math/trigonometry.js +144 -0
  54. package/p5-tests/unit/spec.js +50 -0
  55. package/p5-tests/unit/typography/attributes.js +120 -0
  56. package/p5-tests/unit/typography/loadFont.js +162 -0
  57. package/p5-tests/unit/typography/p5.Font.js +63 -0
  58. package/p5-tests/unit/utilities/conversion.js +329 -0
  59. package/p5-tests/unit/utilities/time_date.js +133 -0
  60. package/package.json +1 -1
  61. package/q5.js +48 -37
  62. package/q5.min.js +1 -1
  63. package/src/q5-2d-image.js +3 -1
  64. package/src/q5-core.js +3 -1
  65. package/src/q5-math.js +1 -0
  66. package/src/q5-webgpu-canvas.js +8 -7
  67. package/src/q5-webgpu-drawing.js +15 -12
  68. package/src/q5-webgpu-image.js +1 -1
  69. package/src/q5-webgpu-text.js +17 -15
@@ -0,0 +1,234 @@
1
+ suite('pixels', function() {
2
+ var myp5;
3
+
4
+ setup(function(done) {
5
+ new p5(function(p) {
6
+ p.setup = function() {
7
+ myp5 = p;
8
+ done();
9
+ };
10
+ });
11
+ });
12
+
13
+ teardown(function() {
14
+ myp5.remove();
15
+ });
16
+
17
+ suite('p5.Image.get', function() {
18
+ var img;
19
+
20
+ setup(function() {
21
+ //create a 50 x 50 half red half green image
22
+ img = myp5.createImage(50, 50);
23
+ img.loadPixels();
24
+
25
+ for (var i = 0; i < img.width; i++) {
26
+ for (var j = 0; j < img.height; j++) {
27
+ var col;
28
+
29
+ if (j <= 25) {
30
+ col = myp5.color(255, 0, 0);
31
+ } else {
32
+ col = myp5.color(0, 0, 255);
33
+ }
34
+
35
+ img.set(i, j, col);
36
+ }
37
+ }
38
+
39
+ img.updatePixels();
40
+ });
41
+
42
+ test('get(x,y) works with integers', function() {
43
+ assert.deepEqual(img.get(25, 25), [255, 0, 0, 255]);
44
+ assert.deepEqual(img.get(25, 26), [0, 0, 255, 255]);
45
+ assert.deepEqual(img.get(0, 0), [255, 0, 0, 255]);
46
+ assert.deepEqual(img.get(49, 49), [0, 0, 255, 255]);
47
+ });
48
+
49
+ test('get(x,y) returns 0s for out of bounds arguments', function() {
50
+ assert.deepEqual(img.get(25, -1), [0, 0, 0, 0]);
51
+ assert.deepEqual(img.get(-1, 26), [0, 0, 0, 0]);
52
+ assert.deepEqual(img.get(25, 50), [0, 0, 0, 0]);
53
+ assert.deepEqual(img.get(50, 26), [0, 0, 0, 0]);
54
+ });
55
+
56
+ test('get() returns a copy when no arguments are supplied', function() {
57
+ var copy = img.get();
58
+ assert.instanceOf(copy, p5.Image);
59
+ assert.equal(copy.width, img.width);
60
+ assert.equal(copy.height, img.height);
61
+
62
+ assert.deepEqual(copy.get(25, 25), [255, 0, 0, 255]);
63
+ assert.deepEqual(copy.get(25, 26), [0, 0, 255, 255]);
64
+ assert.deepEqual(copy.get(0, 0), [255, 0, 0, 255]);
65
+ assert.deepEqual(copy.get(49, 49), [0, 0, 255, 255]);
66
+ });
67
+
68
+ test('get(x,y,w,h) works', function() {
69
+ for (var w = 1; w < img.width + 5; w += 2) {
70
+ for (var x = -w * 2; x <= img.width + w * 2; x += 4) {
71
+ var copy = img.get(x, x, w, w);
72
+ assert.instanceOf(copy, p5.Image);
73
+ assert.equal(copy.width, w);
74
+ assert.equal(copy.height, w);
75
+ assert.deepEqual(copy.get(0, 0), img.get(x, x));
76
+ }
77
+ }
78
+ });
79
+
80
+ test('rounds down when given decimal numbers', function() {
81
+ assert.deepEqual(img.get(25, 25.999), img.get(25, 25));
82
+ });
83
+ });
84
+
85
+ suite('p5.Image.pixels', function() {
86
+ test('should be an array of pixels', function() {
87
+ let img = myp5.createImage(10, 10);
88
+ img.loadPixels();
89
+ assert.typeOf(img.pixels, 'Uint8ClampedArray');
90
+ });
91
+
92
+ test('should store r, g, b, a values for each pixel', function() {
93
+ let img = myp5.createImage(10, 10);
94
+ myp5.pixelDensity(1);
95
+ img.loadPixels();
96
+ assert.strictEqual(img.pixels.length, 400);
97
+ });
98
+
99
+ test('should store correct r, g, b, a values for each pixel', function() {
100
+ let img = myp5.createImage(10, 10);
101
+ myp5.pixelDensity(1);
102
+ img.loadPixels();
103
+ img.pixels[0] = 255;
104
+ img.pixels[1] = 102;
105
+ img.pixels[2] = 204;
106
+ img.pixels[3] = 255;
107
+ img.updatePixels();
108
+
109
+ assert.strictEqual(img.pixels[0], 255);
110
+ assert.strictEqual(img.pixels[1], 102);
111
+ assert.strictEqual(img.pixels[2], 204);
112
+ assert.strictEqual(img.pixels[3], 255);
113
+ });
114
+ });
115
+
116
+ suite('p5.Image.set', function() {
117
+ /* Parameter Validation missing */
118
+ test('set(x,y) changes color of pixel (x, y)', function() {
119
+ let img = myp5.createImage(50, 50);
120
+ img.loadPixels();
121
+ img.set(0, 0, myp5.color(255, 34, 19));
122
+ img.updatePixels();
123
+ assert.deepEqual(img.get(0, 0), [255, 34, 19, 255]);
124
+ });
125
+ });
126
+
127
+ suite('p5.Image.blend', function() {
128
+ test('should copy a region of pixels using the specified blend mode', function() {
129
+ let img = myp5.createImage(50, 50);
130
+ let img2 = myp5.createImage(50, 50);
131
+ img.loadPixels();
132
+ for (let i = 0; i < img.width; i++) {
133
+ for (let j = 0; j < img.height; j++) {
134
+ img.set(i, j, myp5.color(255, 0, 0)); // red
135
+ }
136
+ }
137
+ img.updatePixels();
138
+ img2.loadPixels();
139
+ for (let i = 0; i < img2.width; i++) {
140
+ for (let j = 0; j < img2.height; j++) {
141
+ img2.set(i, j, myp5.color(255, 255, 0)); // yellow
142
+ }
143
+ }
144
+ img2.updatePixels();
145
+ img.blend(img2, 0, 0, 10, 10, 0, 0, 10, 10, myp5.NORMAL); // blend yellow on red in normal mode
146
+ myp5.image(img, 0, 0);
147
+
148
+ for (let i = 0; i < 10; i++) {
149
+ for (let j = 0; j < 10; j++) {
150
+ assert.deepEqual(img.get(i, j), [255, 255, 0, 255]); // should be yellow
151
+ }
152
+ }
153
+ });
154
+
155
+ test('wrong parameter at #8', function() {
156
+ assert.validationError(function() {
157
+ let img = myp5.createImage(50, 50);
158
+ img.blend(0, 0, 10, 10, 10, 0, 10, 10, 'a');
159
+ });
160
+ });
161
+
162
+ test('no friendly-err-msg. missing param #0', function() {
163
+ assert.doesNotThrow(
164
+ function() {
165
+ let img = myp5.createImage(50, 50);
166
+ img.blend(0, 0, 10, 10, 10, 0, 10, 10, myp5.OVERLAY);
167
+ },
168
+ Error,
169
+ 'got unwanted exception'
170
+ );
171
+ });
172
+
173
+ test('missing parameter at #3 ', function() {
174
+ assert.throw(function() {
175
+ let img = myp5.createImage(50, 50);
176
+ img.blend(0, 0, 10, 10, 0, 10, 10, myp5.OVERLAY);
177
+ });
178
+ });
179
+
180
+ test('missing parameter at #8 ', function() {
181
+ assert.throw(function() {
182
+ let img = myp5.createImage(50, 50);
183
+ img.blend(0, 0, 10, 10, 10, 0, 10, 10);
184
+ });
185
+ });
186
+ });
187
+
188
+ suite('p5.Image.copy', function() {
189
+ test('should copy a region of pixels', function() {
190
+ let img = myp5.createImage(50, 50);
191
+ let img2 = myp5.createImage(50, 50);
192
+ img.loadPixels();
193
+ for (let i = 0; i < img.width; i++) {
194
+ for (let j = 0; j < img.height; j++) {
195
+ img.set(i, j, myp5.color(255, 0, 0)); // red
196
+ }
197
+ }
198
+ img.updatePixels();
199
+ img2.loadPixels();
200
+ for (let i = 0; i < img2.width; i++) {
201
+ for (let j = 0; j < img2.height; j++) {
202
+ img2.set(i, j, myp5.color(0, 255, 0)); // green
203
+ }
204
+ }
205
+ img2.updatePixels();
206
+ img.copy(img2, 0, 0, 10, 10, 0, 0, 10, 10); // copy green on red
207
+ myp5.image(img, 0, 0);
208
+
209
+ for (let i = 0; i < 10; i++) {
210
+ for (let j = 0; j < 10; j++) {
211
+ assert.deepEqual(img.get(i, j), [0, 255, 0, 255]); // should be green
212
+ }
213
+ }
214
+ });
215
+
216
+ test('no friendly-err-msg. missing param #0', function() {
217
+ assert.doesNotThrow(
218
+ function() {
219
+ let img = myp5.createImage(50, 50);
220
+ img.copy(0, 0, 10, 10, 10, 0, 10, 10);
221
+ },
222
+ Error,
223
+ 'got unwanted exception'
224
+ );
225
+ });
226
+
227
+ test('missing parameter at #3 ', function() {
228
+ assert.throw(function() {
229
+ let img = myp5.createImage(50, 50);
230
+ img.copy(0, 0, 10, 10, 0, 10, 10);
231
+ });
232
+ });
233
+ });
234
+ });
@@ -0,0 +1,378 @@
1
+ suite('Files', function() {
2
+ var myp5;
3
+
4
+ setup(function(done) {
5
+ new p5(function(p) {
6
+ p.setup = function() {
7
+ myp5 = p;
8
+ done();
9
+ };
10
+ });
11
+ });
12
+
13
+ teardown(function() {
14
+ myp5.remove();
15
+ });
16
+
17
+ // httpDo
18
+ suite('httpDo()', function() {
19
+ test('should be a function', function() {
20
+ assert.ok(myp5.httpDo);
21
+ assert.isFunction(myp5.httpDo);
22
+ });
23
+
24
+ test('should work when provided with just a path', function() {
25
+ return new Promise(function(resolve, reject) {
26
+ myp5.httpDo('unit/assets/sentences.txt', resolve, reject);
27
+ }).then(function(data) {
28
+ assert.ok(data);
29
+ assert.isString(data);
30
+ });
31
+ });
32
+
33
+ test('should accept method parameter', function() {
34
+ return new Promise(function(resolve, reject) {
35
+ myp5.httpDo('unit/assets/sentences.txt', 'GET', resolve, reject);
36
+ }).then(function(data) {
37
+ assert.ok(data);
38
+ assert.isString(data);
39
+ });
40
+ });
41
+
42
+ test('should accept type parameter', function() {
43
+ return new Promise(function(resolve, reject) {
44
+ myp5.httpDo('unit/assets/array.json', 'text', resolve, reject);
45
+ }).then(function(data) {
46
+ assert.ok(data);
47
+ assert.isString(data);
48
+ });
49
+ });
50
+
51
+ test('should accept method and type parameter together', function() {
52
+ return new Promise(function(resolve, reject) {
53
+ myp5.httpDo('unit/assets/array.json', 'GET', 'text', resolve, reject);
54
+ }).then(function(data) {
55
+ assert.ok(data);
56
+ assert.isString(data);
57
+ });
58
+ });
59
+
60
+ test('should pass error object to error callback function', function() {
61
+ return new Promise(function(resolve, reject) {
62
+ myp5.httpDo(
63
+ 'unit/assets/sen.txt',
64
+ function(data) {
65
+ reject('Incorrectly succeeded.');
66
+ },
67
+ resolve
68
+ );
69
+ }).then(function(err) {
70
+ assert.isFalse(err.ok, 'err.ok is false');
71
+ assert.equal(err.status, 404, 'Error status is 404');
72
+ });
73
+ });
74
+
75
+ test('should return a promise', function() {
76
+ var promise = myp5.httpDo('unit/assets/sentences.txt');
77
+ assert.instanceOf(promise, Promise);
78
+ return promise.then(function(data) {
79
+ assert.ok(data);
80
+ assert.isString(data);
81
+ });
82
+ });
83
+
84
+ test('should return a promise that rejects on error', function() {
85
+ return new Promise(function(resolve, reject) {
86
+ var promise = myp5.httpDo('404file');
87
+ assert.instanceOf(promise, Promise);
88
+ promise.then(function(data) {
89
+ reject(new Error('promise resolved.'));
90
+ });
91
+ resolve(
92
+ promise.catch(function(error) {
93
+ assert.instanceOf(error, Error);
94
+ })
95
+ );
96
+ });
97
+ });
98
+ });
99
+
100
+ // saveStrings()
101
+ suite('p5.prototype.saveStrings', function() {
102
+ test('should be a function', function() {
103
+ assert.ok(myp5.saveStrings);
104
+ assert.typeOf(myp5.saveStrings, 'function');
105
+ });
106
+
107
+ test('no friendly-err-msg I', function() {
108
+ assert.doesNotThrow(
109
+ function() {
110
+ let strings = ['some', 'words'];
111
+ myp5.saveStrings(strings, 'myfile');
112
+ },
113
+ Error,
114
+ 'got unwanted exception'
115
+ );
116
+ });
117
+ test('no friendly-err-msg II', function() {
118
+ assert.doesNotThrow(
119
+ function() {
120
+ let strings = ['some', 'words'];
121
+ myp5.saveStrings(strings, 'myfile', 'txt');
122
+ },
123
+ Error,
124
+ 'got unwanted exception'
125
+ );
126
+ });
127
+
128
+ test('no friendly-err-msg III', function() {
129
+ assert.doesNotThrow(
130
+ function() {
131
+ let strings = ['some', 'words'];
132
+ myp5.saveStrings(strings, 'myfile', 'txt', true);
133
+ },
134
+ Error,
135
+ 'got unwanted exception'
136
+ );
137
+ });
138
+
139
+ testUnMinified('missing param #1', function() {
140
+ assert.validationError(function() {
141
+ let strings = ['some', 'words'];
142
+ myp5.saveStrings(strings);
143
+ });
144
+ });
145
+
146
+ testUnMinified('wrong param type at #0', function() {
147
+ assert.validationError(function() {
148
+ let strings = 'some words';
149
+ myp5.saveStrings(strings);
150
+ });
151
+ });
152
+
153
+ testWithDownload(
154
+ 'should download a file with expected contents',
155
+ async function(blobContainer) {
156
+ let strings = ['some', 'words'];
157
+
158
+ myp5.saveStrings(strings, 'myfile');
159
+
160
+ let myBlob = blobContainer.blob;
161
+ let text = await myBlob.text();
162
+ // Each element on a separate line with a trailing line-break
163
+ assert.strictEqual(text, strings.join('\n') + '\n');
164
+ },
165
+ true
166
+ );
167
+
168
+ testWithDownload(
169
+ 'should download a file with expected contents with CRLF',
170
+ async function(blobContainer) {
171
+ let strings = ['some', 'words'];
172
+
173
+ myp5.saveStrings(strings, 'myfile', 'txt', true);
174
+ let myBlob = blobContainer.blob;
175
+ let text = await myBlob.text();
176
+ // Each element on a separate line with a trailing CRLF
177
+ assert.strictEqual(text, strings.join('\r\n') + '\r\n');
178
+ },
179
+ true
180
+ );
181
+ });
182
+
183
+ // saveJSON()
184
+ suite('p5.prototype.saveJSON', function() {
185
+ test('should be a function', function() {
186
+ assert.ok(myp5.saveJSON);
187
+ assert.typeOf(myp5.saveJSON, 'function');
188
+ });
189
+
190
+ test('no friendly-err-msg I', function() {
191
+ assert.doesNotThrow(
192
+ function() {
193
+ let myObj = { hi: 'hello' };
194
+ myp5.saveJSON(myObj, 'myfile');
195
+ },
196
+ Error,
197
+ 'got unwanted exception'
198
+ );
199
+ });
200
+ test('no friendly-err-msg II', function() {
201
+ assert.doesNotThrow(
202
+ function() {
203
+ let myObj = [{ hi: 'hello' }];
204
+ myp5.saveJSON(myObj, 'myfile');
205
+ },
206
+ Error,
207
+ 'got unwanted exception'
208
+ );
209
+ });
210
+
211
+ test('no friendly-err-msg III', function() {
212
+ assert.doesNotThrow(
213
+ function() {
214
+ let myObj = { hi: 'hello' };
215
+ myp5.saveJSON(myObj, 'myfile', true);
216
+ },
217
+ Error,
218
+ 'got unwanted exception'
219
+ );
220
+ });
221
+
222
+ testUnMinified('missing param #1', function() {
223
+ assert.validationError(function() {
224
+ let myObj = { hi: 'hello' };
225
+ myp5.saveJSON(myObj);
226
+ });
227
+ });
228
+
229
+ testUnMinified('wrong param type at #0', function() {
230
+ assert.validationError(function() {
231
+ let myObj = 'some words';
232
+ myp5.saveJSON(myObj);
233
+ });
234
+ });
235
+
236
+ testWithDownload(
237
+ 'should download a file with expected contents',
238
+ async function(blobContainer) {
239
+ let myObj = { hi: 'hello' };
240
+
241
+ myp5.saveJSON(myObj, 'myfile');
242
+ let myBlob = blobContainer.blob;
243
+ let text = await myBlob.text();
244
+ let json = JSON.parse(text);
245
+ // Each element on a separate line with a trailing line-break
246
+ assert.deepEqual(myObj, json);
247
+ },
248
+ true // asyncFn = true
249
+ );
250
+ });
251
+
252
+ // writeFile()
253
+ suite('p5.prototype.writeFile', function() {
254
+ test('should be a function', function() {
255
+ assert.ok(myp5.writeFile);
256
+ assert.typeOf(myp5.writeFile, 'function');
257
+ });
258
+ testWithDownload(
259
+ 'should download a file with expected contents (text)',
260
+ async function(blobContainer) {
261
+ let myArray = ['hello', 'hi'];
262
+
263
+ myp5.writeFile(myArray, 'myfile');
264
+ let myBlob = blobContainer.blob;
265
+ let text = await myBlob.text();
266
+ assert.strictEqual(text, myArray.join(''));
267
+ },
268
+ true // asyncFn = true
269
+ );
270
+ });
271
+
272
+ // downloadFile()
273
+ suite('p5.prototype.downloadFile', function() {
274
+ test('should be a function', function() {
275
+ assert.ok(myp5.writeFile);
276
+ assert.typeOf(myp5.writeFile, 'function');
277
+ });
278
+ testWithDownload(
279
+ 'should download a file with expected contents',
280
+ async function(blobContainer) {
281
+ let myArray = ['hello', 'hi'];
282
+ let inBlob = new Blob(myArray);
283
+ myp5.downloadFile(inBlob, 'myfile');
284
+ let myBlob = blobContainer.blob;
285
+ let text = await myBlob.text();
286
+ assert.strictEqual(text, myArray.join(''));
287
+ },
288
+ true // asyncFn = true
289
+ );
290
+ });
291
+
292
+ // save()
293
+ suite('p5.prototype.save', function() {
294
+ suite('saving images', function() {
295
+ let waitForBlob = async function(blc) {
296
+ let sleep = function(ms) {
297
+ return new Promise(r => setTimeout(r, ms));
298
+ };
299
+ while (!blc.blob) {
300
+ await sleep(5);
301
+ }
302
+ };
303
+ setup(function(done) {
304
+ myp5.createCanvas(20, 20);
305
+ myp5.background(255, 0, 0);
306
+ done();
307
+ });
308
+
309
+ test('should be a function', function() {
310
+ assert.ok(myp5.save);
311
+ assert.typeOf(myp5.save, 'function');
312
+ });
313
+
314
+ testWithDownload(
315
+ 'should download a png file',
316
+ async function(blobContainer) {
317
+ myp5.save();
318
+ await waitForBlob(blobContainer);
319
+ let myBlob = blobContainer.blob;
320
+ assert.strictEqual(myBlob.type, 'image/png');
321
+
322
+ blobContainer.blob = null;
323
+ let gb = myp5.createGraphics(100, 100);
324
+ myp5.save(gb);
325
+ await waitForBlob(blobContainer);
326
+ myBlob = blobContainer.blob;
327
+ assert.strictEqual(myBlob.type, 'image/png');
328
+ },
329
+ true
330
+ );
331
+
332
+ testWithDownload(
333
+ 'should download a jpg file',
334
+ async function(blobContainer) {
335
+ myp5.save('filename.jpg');
336
+ await waitForBlob(blobContainer);
337
+ let myBlob = blobContainer.blob;
338
+ assert.strictEqual(myBlob.type, 'image/jpeg');
339
+
340
+ blobContainer.blob = null;
341
+ let gb = myp5.createGraphics(100, 100);
342
+ myp5.save(gb, 'filename.jpg');
343
+ await waitForBlob(blobContainer);
344
+ myBlob = blobContainer.blob;
345
+ assert.strictEqual(myBlob.type, 'image/jpeg');
346
+ },
347
+ true
348
+ );
349
+ });
350
+
351
+ suite('saving strings and json', function() {
352
+ testWithDownload(
353
+ 'should download a text file',
354
+ async function(blobContainer) {
355
+ let myStrings = ['aaa', 'bbb'];
356
+ myp5.save(myStrings, 'filename');
357
+ let myBlob = blobContainer.blob;
358
+ let text = await myBlob.text();
359
+ assert.strictEqual(text, myStrings.join('\n') + '\n');
360
+ },
361
+ true
362
+ );
363
+
364
+ testWithDownload(
365
+ 'should download a json file',
366
+ async function(blobContainer) {
367
+ let myObj = { hi: 'hello' };
368
+ myp5.save(myObj, 'filename.json');
369
+ let myBlob = blobContainer.blob;
370
+ let text = await myBlob.text();
371
+ let outObj = JSON.parse(text);
372
+ assert.deepEqual(outObj, myObj);
373
+ },
374
+ true
375
+ );
376
+ });
377
+ });
378
+ });