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,2146 @@
1
+ suite('DOM', function() {
2
+ suite('p5.prototype.select', function() {
3
+ /**
4
+ * Uses p5 in instance-mode inside a custom container.
5
+ * All elements are attached inside the container for testing
6
+ * And cleaned up on teardown.
7
+ */
8
+ let myp5;
9
+ let myp5Container;
10
+
11
+ setup(function(done) {
12
+ myp5Container = document.createElement('div');
13
+ document.body.appendChild(myp5Container);
14
+ new p5(function(p) {
15
+ p.setup = function() {
16
+ myp5 = p;
17
+ done();
18
+ };
19
+ }, myp5Container);
20
+ });
21
+
22
+ teardown(function() {
23
+ myp5.remove();
24
+ if (myp5Container && myp5Container.parentNode) {
25
+ myp5Container.parentNode.removeChild(myp5Container);
26
+ }
27
+ p5Container = null;
28
+ });
29
+
30
+ test('should return only one p5.element if match is found', function() {
31
+ // Adding 2 buttons to container
32
+ myp5.createCheckbox('Text 1');
33
+ myp5.createCheckbox('Text 2');
34
+ const result = myp5.select('input');
35
+
36
+ assert.instanceOf(result, p5.Element);
37
+ });
38
+
39
+ const generateButton = (name, className = null) => {
40
+ const button = myp5.createButton(name);
41
+ if (className) {
42
+ button.class(className);
43
+ }
44
+ return button;
45
+ };
46
+
47
+ test('should find element by class name', function() {
48
+ // Creates 2 buttons with same class and test if it selects only one.
49
+ const testClassName = 'test-button';
50
+ const testButton = generateButton('Button 1', testClassName);
51
+ generateButton('Button 2', testClassName);
52
+
53
+ const result = myp5.select(`.${testClassName}`);
54
+ assert.deepEqual(result.elt, testButton.elt);
55
+ });
56
+
57
+ test('should find element by class name from given container', function() {
58
+ // Creates 2 buttons with same class in a container and test if it selects only one.
59
+ const testClassName = 'test-button';
60
+ generateButton('Button 1', testClassName);
61
+ const testButton = generateButton('Button 2', testClassName);
62
+ const testContainer = myp5.createDiv();
63
+ testButton.parent(testContainer);
64
+
65
+ const result = myp5.select(`.${testClassName}`, testContainer);
66
+ assert.deepEqual(testButton.elt, result.elt);
67
+ });
68
+
69
+ test('should return null when no matches are found by class name', function() {
70
+ // Gives unused className and tests if it returns null
71
+ const testClassName = 'test-button';
72
+ generateButton('Test Button', testClassName);
73
+ const result = myp5.select('.classNameWithTypo');
74
+ assert.isNull(result);
75
+ });
76
+
77
+ test('should find element by tag name', function() {
78
+ // Creates 2 similar elements and tests if it selects only one.
79
+ const testButton = generateButton('Button 1');
80
+ generateButton('Button 2');
81
+ const result = myp5.select('button');
82
+ assert.deepEqual(result.elt, testButton.elt);
83
+ });
84
+
85
+ test('should find element by tag name from given container', function() {
86
+ // Creates 2 elements inside and outside of a container and tests if it
87
+ // selects inside the container
88
+ generateButton('Button 1');
89
+ const testButton = generateButton('Button 2');
90
+ const testDiv = myp5.createDiv();
91
+ testButton.parent(testDiv);
92
+
93
+ const result = myp5.select('button', testDiv);
94
+ assert.deepEqual(result.elt, testButton.elt);
95
+ });
96
+
97
+ test('should return null when no matches are found by tag name', function() {
98
+ generateButton('Test Button');
99
+ const result = myp5.select('video', myp5Container);
100
+ assert.isNull(result);
101
+ });
102
+
103
+ const generateDiv = (id = null, className = null) => {
104
+ const div = myp5.createDiv();
105
+ if (id) {
106
+ div.id(id);
107
+ }
108
+ if (className) {
109
+ div.class(className);
110
+ }
111
+ return div;
112
+ };
113
+
114
+ test('should select element in container using CSS selector with ID', function() {
115
+ const divID = 'divId';
116
+ const testDiv = generateDiv(divID);
117
+ const testButton = generateButton('Button 1');
118
+ generateButton('Button 2');
119
+ testButton.parent(testDiv);
120
+
121
+ const result = myp5.select(`#${divID} button`);
122
+ assert.deepEqual(result.elt, testButton.elt);
123
+ });
124
+
125
+ test('should select element in container using CSS selector with class name', function() {
126
+ const divClass = 'divClass';
127
+ const testDiv = generateDiv(null, divClass);
128
+ const testButton = generateButton('Button 1');
129
+ generateButton('Button 2');
130
+ testButton.parent(testDiv);
131
+
132
+ const result = myp5.select(`.${divClass} button`);
133
+ assert.deepEqual(result.elt, testButton.elt);
134
+ });
135
+ });
136
+
137
+ suite('p5.prototype.selectAll', function() {
138
+ let myp5;
139
+ let myp5Container;
140
+
141
+ setup(function(done) {
142
+ myp5Container = document.createElement('div');
143
+ document.body.appendChild(myp5Container);
144
+ new p5(function(p) {
145
+ p.setup = function() {
146
+ myp5 = p;
147
+ let mydiv = document.createElement('div');
148
+ mydiv.setAttribute('id', 'main');
149
+ let childbutton = document.createElement('button');
150
+ childbutton.setAttribute('class', 'p5button');
151
+ mydiv.append(childbutton);
152
+ let otherbutton = document.createElement('button');
153
+ otherbutton.setAttribute('class', 'p5button');
154
+ myp5Container.append(mydiv, otherbutton);
155
+ done();
156
+ };
157
+ }, myp5Container);
158
+ });
159
+
160
+ teardown(function() {
161
+ myp5.remove();
162
+ if (myp5Container && myp5Container.parentNode) {
163
+ myp5Container.parentNode.removeChild(myp5Container);
164
+ }
165
+ myp5Container = null;
166
+ });
167
+
168
+ test('should return an array', function() {
169
+ const elements = myp5.selectAll('button');
170
+ assert.isArray(elements);
171
+ });
172
+
173
+ test('should return empty array when no matching classes are found', function() {
174
+ const elements = myp5.selectAll('.randomElements');
175
+ assert.isArray(elements);
176
+ assert.lengthOf(elements, 0);
177
+ });
178
+
179
+ const matchResults = (p5Results, domResults) => {
180
+ assert.lengthOf(p5Results, domResults.length);
181
+ for (let i = 0; i < p5Results.length; i += 1) {
182
+ assert.deepEqual(p5Results[i].elt, domResults[i]);
183
+ }
184
+ };
185
+
186
+ test('should find all elements with matching class name', function() {
187
+ const testClassName = 'p5button';
188
+ const p5Results = myp5.selectAll(`.${testClassName}`);
189
+ const domResults = myp5Container.getElementsByClassName(testClassName);
190
+ matchResults(p5Results, domResults);
191
+ });
192
+
193
+ test('should find all elements with matching class name in given container', function() {
194
+ const testClassName = 'p5button';
195
+ const parentContainerId = 'main';
196
+ const p5Results = myp5.selectAll(
197
+ `.${testClassName}`,
198
+ `#${parentContainerId}`
199
+ );
200
+ const containerElement = document.getElementById(parentContainerId);
201
+ const domResults = containerElement.getElementsByClassName(testClassName);
202
+ matchResults(p5Results, domResults);
203
+ });
204
+
205
+ test('should find all elements with matching tag name', function() {
206
+ const testTagName = 'button';
207
+ const p5Results = myp5.selectAll(testTagName);
208
+ const domResults = myp5Container.getElementsByTagName(testTagName);
209
+ matchResults(p5Results, domResults);
210
+ });
211
+
212
+ test('should find all elements with matching tag name in given container', function() {
213
+ const testTagName = 'button';
214
+ const parentContainerId = 'main';
215
+ const p5Results = myp5.selectAll(testTagName, `#${parentContainerId}`);
216
+ const containerElement = document.getElementById(parentContainerId);
217
+ const domResults = containerElement.getElementsByTagName(testTagName);
218
+ matchResults(p5Results, domResults);
219
+ });
220
+
221
+ test('should find all elements in container using CSS selector with id', function() {
222
+ const testTagName = 'button';
223
+ const parentContainerId = 'main';
224
+ const p5Results = myp5.selectAll(`#${parentContainerId} ${testTagName}`);
225
+ const containerElement = document.getElementById(parentContainerId);
226
+ const domResults = containerElement.getElementsByTagName(testTagName);
227
+ matchResults(p5Results, domResults);
228
+ });
229
+ });
230
+
231
+ suite('p5.prototype.removeElements', function() {
232
+ let myp5;
233
+ let myp5Container;
234
+
235
+ setup(function(done) {
236
+ myp5Container = document.createElement('div');
237
+ document.body.appendChild(myp5Container);
238
+ new p5(function(p) {
239
+ p.setup = function() {
240
+ // configure p5 to not add a canvas by default.
241
+ p.noCanvas();
242
+ myp5 = p;
243
+ done();
244
+ };
245
+ }, myp5Container);
246
+ });
247
+
248
+ teardown(function() {
249
+ myp5.remove();
250
+ if (myp5Container && myp5Container.parentNode) {
251
+ myp5Container.parentNode.removeChild(myp5Container);
252
+ }
253
+ myp5Container = null;
254
+ });
255
+
256
+ test('should remove all elements created by p5 except Canvas', function() {
257
+ // creates 6 elements one of which is a canvas, then calls
258
+ // removeElements and tests if only canvas is left.
259
+ const tags = ['a', 'button', 'canvas', 'div', 'p', 'video'];
260
+ for (const tag of tags) {
261
+ myp5.createElement(tag);
262
+ }
263
+ // Check if all elements are created.
264
+ assert.deepEqual(myp5Container.childElementCount, tags.length);
265
+
266
+ // Call removeElements and check if only canvas is remaining
267
+ myp5.removeElements();
268
+ assert.deepEqual(myp5Container.childElementCount, 1);
269
+ const remainingElement = myp5Container.children[0];
270
+ assert.instanceOf(remainingElement, HTMLCanvasElement);
271
+ });
272
+ });
273
+
274
+ suite('p5.Element.prototype.changed', function() {
275
+ testSketchWithPromise(
276
+ 'should trigger callback when element changes',
277
+ function(sketch, resolve, reject) {
278
+ sketch.setup = function() {
279
+ const testElement = sketch.createSlider(0, 100, 50, 10);
280
+ testElement.changed(resolve);
281
+ testElement.elt.dispatchEvent(new Event('change'));
282
+ };
283
+ }
284
+ );
285
+
286
+ testSketchWithPromise(
287
+ 'should not trigger callback after changed(false) is called',
288
+ function(sketch, resolve, reject) {
289
+ sketch.setup = function() {
290
+ const testElement = sketch.createSlider(0, 100, 50, 10);
291
+ // if callback is called, there is some error. so reject
292
+ testElement.changed(reject);
293
+ testElement.changed(false);
294
+ testElement.elt.dispatchEvent(new Event('change'));
295
+ resolve();
296
+ };
297
+ }
298
+ );
299
+ });
300
+
301
+ suite('p5.Element.prototype.input', function() {
302
+ testSketchWithPromise(
303
+ 'should trigger callback when input is provided',
304
+ function(sketch, resolve, reject) {
305
+ sketch.setup = function() {
306
+ const testElement = sketch.createElement('input');
307
+ testElement.input(resolve);
308
+ testElement.elt.dispatchEvent(new Event('input'));
309
+ };
310
+ }
311
+ );
312
+
313
+ testSketchWithPromise(
314
+ 'should not trigger callback after input(false) is called',
315
+ function(sketch, resolve, reject) {
316
+ sketch.setup = function() {
317
+ const testElement = sketch.createElement('input');
318
+ // if callback is called, there is some error. so reject
319
+ testElement.input(reject);
320
+ testElement.input(false);
321
+ testElement.elt.dispatchEvent(new Event('input'));
322
+ resolve();
323
+ };
324
+ }
325
+ );
326
+ });
327
+
328
+ suite('p5.prototype.createDiv', function() {
329
+ let myp5;
330
+ let testElement;
331
+
332
+ setup(function(done) {
333
+ new p5(function(p) {
334
+ p.setup = function() {
335
+ myp5 = p;
336
+ done();
337
+ };
338
+ });
339
+ });
340
+
341
+ teardown(function() {
342
+ myp5.remove();
343
+ if (testElement && testElement.parentNode) {
344
+ testElement.parentNode.removeChild(testElement);
345
+ }
346
+ testElement = null;
347
+ });
348
+
349
+ test('should be a function', function() {
350
+ assert.isFunction(myp5.createDiv);
351
+ });
352
+
353
+ test('should return a p5.Element of div type', function() {
354
+ testElement = myp5.createDiv();
355
+ assert.instanceOf(testElement, p5.Element);
356
+ assert.instanceOf(testElement.elt, HTMLDivElement);
357
+ });
358
+
359
+ test('should set given param as innerHTML of div', function() {
360
+ const testHTML = '<p>Hello</p>';
361
+ testElement = myp5.createDiv(testHTML);
362
+ assert.deepEqual(testElement.elt.innerHTML, testHTML);
363
+ });
364
+ });
365
+
366
+ suite('p5.prototype.createP', function() {
367
+ let myp5;
368
+ let testElement;
369
+
370
+ setup(function(done) {
371
+ new p5(function(p) {
372
+ p.setup = function() {
373
+ myp5 = p;
374
+ done();
375
+ };
376
+ });
377
+ });
378
+
379
+ teardown(function() {
380
+ myp5.remove();
381
+ if (testElement && testElement.parentNode) {
382
+ testElement.parentNode.removeChild(testElement);
383
+ }
384
+ testElement = null;
385
+ });
386
+
387
+ test('should be a function', function() {
388
+ assert.isFunction(myp5.createP);
389
+ });
390
+
391
+ test('should return a p5.Element of p type', function() {
392
+ testElement = myp5.createP();
393
+ assert.instanceOf(testElement, p5.Element);
394
+ assert.instanceOf(testElement.elt, HTMLParagraphElement);
395
+ });
396
+
397
+ test('should set given param as innerHTML of p', function() {
398
+ const testHTML = '<b>Hello</b>';
399
+ testElement = myp5.createP(testHTML);
400
+ assert.deepEqual(testElement.elt.innerHTML, testHTML);
401
+ });
402
+ });
403
+
404
+ suite('p5.prototype.createSpan', function() {
405
+ let myp5;
406
+ let testElement;
407
+
408
+ setup(function(done) {
409
+ new p5(function(p) {
410
+ p.setup = function() {
411
+ myp5 = p;
412
+ done();
413
+ };
414
+ });
415
+ });
416
+
417
+ teardown(function() {
418
+ myp5.remove();
419
+ if (testElement && testElement.parentNode) {
420
+ testElement.parentNode.removeChild(testElement);
421
+ }
422
+ testElement = null;
423
+ });
424
+
425
+ test('should be a function', function() {
426
+ assert.isFunction(myp5.createSpan);
427
+ });
428
+
429
+ test('should return a p5.Element of span type', function() {
430
+ testElement = myp5.createSpan();
431
+ assert.instanceOf(testElement, p5.Element);
432
+ assert.instanceOf(testElement.elt, HTMLSpanElement);
433
+ });
434
+
435
+ test('should set given param as innerHTML of span', function() {
436
+ const testHTML = '<em>Hello</em>';
437
+ testElement = myp5.createSpan(testHTML);
438
+ assert.deepEqual(testElement.elt.innerHTML, testHTML);
439
+ });
440
+ });
441
+
442
+ suite('p5.prototype.createImg', function() {
443
+ let myp5;
444
+ let testElement;
445
+ const imagePath = 'unit/assets/cat.jpg';
446
+
447
+ setup(function(done) {
448
+ new p5(function(p) {
449
+ p.setup = function() {
450
+ myp5 = p;
451
+ done();
452
+ };
453
+ });
454
+ });
455
+
456
+ teardown(function() {
457
+ myp5.remove();
458
+ if (testElement && testElement.parentNode) {
459
+ testElement.parentNode.removeChild(testElement);
460
+ }
461
+ testElement = null;
462
+ });
463
+
464
+ test('should be a function', function() {
465
+ assert.isFunction(myp5.createImg);
466
+ });
467
+
468
+ test('should return p5.Element of image type', function() {
469
+ testElement = myp5.createImg(imagePath, '');
470
+ assert.instanceOf(testElement, p5.Element);
471
+ assert.instanceOf(testElement.elt, HTMLImageElement);
472
+ });
473
+
474
+ test('should set src of image from params', function() {
475
+ testElement = myp5.createImg(imagePath, '');
476
+ assert.isTrue(testElement.elt.src.endsWith(imagePath));
477
+ });
478
+
479
+ test('should set alt from params if given', function() {
480
+ const alternativeText = 'Picture of a cat';
481
+ testElement = myp5.createImg(imagePath, alternativeText);
482
+ assert.deepEqual(testElement.elt.alt, alternativeText);
483
+ });
484
+
485
+ test('should set crossOrigin from params if given', function() {
486
+ const crossOrigin = 'anonymous';
487
+ testElement = myp5.createImg(imagePath, '', crossOrigin);
488
+ assert.deepEqual(testElement.elt.crossOrigin, crossOrigin);
489
+ });
490
+
491
+ testSketchWithPromise(
492
+ 'should trigger callback when image is loaded',
493
+ function(sketch, resolve, reject) {
494
+ sketch.setup = function() {
495
+ testElement = sketch.createImg(imagePath, '', '', resolve);
496
+ testElement.elt.dispatchEvent(new Event('load'));
497
+ };
498
+ }
499
+ );
500
+ });
501
+
502
+ suite('p5.prototype.createA', function() {
503
+ let myp5;
504
+ let testElement;
505
+
506
+ setup(function(done) {
507
+ new p5(function(p) {
508
+ p.setup = function() {
509
+ myp5 = p;
510
+ done();
511
+ };
512
+ });
513
+ });
514
+
515
+ teardown(function() {
516
+ myp5.remove();
517
+ if (testElement && testElement.parentNode) {
518
+ testElement.parentNode.removeChild(testElement);
519
+ testElement = null;
520
+ }
521
+ });
522
+
523
+ test('should return a p5.Element of anchor type', () => {
524
+ testElement = myp5.createA('', '');
525
+ assert.instanceOf(testElement, p5.Element);
526
+ assert.instanceOf(testElement.elt, HTMLAnchorElement);
527
+ });
528
+
529
+ test('creates anchor with given link & text', function() {
530
+ const testUrl = 'http://p5js.org/';
531
+ const testText = 'p5js website';
532
+ testElement = myp5.createA(testUrl, testText);
533
+
534
+ assert.deepEqual(testElement.elt.href, testUrl);
535
+ assert.deepEqual(testElement.elt.text, testText);
536
+ });
537
+
538
+ test('creates anchor with given target', function() {
539
+ const testTarget = 'blank';
540
+ testElement = myp5.createA('http://p5js.org', 'p5js website', testTarget);
541
+ assert.deepEqual(testElement.elt.target, testTarget);
542
+ });
543
+ });
544
+
545
+ suite('p5.prototype.createSlider', function() {
546
+ let myp5;
547
+ let testElement;
548
+
549
+ setup(function(done) {
550
+ new p5(function(p) {
551
+ p.setup = function() {
552
+ myp5 = p;
553
+ done();
554
+ };
555
+ });
556
+ });
557
+
558
+ teardown(function() {
559
+ myp5.remove();
560
+ if (testElement && testElement.parentNode) {
561
+ testElement.parentNode.removeChild(testElement);
562
+ }
563
+ testElement = null;
564
+ });
565
+
566
+ test('should return a p5.Element of slider type', () => {
567
+ testElement = myp5.createSlider(0, 100, 0, 1);
568
+ assert.instanceOf(testElement, p5.Element);
569
+ assert.instanceOf(testElement.elt, HTMLInputElement);
570
+ assert.deepEqual(testElement.elt.type, 'range');
571
+ });
572
+
573
+ test('should set min and max values', function() {
574
+ let testElement = myp5.createSlider(20, 80);
575
+ assert.deepEqual(testElement.elt.min, '20');
576
+ assert.deepEqual(testElement.elt.max, '80');
577
+ });
578
+
579
+ test('should set slider position', function() {
580
+ let testElement = myp5.createSlider(20, 80, 50);
581
+ assert.deepEqual(testElement.elt.value, '50');
582
+ });
583
+
584
+ test('should set step value', function() {
585
+ testElement = myp5.createSlider(20, 80, 10, 5);
586
+ assert.deepEqual(testElement.elt.step, '5');
587
+ });
588
+ });
589
+
590
+ suite('p5.prototype.createButton', function() {
591
+ let myp5;
592
+ let testElement;
593
+
594
+ setup(function(done) {
595
+ new p5(function(p) {
596
+ p.setup = function() {
597
+ myp5 = p;
598
+ done();
599
+ };
600
+ });
601
+ });
602
+ teardown(function() {
603
+ myp5.remove();
604
+ if (testElement && testElement.parentNode) {
605
+ testElement.parentNode.removeChild(testElement);
606
+ }
607
+ testElement = null;
608
+ });
609
+
610
+ test('should return a p5.Element of button type', function() {
611
+ testElement = myp5.createButton('testButton', 'testButton');
612
+ assert.instanceOf(testElement, p5.Element);
613
+ assert.instanceOf(testElement.elt, HTMLButtonElement);
614
+ });
615
+
616
+ testSketchWithPromise(
617
+ 'should trigger callback when mouse is pressed',
618
+ function(sketch, resolve, reject) {
619
+ sketch.setup = function() {
620
+ const testElement = sketch.createButton('test');
621
+ testElement.mousePressed(resolve);
622
+ testElement.elt.dispatchEvent(new Event('mousedown'));
623
+ };
624
+ }
625
+ );
626
+ });
627
+
628
+ // Tests for createCheckbox
629
+ suite('p5.prototype.createCheckbox', function() {
630
+ let myp5;
631
+ let testElement;
632
+
633
+ setup(function(done) {
634
+ new p5(function(p) {
635
+ p.setup = function() {
636
+ myp5 = p;
637
+ done();
638
+ };
639
+ });
640
+ });
641
+ teardown(function() {
642
+ myp5.remove();
643
+ if (testElement && testElement.parentNode) {
644
+ testElement.parentNode.removeChild(testElement);
645
+ }
646
+ testElement = null;
647
+ });
648
+
649
+ // helper functions
650
+ const getSpanElement = el =>
651
+ el.elt.firstElementChild.getElementsByTagName('span').length
652
+ ? el.elt.firstElementChild.getElementsByTagName('span')[0]
653
+ : null;
654
+
655
+ const getCheckboxElement = el =>
656
+ el.elt.firstElementChild.getElementsByTagName('input').length
657
+ ? el.elt.firstElementChild.getElementsByTagName('input')[0]
658
+ : null;
659
+
660
+ test('should be a function', function() {
661
+ assert.isFunction(myp5.createCheckbox);
662
+ });
663
+
664
+ test('should return a p5.Element with checkbox as descendant', function() {
665
+ testElement = myp5.createCheckbox();
666
+ const checkboxElement = getCheckboxElement(testElement);
667
+
668
+ assert.instanceOf(testElement, p5.Element);
669
+ assert.instanceOf(checkboxElement, HTMLInputElement);
670
+ });
671
+
672
+ test('calling createCheckbox(label) should create checkbox and set its label', function() {
673
+ const labelValue = 'label';
674
+ testElement = myp5.createCheckbox(labelValue);
675
+ const spanElement = getSpanElement(testElement);
676
+ const testElementLabelValue = getSpanElement(testElement)
677
+ ? getSpanElement(testElement).innerHTML
678
+ : '';
679
+
680
+ assert.instanceOf(testElement, p5.Element);
681
+ assert.instanceOf(spanElement, HTMLSpanElement);
682
+ assert.deepEqual(testElementLabelValue, labelValue);
683
+ });
684
+
685
+ test('calling createCheckbox(label, true) should create a checked checkbox and set its label', function() {
686
+ const labelValue = 'label';
687
+ testElement = myp5.createCheckbox(labelValue, true);
688
+
689
+ const spanElement = getSpanElement(testElement);
690
+ const testElementLabelValue = getSpanElement(testElement)
691
+ ? getSpanElement(testElement).innerHTML
692
+ : '';
693
+
694
+ assert.instanceOf(testElement, p5.Element);
695
+ assert.instanceOf(spanElement, HTMLSpanElement);
696
+ assert.deepEqual(testElementLabelValue, labelValue);
697
+ assert.isTrue(testElement.checked());
698
+ });
699
+
700
+ test('calling checked() should return checked value of checkbox', function() {
701
+ testElement = myp5.createCheckbox('', true);
702
+ assert.isTrue(testElement.checked());
703
+ });
704
+
705
+ test('calling checked(true) should set checked value of checkbox', function() {
706
+ testElement = myp5.createCheckbox('', false);
707
+ testElement.checked(true);
708
+ assert.isTrue(testElement.checked());
709
+ });
710
+ });
711
+
712
+ suite('p5.prototype.createSelect', function() {
713
+ let myp5;
714
+ let testElement;
715
+
716
+ setup(function(done) {
717
+ new p5(function(p) {
718
+ p.setup = function() {
719
+ myp5 = p;
720
+ done();
721
+ };
722
+ });
723
+ });
724
+
725
+ teardown(function() {
726
+ myp5.remove();
727
+ if (testElement && testElement.parentNode) {
728
+ testElement.parentNode.removeChild(testElement);
729
+ testElement = null;
730
+ }
731
+ });
732
+
733
+ const createHTMLSelect = options => {
734
+ const selectElement = document.createElement('select');
735
+ for (const optionName of options) {
736
+ const option = document.createElement('option');
737
+ option.setAttribute('label', optionName);
738
+ option.setAttribute('value', optionName);
739
+ selectElement.add(option);
740
+ }
741
+ return selectElement;
742
+ };
743
+
744
+ test('should be a function', function() {
745
+ assert.isFunction(myp5.createSelect);
746
+ });
747
+
748
+ test('should return p5.Element of select HTML Element', function() {
749
+ testElement = myp5.createSelect();
750
+ assert.instanceOf(testElement, p5.Element);
751
+ assert.instanceOf(testElement.elt, HTMLSelectElement);
752
+ });
753
+
754
+ test('should return p5.Element when select element is passed', function() {
755
+ selectElement = createHTMLSelect(['option1', 'option2']);
756
+ testElement = myp5.createSelect(selectElement);
757
+ assert.deepEqual(testElement.elt, selectElement);
758
+ });
759
+
760
+ test('calling option(newName) should add a new option', function() {
761
+ const testOptions = ['John', 'Bethany', 'Dwayne'];
762
+ testElement = myp5.createSelect();
763
+ for (const optionName of testOptions) testElement.option(optionName);
764
+
765
+ const htmlOptions = [];
766
+ for (const optionName of testElement.elt.options) {
767
+ assert.deepEqual(optionName.label, optionName.value);
768
+ htmlOptions.push(optionName.label);
769
+ }
770
+ assert.deepEqual(htmlOptions, testOptions);
771
+ });
772
+
773
+ test('calling option(name, newValue) should update value of option', function() {
774
+ const optionName = 'john';
775
+ const testValues = [1, 'abc', true];
776
+ testElement = myp5.createSelect();
777
+ testElement.option(optionName, 0);
778
+
779
+ for (const newValue of testValues) {
780
+ testElement.option(optionName, newValue);
781
+ const htmlValue = testElement.elt.options[0].value;
782
+ assert(htmlValue, newValue);
783
+ }
784
+ });
785
+
786
+ test('calling value() should return current selected option', function() {
787
+ testElement = myp5.createSelect();
788
+ testElement.option('Sunday');
789
+ testElement.option('Monday');
790
+ testElement.elt.options[1].selected = true;
791
+ assert(testElement.value(), 'Monday');
792
+ });
793
+
794
+ test('calling selected() should return all selected options', function() {
795
+ testElement = myp5.createSelect(true);
796
+ options = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'];
797
+ for (const optionName of options) testElement.option(optionName);
798
+
799
+ // Select multiple options
800
+ const selectedOptions = options.slice(0, 3);
801
+ for (let i = 0; i < selectedOptions.length; i++) {
802
+ testElement.elt.options[i].selected = true;
803
+ assert.deepEqual(
804
+ testElement.selected(),
805
+ selectedOptions.slice(0, i + 1)
806
+ );
807
+ }
808
+ });
809
+
810
+ test('should update select value when HTML special characters are in the name', function() {
811
+ testElement = myp5.createSelect(true);
812
+ testElement.option('&', 'foo');
813
+ assert.equal(testElement.elt.options.length, 1);
814
+ assert.equal(testElement.elt.options[0].value, 'foo');
815
+ testElement.option('&', 'bar');
816
+ assert.equal(testElement.elt.options[0].value, 'bar');
817
+ });
818
+
819
+ test('calling selected(value) should updated selectedIndex', function() {
820
+ testElement = myp5.createSelect(true);
821
+ options = ['Sunday', 'Monday', 'Tuesday', 'Friday'];
822
+ for (const optionName of options) testElement.option(optionName);
823
+
824
+ // Select multiple options and check if the values get updated
825
+ for (let i = 0; i < options.length; i++) {
826
+ testElement.selected(options[i]);
827
+ const selectedIndexValue =
828
+ testElement.elt.options[testElement.elt.selectedIndex].value;
829
+ assert.deepEqual(selectedIndexValue, options[i]);
830
+ }
831
+ });
832
+
833
+ test('calling disable() should disable the whole dropdown', function() {
834
+ testElement = myp5.createSelect(true);
835
+ testElement.disable();
836
+
837
+ assert.isTrue(testElement.elt.disabled);
838
+ });
839
+
840
+ test('should disable an option when disable() method invoked with option name', function() {
841
+ testElement = myp5.createSelect(true);
842
+ options = ['Sunday', 'Monday', 'Tuesday', 'Friday'];
843
+ for (const optionName of options) testElement.option(optionName);
844
+
845
+ const disabledIndex = 2;
846
+ testElement.disable(options[disabledIndex]);
847
+ assert.isTrue(testElement.elt.options[disabledIndex].disabled);
848
+ assert.isFalse(testElement.elt.options[disabledIndex].selected);
849
+ });
850
+ });
851
+
852
+ suite('p5.prototype.createRadio', function() {
853
+ let myp5;
854
+ let testElement;
855
+
856
+ setup(function(done) {
857
+ new p5(function(p) {
858
+ p.setup = function() {
859
+ myp5 = p;
860
+ done();
861
+ };
862
+ });
863
+ });
864
+
865
+ teardown(function() {
866
+ myp5.remove();
867
+ if (testElement && testElement.parentNode) {
868
+ testElement.parentNode.removeChild(testElement);
869
+ testElement = null;
870
+ }
871
+ });
872
+
873
+ // Helper functions
874
+ const createRadioElement = (options = []) => {
875
+ const radioEl = document.createElement('div');
876
+ for (const option of options) {
877
+ const optionEl = document.createElement('input');
878
+ optionEl.setAttribute('type', 'radio');
879
+ optionEl.setAttribute('value', option);
880
+ radioEl.appendChild(optionEl);
881
+ }
882
+ return radioEl;
883
+ };
884
+
885
+ const isRadioInput = el =>
886
+ el instanceof HTMLInputElement && el.type === 'radio';
887
+ const isLabelElement = el => el instanceof HTMLLabelElement;
888
+
889
+ const getChildren = radioEl =>
890
+ Array.from(radioEl.children)
891
+ .filter(
892
+ el =>
893
+ isRadioInput(el) ||
894
+ (isLabelElement(el) && isRadioInput(el.firstElementChild))
895
+ )
896
+ .map(el => (isRadioInput(el) ? el : el.firstElementChild));
897
+
898
+ test('should be a function', function() {
899
+ assert.isFunction(myp5.createRadio);
900
+ });
901
+
902
+ test('should return p5.Element of radio type', function() {
903
+ testElement = myp5.createRadio();
904
+ assert.instanceOf(testElement, p5.Element);
905
+ assert.instanceOf(testElement.elt, HTMLDivElement);
906
+ });
907
+
908
+ test('should return p5.Element from existing radio Element', function() {
909
+ const options = ['Saturday', 'Sunday'];
910
+ const radioElement = createRadioElement(options);
911
+ testElement = myp5.createRadio(radioElement);
912
+
913
+ assert.deepEqual(testElement.elt, radioElement);
914
+ });
915
+
916
+ test('calling option(value) should return existing radio element', function() {
917
+ const options = ['Saturday', 'Sunday'];
918
+ const radioElement = createRadioElement(options);
919
+ testElement = myp5.createRadio(radioElement);
920
+ for (const radioInput of getChildren(radioElement)) {
921
+ const optionEl = testElement.option(radioInput.value);
922
+ assert.deepEqual(radioInput, optionEl);
923
+ }
924
+ assert.deepEqual(getChildren(testElement.elt).length, options.length);
925
+ });
926
+
927
+ test('calling option(newValue) should create a new radio input', function() {
928
+ const testName = 'defaultRadio';
929
+ const options = ['Saturday', 'Sunday'];
930
+ testElement = myp5.createRadio(testName);
931
+ let count = 0;
932
+ for (const option of options) {
933
+ const optionEl = testElement.option(option);
934
+ assert.instanceOf(optionEl, HTMLInputElement);
935
+ assert.deepEqual(optionEl.type, 'radio');
936
+ assert.deepEqual(optionEl.value, option);
937
+ assert.deepEqual(optionEl.name, testName);
938
+ // Increment by one for every label element
939
+ count += 1;
940
+
941
+ assert.deepEqual(testElement.elt.childElementCount, count);
942
+ }
943
+ });
944
+
945
+ test('calling option(value, label) should set label of option', function() {
946
+ const testName = 'defaultRadio';
947
+ const options = ['Saturday', 'Sunday'];
948
+ testElement = myp5.createRadio(testName);
949
+ for (const option of options) {
950
+ const optionLabel = `${option}-label`;
951
+ const optionEl = testElement.option(option, optionLabel);
952
+ assert.deepEqual(optionEl.value, option);
953
+ assert.deepEqual(optionEl.name, testName);
954
+ const spanEl = optionEl.nextElementSibling;
955
+ assert.deepEqual(spanEl.innerHTML, optionLabel);
956
+ }
957
+ });
958
+
959
+ test('should use given name for all options', function() {
960
+ const testName = 'defaultRadio';
961
+ const options = ['Saturday', 'Sunday'];
962
+ const radioElement = createRadioElement(options);
963
+ testElement = myp5.createRadio(radioElement, testName);
964
+
965
+ for (const option of options) {
966
+ const optionEl = testElement.option(option);
967
+ assert.deepEqual(optionEl.name, testName);
968
+ }
969
+ });
970
+
971
+ test('calling remove(value) should remove option', function() {
972
+ const options = ['Monday', 'Friday', 'Saturday', 'Sunday'];
973
+ const radioElement = createRadioElement(options);
974
+ testElement = myp5.createRadio(radioElement);
975
+
976
+ // Remove element
977
+ const testValue = 'Friday';
978
+ options.splice(options.indexOf(testValue), 1);
979
+ testElement.remove(testValue);
980
+ // Verify remaining options
981
+ const remainingOptions = Array.from(getChildren(testElement.elt)).map(
982
+ el => el.value
983
+ );
984
+ assert.deepEqual(options, remainingOptions);
985
+ });
986
+
987
+ test('calling value() should return selected value', function() {
988
+ const options = ['Monday', 'Friday', 'Saturday', 'Sunday'];
989
+ const selectedValue = options[1];
990
+ testElement = myp5.createRadio();
991
+ for (const option of options) testElement.option(option);
992
+ testElement.selected(selectedValue);
993
+ assert.deepEqual(testElement.value(), selectedValue);
994
+ });
995
+
996
+ test('calling selected(value) should select a value and return it', function() {
997
+ const options = ['Monday', 'Friday', 'Saturday', 'Sunday'];
998
+ testElement = myp5.createRadio();
999
+ for (const option of options) testElement.option(option);
1000
+
1001
+ for (const option of options) {
1002
+ testElement.selected(option);
1003
+ const selectedInput = testElement.option(option);
1004
+ assert.deepEqual(selectedInput.checked, true);
1005
+ }
1006
+ });
1007
+
1008
+ test('calling selected() should return the currently selected option', function() {
1009
+ const options = ['Monday', 'Friday', 'Saturday', 'Sunday'];
1010
+ testElement = myp5.createRadio();
1011
+ for (const option of options) testElement.option(option);
1012
+
1013
+ const testOption = getChildren(testElement.elt)[1];
1014
+ testOption.setAttribute('checked', true);
1015
+ const selectedOption = testElement.selected();
1016
+ assert.deepEqual(selectedOption, testOption);
1017
+ assert.isTrue(selectedOption.checked);
1018
+ });
1019
+
1020
+ test('calling disable() should disable all the radio inputs', function() {
1021
+ const options = ['Monday', 'Friday', 'Saturday', 'Sunday'];
1022
+ testElement = myp5.createRadio();
1023
+ for (const option of options) testElement.option(option);
1024
+
1025
+ testElement.disable();
1026
+ for (const option of options) {
1027
+ assert.isTrue(testElement.option(option).disabled);
1028
+ }
1029
+ });
1030
+ });
1031
+
1032
+ suite('p5.prototype.createColorPicker', function() {
1033
+ let myp5;
1034
+ let testElement;
1035
+
1036
+ setup(function(done) {
1037
+ new p5(function(p) {
1038
+ p.setup = function() {
1039
+ myp5 = p;
1040
+ done();
1041
+ };
1042
+ });
1043
+ });
1044
+
1045
+ teardown(function() {
1046
+ myp5.remove();
1047
+ if (testElement && testElement.parentNode) {
1048
+ testElement.parentNode.removeChild(testElement);
1049
+ }
1050
+ testElement = null;
1051
+ });
1052
+
1053
+ test('should be a function', function() {
1054
+ assert.isFunction(myp5.createColorPicker);
1055
+ });
1056
+
1057
+ test('should return p5.Element of input[color] type', function() {
1058
+ testElement = myp5.createColorPicker();
1059
+
1060
+ assert.instanceOf(testElement, p5.Element);
1061
+ assert.instanceOf(testElement.elt, HTMLInputElement);
1062
+ assert.deepEqual(testElement.elt.type, 'color');
1063
+ });
1064
+
1065
+ test('should accept a p5.Color as param', function() {
1066
+ const testColor = myp5.color('red');
1067
+ testElement = myp5.createColorPicker(testColor);
1068
+
1069
+ assert.deepEqual(testElement.elt.value, testColor.toString('#rrggbb'));
1070
+ });
1071
+
1072
+ test('should accept a string as param', function() {
1073
+ const testColorString = '#f00f00';
1074
+ testElement = myp5.createColorPicker(testColorString);
1075
+ assert.deepEqual(testElement.elt.value, testColorString);
1076
+ });
1077
+
1078
+ test('calling color() should return the current color as p5.color', function() {
1079
+ const testColorString = 'red';
1080
+ const testColor = myp5.color(testColorString);
1081
+ testElement = myp5.createColorPicker(testColorString);
1082
+ assert.deepEqual(testElement.color(), testColor);
1083
+ });
1084
+
1085
+ test('calling value() should return hex string of color', function() {
1086
+ const testColor = myp5.color('aqua');
1087
+ testElement = myp5.createColorPicker(testColor);
1088
+ assert.deepEqual(testElement.value(), testColor.toString('#rrggbb'));
1089
+ });
1090
+ });
1091
+
1092
+ suite('p5.prototype.createInput', function() {
1093
+ let myp5;
1094
+ let testElement;
1095
+
1096
+ setup(function(done) {
1097
+ new p5(function(p) {
1098
+ p.setup = function() {
1099
+ myp5 = p;
1100
+ done();
1101
+ };
1102
+ });
1103
+ });
1104
+
1105
+ teardown(function() {
1106
+ myp5.remove();
1107
+ if (testElement && testElement.parentNode) {
1108
+ testElement.parentNode.removeChild(testElement);
1109
+ }
1110
+ testElement = null;
1111
+ });
1112
+
1113
+ test('should be a function', function() {
1114
+ assert.isFunction(myp5.createInput);
1115
+ });
1116
+
1117
+ test('should return p5.Element of input type', function() {
1118
+ testElement = myp5.createInput();
1119
+ assert.instanceOf(testElement, p5.Element);
1120
+ assert.instanceOf(testElement.elt, HTMLInputElement);
1121
+ });
1122
+
1123
+ test('should set given value as input', function() {
1124
+ const testValues = ['123', '', 'Hello world'];
1125
+ for (const value of testValues) {
1126
+ testElement = myp5.createInput(value);
1127
+ assert.deepEqual(testElement.elt.value, value);
1128
+ }
1129
+ });
1130
+
1131
+ test('should create input of given type and value', function() {
1132
+ const testType = 'password';
1133
+ const testValue = '1234056789';
1134
+ testElement = myp5.createInput(testValue, testType);
1135
+ assert.deepEqual(testElement.elt.type, testType);
1136
+ assert.deepEqual(testElement.elt.value, testValue);
1137
+ });
1138
+ });
1139
+
1140
+ suite('p5.prototype.createFileInput', function() {
1141
+ if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
1142
+ throw Error(
1143
+ 'File API not supported in test environment. Cannot run tests'
1144
+ );
1145
+ }
1146
+
1147
+ let myp5;
1148
+ let testElement;
1149
+
1150
+ setup(function(done) {
1151
+ new p5(function(p) {
1152
+ p.setup = function() {
1153
+ myp5 = p;
1154
+ done();
1155
+ };
1156
+ });
1157
+ });
1158
+
1159
+ teardown(function() {
1160
+ if (testElement && testElement.parentNode) {
1161
+ testElement.parentNode.removeChild(testElement);
1162
+ }
1163
+ testElement = null;
1164
+ myp5.remove();
1165
+ });
1166
+
1167
+ const emptyCallback = () => {};
1168
+ const createDummyFile = filename => {
1169
+ return new File(['testFileBlob'], filename, {
1170
+ type: 'text/plain'
1171
+ });
1172
+ };
1173
+
1174
+ test('should be a function', function() {
1175
+ assert.isFunction(myp5.createFileInput);
1176
+ });
1177
+
1178
+ test('should return input of file input', function() {
1179
+ testElement = myp5.createFileInput(emptyCallback);
1180
+ assert.instanceOf(testElement, p5.Element);
1181
+ assert.instanceOf(testElement.elt, HTMLInputElement);
1182
+ assert.deepEqual(testElement.elt.type, 'file');
1183
+ });
1184
+
1185
+ testSketchWithPromise(
1186
+ 'should trigger callback on input change event',
1187
+ function(sketch, resolve, reject) {
1188
+ sketch.setup = function() {
1189
+ testElement = myp5.createFileInput(resolve);
1190
+ const testFile = createDummyFile('file');
1191
+ testElement.files = testFile;
1192
+
1193
+ const mockedEvent = new Event('change');
1194
+ const mockedDataTransfer = new DataTransfer();
1195
+ mockedDataTransfer.items.add(testFile);
1196
+ testElement.elt.files = mockedDataTransfer.files;
1197
+ testElement.elt.dispatchEvent(mockedEvent);
1198
+ };
1199
+ }
1200
+ );
1201
+
1202
+ test('should accept multiple files if specified', function() {
1203
+ testElement = myp5.createFileInput(emptyCallback, true);
1204
+ assert.isTrue(testElement.elt.multiple);
1205
+ });
1206
+
1207
+ testSketchWithPromise(
1208
+ 'should trigger callback for each file if multiple files are given',
1209
+ function(sketch, resolve, reject) {
1210
+ sketch.setup = function() {
1211
+ let totalTriggers = 0;
1212
+ let filesCount = 7;
1213
+
1214
+ const handleFiles = event => {
1215
+ totalTriggers += 1;
1216
+ if (totalTriggers === filesCount) resolve();
1217
+ };
1218
+
1219
+ const mockedEvent = new Event('change');
1220
+ const mockedDataTransfer = new DataTransfer();
1221
+ for (let i = 0; i < filesCount; i += 1) {
1222
+ mockedDataTransfer.items.add(createDummyFile(i.toString()));
1223
+ }
1224
+
1225
+ testElement = myp5.createFileInput(handleFiles, true);
1226
+ testElement.elt.files = mockedDataTransfer.files;
1227
+ testElement.elt.dispatchEvent(mockedEvent);
1228
+ };
1229
+ }
1230
+ );
1231
+ });
1232
+
1233
+ suite('p5.prototype.createVideo', function() {
1234
+ let myp5;
1235
+ let testElement;
1236
+
1237
+ setup(function(done) {
1238
+ new p5(function(p) {
1239
+ p.setup = function() {
1240
+ myp5 = p;
1241
+ done();
1242
+ };
1243
+ });
1244
+ });
1245
+
1246
+ teardown(function() {
1247
+ myp5.remove();
1248
+ if (testElement && testElement.parentNode) {
1249
+ testElement.parentNode.removeChild(testElement);
1250
+ testElement = null;
1251
+ }
1252
+ });
1253
+
1254
+ const mediaSources = [
1255
+ '/test/unit/assets/nyan_cat.gif',
1256
+ '/test/unit/assets/target.gif'
1257
+ ];
1258
+
1259
+ test('should be a function', function() {
1260
+ assert.isFunction(myp5.createVideo);
1261
+ });
1262
+
1263
+ test('should return p5.Element of HTMLVideoElement', function() {
1264
+ testElement = myp5.createVideo('');
1265
+ assert.instanceOf(testElement, p5.MediaElement);
1266
+ assert.instanceOf(testElement.elt, HTMLVideoElement);
1267
+ });
1268
+
1269
+ test('should accept a singular media source', function() {
1270
+ const mediaSource = mediaSources[0];
1271
+ testElement = myp5.createVideo(mediaSource);
1272
+ const sourceEl = testElement.elt.children[0];
1273
+
1274
+ assert.deepEqual(testElement.elt.childElementCount, 1);
1275
+ assert.instanceOf(sourceEl, HTMLSourceElement);
1276
+ assert.isTrue(sourceEl.src.endsWith(mediaSource));
1277
+ });
1278
+
1279
+ test('should accept multiple media sources', function() {
1280
+ testElement = myp5.createVideo(mediaSources);
1281
+
1282
+ assert.deepEqual(testElement.elt.childElementCount, mediaSources.length);
1283
+ for (let index = 0; index < mediaSources.length; index += 1) {
1284
+ const sourceEl = testElement.elt.children[index];
1285
+ assert.instanceOf(sourceEl, HTMLSourceElement);
1286
+ assert.isTrue(sourceEl.src.endsWith(mediaSources[index]));
1287
+ }
1288
+ });
1289
+
1290
+ testSketchWithPromise(
1291
+ 'should trigger callback on canplaythrough event',
1292
+ function(sketch, resolve, reject) {
1293
+ sketch.setup = function() {
1294
+ testElement = myp5.createVideo(mediaSources, resolve);
1295
+ testElement.elt.dispatchEvent(new Event('canplaythrough'));
1296
+ };
1297
+ }
1298
+ );
1299
+
1300
+ test('should work with tint()', function(done) {
1301
+ const imgElt = myp5.createImg('/test/unit/assets/cat.jpg', '');
1302
+ testElement = myp5.createVideo('/test/unit/assets/cat.webm', () => {
1303
+ // Workaround for headless tests, where the video data isn't loading
1304
+ // correctly: mock the video element using an image for this test
1305
+ const prevElt = testElement.elt;
1306
+ testElement.elt = imgElt.elt;
1307
+
1308
+ myp5.background(255);
1309
+ myp5.tint(255, 0, 0);
1310
+ myp5.image(testElement, 0, 0);
1311
+
1312
+ testElement.elt = prevElt;
1313
+ imgElt.remove();
1314
+
1315
+ myp5.loadPixels();
1316
+ testElement.loadPixels();
1317
+ assert.equal(myp5.pixels[0], testElement.pixels[0]);
1318
+ assert.equal(myp5.pixels[1], 0);
1319
+ assert.equal(myp5.pixels[2], 0);
1320
+ done();
1321
+ });
1322
+ });
1323
+
1324
+ test('should work with updatePixels()', function(done) {
1325
+ let loaded = false;
1326
+ let prevElt;
1327
+ const imgElt = myp5.createImg('/test/unit/assets/cat.jpg', '');
1328
+ testElement = myp5.createVideo('/test/unit/assets/cat.webm', () => {
1329
+ loaded = true;
1330
+ // Workaround for headless tests, where the video data isn't loading
1331
+ // correctly: mock the video element using an image for this test
1332
+ prevElt = testElement.elt;
1333
+ testElement.elt = imgElt.elt;
1334
+ });
1335
+
1336
+ let drewUpdatedPixels = false;
1337
+ myp5.draw = function() {
1338
+ if (!loaded) return;
1339
+ myp5.background(255);
1340
+
1341
+ if (!drewUpdatedPixels) {
1342
+ // First, update pixels and check that it draws the updated
1343
+ // pixels correctly
1344
+ testElement.loadPixels();
1345
+ for (let i = 0; i < testElement.pixels.length; i += 4) {
1346
+ // Set every pixel to red
1347
+ testElement.pixels[i] = 255;
1348
+ testElement.pixels[i + 1] = 0;
1349
+ testElement.pixels[i + 2] = 0;
1350
+ testElement.pixels[i + 3] = 255;
1351
+ }
1352
+ testElement.updatePixels();
1353
+ myp5.image(testElement, 0, 0);
1354
+
1355
+ // The element should have drawn using the updated red pixels
1356
+ myp5.loadPixels();
1357
+ assert.deepEqual([...myp5.pixels.slice(0, 4)], [255, 0, 0, 255]);
1358
+
1359
+ // Mark that we've done the first check so we can see whether
1360
+ // the video still updates on the next frame
1361
+ drewUpdatedPixels = true;
1362
+ } else {
1363
+ // Next, make sure it still updates with the real pixels from
1364
+ // the next frame of the video on the next frame of animation
1365
+ myp5.image(testElement, 0, 0);
1366
+
1367
+ myp5.loadPixels();
1368
+ testElement.loadPixels();
1369
+ expect([...testElement.pixels.slice(0, 4)])
1370
+ .to.not.deep.equal([255, 0, 0, 255]);
1371
+ assert.deepEqual(
1372
+ [...myp5.pixels.slice(0, 4)],
1373
+ [...testElement.pixels.slice(0, 4)]
1374
+ );
1375
+ testElement.elt = prevElt;
1376
+ imgElt.remove();
1377
+ done();
1378
+ }
1379
+ };
1380
+ });
1381
+ });
1382
+
1383
+ suite('p5.prototype.createAudio', function() {
1384
+ let myp5;
1385
+ let testElement;
1386
+
1387
+ setup(function(done) {
1388
+ new p5(function(p) {
1389
+ p.setup = function() {
1390
+ myp5 = p;
1391
+ done();
1392
+ };
1393
+ });
1394
+ });
1395
+
1396
+ teardown(function() {
1397
+ myp5.remove();
1398
+ if (testElement && testElement.parentNode) {
1399
+ testElement.parentNode.removeChild(testElement);
1400
+ testElement = null;
1401
+ }
1402
+ });
1403
+
1404
+ const mediaSources = [
1405
+ '/test/unit/assets/beat.mp3',
1406
+ '/test/unit/assets/beat.mp3'
1407
+ ];
1408
+
1409
+ test('should be a function', function() {
1410
+ assert.isFunction(myp5.createAudio);
1411
+ });
1412
+
1413
+ test('should return p5.Element of HTMLAudioElement', function() {
1414
+ testElement = myp5.createAudio('');
1415
+ assert.instanceOf(testElement, p5.MediaElement);
1416
+ assert.instanceOf(testElement.elt, HTMLAudioElement);
1417
+ });
1418
+
1419
+ test('should accept a singular media source', function() {
1420
+ const mediaSource = mediaSources[0];
1421
+ testElement = myp5.createAudio(mediaSource);
1422
+ const sourceEl = testElement.elt.children[0];
1423
+
1424
+ assert.deepEqual(testElement.elt.childElementCount, 1);
1425
+ assert.instanceOf(sourceEl, HTMLSourceElement);
1426
+ assert.isTrue(sourceEl.src.endsWith(mediaSource));
1427
+ });
1428
+
1429
+ test('should accept multiple media sources', function() {
1430
+ testElement = myp5.createAudio(mediaSources);
1431
+
1432
+ assert.deepEqual(testElement.elt.childElementCount, mediaSources.length);
1433
+ for (let index = 0; index < mediaSources.length; index += 1) {
1434
+ const sourceEl = testElement.elt.children[index];
1435
+ assert.instanceOf(sourceEl, HTMLSourceElement);
1436
+ assert.isTrue(sourceEl.src.endsWith(mediaSources[index]));
1437
+ }
1438
+ });
1439
+
1440
+ testSketchWithPromise(
1441
+ 'should trigger callback on canplaythrough event',
1442
+ function(sketch, resolve, reject) {
1443
+ sketch.setup = function() {
1444
+ testElement = myp5.createAudio(mediaSources, resolve);
1445
+ testElement.elt.dispatchEvent(new Event('canplaythrough'));
1446
+ };
1447
+ }
1448
+ );
1449
+ });
1450
+
1451
+ suite('p5.prototype.createCapture', function() {
1452
+ // to run these tests, getUserMedia is required to be supported
1453
+ if (!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia)) {
1454
+ throw Error(
1455
+ 'Cannot run tests as getUserMedia not supported in this browser'
1456
+ );
1457
+ }
1458
+
1459
+ let myp5;
1460
+ let testElement;
1461
+
1462
+ setup(function(done) {
1463
+ new p5(function(p) {
1464
+ p.setup = function() {
1465
+ myp5 = p;
1466
+ done();
1467
+ };
1468
+ });
1469
+ });
1470
+
1471
+ teardown(function() {
1472
+ if (testElement && testElement.parentNode) {
1473
+ testElement.parentNode.removeChild(testElement);
1474
+ }
1475
+ testElement = null;
1476
+ myp5.remove();
1477
+ });
1478
+
1479
+ test('should be a function', function() {
1480
+ assert.isFunction(myp5.createCapture);
1481
+ });
1482
+
1483
+ test('should return p5.Element of video type', function() {
1484
+ testElement = myp5.createCapture(myp5.VIDEO);
1485
+ assert.instanceOf(testElement, p5.Element);
1486
+ assert.instanceOf(testElement.elt, HTMLVideoElement);
1487
+ });
1488
+
1489
+ test('should throw error if getUserMedia is not supported', function() {
1490
+ // Remove getUserMedia method and test
1491
+ const backup = navigator.mediaDevices.getUserMedia;
1492
+ navigator.mediaDevices.getUserMedia = undefined;
1493
+ try {
1494
+ testElement = myp5.createCapture(myp5.VIDEO);
1495
+ assert.fail();
1496
+ } catch (error) {
1497
+ assert.instanceOf(error, DOMException);
1498
+ }
1499
+
1500
+ // Restore backup, very important.
1501
+ navigator.mediaDevices.getUserMedia = backup;
1502
+ });
1503
+
1504
+ testSketchWithPromise(
1505
+ 'triggers the callback after loading metadata',
1506
+ function(sketch, resolve, reject) {
1507
+ sketch.setup = function() {
1508
+ testElement = myp5.createCapture(myp5.VIDEO, resolve);
1509
+ const mockedEvent = new Event('loadedmetadata');
1510
+ testElement.elt.dispatchEvent(mockedEvent);
1511
+ };
1512
+ }
1513
+ );
1514
+
1515
+ // Required for ios 11 devices
1516
+ test('should have playsinline attribute to empty string on DOM element', function() {
1517
+ testElement = myp5.createCapture(myp5.VIDEO);
1518
+ console.log(testElement.elt);
1519
+ // Weird check, setter accepts : playinline, getter accepts playInline
1520
+ assert.isTrue(testElement.elt.playsInline);
1521
+ });
1522
+ });
1523
+
1524
+ suite('p5.prototype.createElement', function() {
1525
+ let myp5;
1526
+ let testElement;
1527
+
1528
+ setup(function(done) {
1529
+ new p5(function(p) {
1530
+ p.setup = function() {
1531
+ myp5 = p;
1532
+ done();
1533
+ };
1534
+ });
1535
+ });
1536
+
1537
+ teardown(function() {
1538
+ myp5.remove();
1539
+ if (testElement && testElement.parentNode) {
1540
+ testElement.parentNode.removeChild(testElement);
1541
+ testElement = null;
1542
+ }
1543
+ });
1544
+
1545
+ const testData = {
1546
+ div: HTMLDivElement,
1547
+ p: HTMLParagraphElement,
1548
+ button: HTMLButtonElement,
1549
+ input: HTMLInputElement,
1550
+ video: HTMLVideoElement
1551
+ };
1552
+
1553
+ test('should be a function', function() {
1554
+ assert.isFunction(myp5.createElement);
1555
+ });
1556
+
1557
+ test('should return a p5.Element of appropriate type', function() {
1558
+ for (const [tag, domElName] of Object.entries(testData)) {
1559
+ testElement = myp5.createElement(tag);
1560
+ assert.instanceOf(testElement, p5.Element);
1561
+ assert.instanceOf(testElement.elt, domElName);
1562
+ }
1563
+ });
1564
+
1565
+ test('should set given content as innerHTML', function() {
1566
+ const testContent = 'Lorem ipsum';
1567
+ testElement = myp5.createElement('div', testContent);
1568
+ assert.deepEqual(testElement.elt.innerHTML, testContent);
1569
+ });
1570
+ });
1571
+
1572
+ // p5.Element.prototype.addClass
1573
+ suite('p5.Element.prototype.addClass', function() {
1574
+ let myp5;
1575
+ let testElement;
1576
+
1577
+ setup(function(done) {
1578
+ new p5(function(p) {
1579
+ p.setup = function() {
1580
+ myp5 = p;
1581
+ done();
1582
+ };
1583
+ });
1584
+ });
1585
+
1586
+ teardown(function() {
1587
+ myp5.remove();
1588
+ if (testElement && testElement.parentNode) {
1589
+ testElement.parentNode.removeChild(testElement);
1590
+ }
1591
+ testElement = null;
1592
+ });
1593
+
1594
+ test('should be a function', function() {
1595
+ // Create any p5.Element
1596
+ testElement = myp5.createElement('div');
1597
+ assert.isFunction(testElement.addClass);
1598
+ });
1599
+
1600
+ test('should add provided string to class names', function() {
1601
+ const testClassName = 'jumbotron';
1602
+ testElement = myp5.createElement('div');
1603
+ testElement.addClass(testClassName);
1604
+ assert.deepEqual(testElement.elt.className, testClassName);
1605
+ });
1606
+
1607
+ test('should not add class name, if already exists', function() {
1608
+ const testClassName1 = 'jumbotron';
1609
+ const testClassName2 = 'container-fluid';
1610
+ const expectedClassName = testClassName1 + ' ' + testClassName2;
1611
+
1612
+ testElement = myp5.createElement('div');
1613
+ testElement.addClass(testClassName1);
1614
+ testElement.addClass(testClassName2);
1615
+
1616
+ // Should not add the class name again
1617
+ testElement.addClass(testClassName1);
1618
+ assert.deepEqual(testElement.elt.className, expectedClassName);
1619
+ });
1620
+ });
1621
+
1622
+ // p5.Element.prototype.removeClass
1623
+ suite('p5.Element.prototype.removeClass', function() {
1624
+ let myp5;
1625
+ let testElement;
1626
+
1627
+ setup(function(done) {
1628
+ new p5(function(p) {
1629
+ p.setup = function() {
1630
+ myp5 = p;
1631
+ done();
1632
+ };
1633
+ });
1634
+ });
1635
+
1636
+ teardown(function() {
1637
+ myp5.remove();
1638
+ if (testElement && testElement.parentNode) {
1639
+ testElement.parentNode.removeChild(testElement);
1640
+ }
1641
+ testElement = null;
1642
+ });
1643
+
1644
+ test('should be a function', function() {
1645
+ // Create any p5.Element
1646
+ testElement = myp5.createElement('div');
1647
+ assert.isFunction(testElement.removeClass);
1648
+ });
1649
+
1650
+ test('should remove provided string from class names', function() {
1651
+ const defaultClassNames = 'col-md-9 col-sm-12';
1652
+ const testClassName = 'jumbotron';
1653
+
1654
+ testElement = myp5.createElement('div');
1655
+ testElement.addClass(defaultClassNames);
1656
+ testElement.addClass(testClassName);
1657
+
1658
+ // Removing a class name
1659
+ testElement.removeClass(testClassName);
1660
+ assert.deepEqual(testElement.elt.className, defaultClassNames);
1661
+ });
1662
+
1663
+ test('should not throw error if class name not exists', function() {
1664
+ const testClassName1 = 'jumbotron';
1665
+ const testClassName2 = 'container-fluid';
1666
+
1667
+ testElement = myp5.createElement('div');
1668
+ testElement.addClass(testClassName1);
1669
+
1670
+ // Handling the curse of 'this'
1671
+ testElement.removeClass = testElement.removeClass.bind(testElement);
1672
+ assert.doesNotThrow(testElement.removeClass, testClassName2);
1673
+ assert.deepEqual(testElement.elt.className, testClassName1);
1674
+ });
1675
+ });
1676
+
1677
+ // p5.Element.prototype.hasClass
1678
+ suite('p5.Element.prototype.hasClass', function() {
1679
+ let myp5;
1680
+ let testElement;
1681
+
1682
+ setup(function(done) {
1683
+ new p5(function(p) {
1684
+ p.setup = function() {
1685
+ myp5 = p;
1686
+ done();
1687
+ };
1688
+ });
1689
+ });
1690
+
1691
+ teardown(function() {
1692
+ myp5.remove();
1693
+ if (testElement && testElement.parentNode) {
1694
+ testElement.parentNode.removeChild(testElement);
1695
+ }
1696
+ testElement = null;
1697
+ });
1698
+
1699
+ test('should be a function', function() {
1700
+ // Create any p5.Element
1701
+ testElement = myp5.createElement('div');
1702
+ assert.isFunction(testElement.hasClass);
1703
+ });
1704
+
1705
+ test('should return true for existing class name', function() {
1706
+ const defaultClassNames = 'col-md-9 jumbotron';
1707
+ const testClassName = 'jumbotron';
1708
+
1709
+ testElement = myp5.createElement('div');
1710
+ testElement.addClass(defaultClassNames);
1711
+
1712
+ assert.isTrue(testElement.hasClass(testClassName));
1713
+ });
1714
+
1715
+ test('should return false for non-existing class name', function() {
1716
+ const defaultClassNames = 'col-md-9 jumbotron';
1717
+ const testClassName = 'container-fluid';
1718
+
1719
+ testElement = myp5.createElement('div');
1720
+ testElement.addClass(defaultClassNames);
1721
+
1722
+ assert.isFalse(testElement.hasClass(testClassName));
1723
+ });
1724
+ });
1725
+
1726
+ // p5.Element.prototype.toggleClass
1727
+ suite('p5.Element.prototype.toggleClass', function() {
1728
+ let myp5;
1729
+ let testElement;
1730
+
1731
+ setup(function(done) {
1732
+ new p5(function(p) {
1733
+ p.setup = function() {
1734
+ myp5 = p;
1735
+ done();
1736
+ };
1737
+ });
1738
+ });
1739
+
1740
+ teardown(function() {
1741
+ myp5.remove();
1742
+ if (testElement && testElement.parentNode) {
1743
+ testElement.parentNode.removeChild(testElement);
1744
+ }
1745
+ testElement = null;
1746
+ });
1747
+
1748
+ test('should be a function', function() {
1749
+ // Create any p5.Element
1750
+ testElement = myp5.createElement('div');
1751
+ assert.isFunction(testElement.toggleClass);
1752
+ });
1753
+
1754
+ test('should remove an existing class name', function() {
1755
+ const defaultClassName = 'container-fluid';
1756
+ const testClassName = 'jumbotron';
1757
+
1758
+ testElement = myp5.createElement('div');
1759
+ testElement.addClass(defaultClassName);
1760
+ testElement.addClass(testClassName);
1761
+
1762
+ testElement.toggleClass(testClassName);
1763
+ assert.deepEqual(testElement.elt.className, defaultClassName);
1764
+ });
1765
+
1766
+ test('should add an non-existing class name', function() {
1767
+ const defaultClassName = 'container-fluid';
1768
+ const testClassName = 'jumbotron';
1769
+
1770
+ testElement = myp5.createElement('div');
1771
+ testElement.addClass(defaultClassName);
1772
+
1773
+ testElement.toggleClass(testClassName);
1774
+ assert.deepEqual(
1775
+ testElement.elt.className,
1776
+ defaultClassName + ' ' + testClassName
1777
+ );
1778
+ });
1779
+ });
1780
+
1781
+ // p5.Element.prototype.child
1782
+ suite('p5.Element.prototype.child', function() {
1783
+ let myp5;
1784
+ let testElement;
1785
+
1786
+ setup(function(done) {
1787
+ new p5(function(p) {
1788
+ p.setup = function() {
1789
+ myp5 = p;
1790
+ done();
1791
+ };
1792
+ });
1793
+ });
1794
+
1795
+ teardown(function() {
1796
+ myp5.remove();
1797
+ if (testElement && testElement.parentNode) {
1798
+ testElement.parentNode.removeChild(testElement);
1799
+ }
1800
+ testElement = null;
1801
+ });
1802
+
1803
+ test('should be a function', function() {
1804
+ testElement = myp5.createElement('div');
1805
+ assert.isFunction(testElement.child);
1806
+ });
1807
+
1808
+ test('should return all child nodes by default', function() {
1809
+ testElement = myp5.createElement('div');
1810
+ const childElement = myp5.createElement('p');
1811
+
1812
+ // Add child element by using DOM API
1813
+ testElement.elt.appendChild(childElement.elt);
1814
+
1815
+ const childNodes = testElement.child();
1816
+ assert.deepEqual(childNodes.length, testElement.elt.childElementCount);
1817
+ childNodes.forEach((childElement, index) => {
1818
+ const domChild = testElement.elt.children[index];
1819
+ assert.deepEqual(childElement, domChild);
1820
+ });
1821
+ });
1822
+
1823
+ test('should append p5 element as child', function() {
1824
+ testElement = myp5.createElement('div');
1825
+ const childElement = myp5.createElement('p');
1826
+
1827
+ testElement.child(childElement);
1828
+ const childNodes = Array.from(testElement.elt.children);
1829
+ assert.isTrue(childNodes.includes(childElement.elt));
1830
+ });
1831
+
1832
+ test('should append dom element as child', function() {
1833
+ testElement = myp5.createElement('div');
1834
+ const childElement = myp5.createElement('p');
1835
+
1836
+ testElement.child(childElement.elt);
1837
+ const childNodes = Array.from(testElement.elt.children);
1838
+ assert.isTrue(childNodes.includes(childElement.elt));
1839
+ });
1840
+
1841
+ test('should append element as child from a given id', function() {
1842
+ testElement = myp5.createElement('div');
1843
+ const childId = 'testChildElement';
1844
+ const childElement = myp5.createElement('p');
1845
+ childElement.id(childId);
1846
+
1847
+ testElement.child(childId);
1848
+ const childNodes = Array.from(testElement.elt.children);
1849
+ assert.isTrue(childNodes.includes(childElement.elt));
1850
+ });
1851
+
1852
+ test('should not throw error if mathcing element is not found from a given id', function() {
1853
+ testElement = myp5.createElement('div');
1854
+ const randomChildId = 'testChildElement';
1855
+ expect(() => testElement.child(randomChildId)).to.not.throw();
1856
+ });
1857
+ });
1858
+
1859
+ // p5.Element.prototype.center
1860
+ suite('p5.Element.prototype.center', function() {
1861
+ let myp5;
1862
+ let testElement;
1863
+
1864
+ setup(function(done) {
1865
+ new p5(function(p) {
1866
+ p.setup = function() {
1867
+ myp5 = p;
1868
+ done();
1869
+ };
1870
+ });
1871
+ });
1872
+
1873
+ teardown(function() {
1874
+ myp5.remove();
1875
+ if (testElement && testElement.parentNode) {
1876
+ testElement.parentNode.removeChild(testElement);
1877
+ }
1878
+ testElement = null;
1879
+ });
1880
+
1881
+ test('should be a function', function() {
1882
+ testElement = myp5.createElement('div');
1883
+ assert.isFunction(testElement.center);
1884
+ });
1885
+
1886
+ // test('should center an element horizontally', function() {
1887
+ // // center doesn't work.
1888
+ // });
1889
+
1890
+ // test('should center an element vertically', function() {
1891
+ // // center doesn't work.
1892
+ // });
1893
+
1894
+ // test('should center an element horizontally and vertically', function() {
1895
+ // // center doesn't work.
1896
+ // });
1897
+ });
1898
+
1899
+ // p5.Element.prototype.html
1900
+ suite('p5.Element.prototype.html', function() {
1901
+ let myp5;
1902
+ let testElement;
1903
+
1904
+ setup(function(done) {
1905
+ new p5(function(p) {
1906
+ p.setup = function() {
1907
+ myp5 = p;
1908
+ done();
1909
+ };
1910
+ });
1911
+ });
1912
+
1913
+ teardown(function() {
1914
+ myp5.remove();
1915
+ if (testElement && testElement.parentNode) {
1916
+ testElement.parentNode.removeChild(testElement);
1917
+ }
1918
+ testElement = null;
1919
+ });
1920
+
1921
+ test('should be a function', function() {
1922
+ // Create any p5.Element
1923
+ testElement = myp5.createElement('a');
1924
+ assert.isFunction(testElement.position);
1925
+ });
1926
+
1927
+ test('should return the inner HTML of element if no argument is given', function() {
1928
+ testElement = myp5.createElement('div');
1929
+ const testHTML = '<p>Hello World</p>';
1930
+
1931
+ testElement.elt.innerHTML = testHTML;
1932
+ assert.deepEqual(testElement.html(), testHTML);
1933
+ });
1934
+
1935
+ test('should replace the inner HTML of element', function() {
1936
+ testElement = myp5.createElement('div');
1937
+ const initialtestHTML = '<p>Hello World</p>';
1938
+ const modifiedtestHTML = '<p>Hello World !!!</p>';
1939
+
1940
+ testElement.html(initialtestHTML);
1941
+ assert.deepEqual(testElement.elt.innerHTML, initialtestHTML);
1942
+
1943
+ testElement.html(modifiedtestHTML);
1944
+ assert.deepEqual(testElement.elt.innerHTML, modifiedtestHTML);
1945
+ });
1946
+
1947
+ test('should append to the inner HTML if second param is true', function() {
1948
+ testElement = myp5.createElement('div');
1949
+ const testHTML1 = '<p>Hello World</p>';
1950
+ const testHTML2 = '<p>Hello World !!!</p>';
1951
+
1952
+ testElement.html(testHTML1);
1953
+ assert.deepEqual(testElement.elt.innerHTML, testHTML1);
1954
+
1955
+ testElement.html(testHTML2, true);
1956
+ assert.deepEqual(testElement.elt.innerHTML, testHTML1 + testHTML2);
1957
+ });
1958
+
1959
+ test('should replace the inner HTML if second param is false', function() {
1960
+ testElement = myp5.createElement('div');
1961
+ const testHTML1 = '<p>Hello World</p>';
1962
+ const testHTML2 = '<p>Hello World !!!</p>';
1963
+
1964
+ testElement.html(testHTML1);
1965
+ assert.deepEqual(testElement.elt.innerHTML, testHTML1);
1966
+
1967
+ testElement.html(testHTML2, false);
1968
+ assert.deepEqual(testElement.elt.innerHTML, testHTML2);
1969
+ });
1970
+ });
1971
+
1972
+ // p5.Element.prototype.position
1973
+ suite('p5.Element.prototype.position', function() {
1974
+ let myp5;
1975
+ let testElement;
1976
+
1977
+ setup(function(done) {
1978
+ new p5(function(p) {
1979
+ p.setup = function() {
1980
+ myp5 = p;
1981
+ done();
1982
+ };
1983
+ });
1984
+ });
1985
+
1986
+ teardown(function() {
1987
+ myp5.remove();
1988
+ if (testElement && testElement.parentNode) {
1989
+ testElement.parentNode.removeChild(testElement);
1990
+ }
1991
+ testElement = null;
1992
+ });
1993
+
1994
+ test('should be a function', function() {
1995
+ // Create any p5.Element
1996
+ testElement = myp5.createElement('a');
1997
+ assert.isFunction(testElement.position);
1998
+ });
1999
+
2000
+ test('should return current position if no args are given', function() {
2001
+ testElement = myp5.createButton('testButton');
2002
+ const position = testElement.position();
2003
+ assert.deepEqual(position.x, testElement.elt.offsetLeft);
2004
+ assert.deepEqual(position.y, testElement.elt.offsetTop);
2005
+ });
2006
+
2007
+ test('should set default position as absolute', function() {
2008
+ testElement = myp5.createButton('testButton');
2009
+ testElement.position(20, 70);
2010
+ assert.deepEqual(testElement.elt.style.position, 'absolute');
2011
+ });
2012
+
2013
+ test('should set given params as properties', function() {
2014
+ let testElement = myp5.createButton('testButton');
2015
+ testElement.position(20, 80, 'static');
2016
+
2017
+ assert.deepEqual(testElement.elt.style.position, 'static');
2018
+ assert.deepEqual(testElement.elt.style.left, '20px');
2019
+ assert.deepEqual(testElement.elt.style.top, '80px');
2020
+ });
2021
+ });
2022
+
2023
+ // p5.Element.prototype._translate
2024
+
2025
+ // p5.Element.prototype._rotate
2026
+
2027
+ // p5.Element.prototype.style
2028
+
2029
+ // p5.Element.prototype.attribute
2030
+
2031
+ // p5.Element.prototype.removeAttribute
2032
+
2033
+ // p5.Element.prototype.value
2034
+
2035
+ // p5.Element.prototype.show
2036
+
2037
+ // p5.Element.prototype.hide
2038
+
2039
+ // p5.Element.prototype.size
2040
+
2041
+ // p5.Element.prototype.remove
2042
+
2043
+ suite('p5.prototype.drop', function() {
2044
+ testSketchWithPromise('drop fires multiple events', function(
2045
+ sketch,
2046
+ resolve,
2047
+ reject
2048
+ ) {
2049
+ let testElement;
2050
+ let fileFnCounter = 0;
2051
+ let eventFnCounter = 0;
2052
+ sketch.setup = function() {
2053
+ testElement = sketch.createDiv('Drop files inside');
2054
+
2055
+ // Setup test functions and constants
2056
+ const file1 = new File(['foo'], 'foo.txt', { type: 'text/plain' });
2057
+ const file2 = new File(['foo'], 'foo.txt', { type: 'text/plain' });
2058
+ const hasFinished = () => {
2059
+ if (fileFnCounter > 1 && eventFnCounter === 1) resolve();
2060
+ };
2061
+ const testFileFn = () => {
2062
+ fileFnCounter += 1;
2063
+ hasFinished();
2064
+ };
2065
+ const testEventFn = () => {
2066
+ eventFnCounter += 1;
2067
+ hasFinished();
2068
+ };
2069
+ testElement.drop(testFileFn, testEventFn);
2070
+
2071
+ // Fire a mock drop and test the method
2072
+ const mockedEvent = new Event('drop');
2073
+ mockedEvent.dataTransfer = { files: [file1, file2] };
2074
+ testElement.elt.dispatchEvent(mockedEvent);
2075
+ };
2076
+ });
2077
+ });
2078
+
2079
+ // p5.MediaElement
2080
+
2081
+ // p5.MediaElement.play
2082
+
2083
+ // p5.MediaElement.stop
2084
+
2085
+ // p5.MediaElement.pause
2086
+
2087
+ // p5.MediaElement.loop
2088
+
2089
+ // p5.MediaElement.noLoop
2090
+
2091
+ // p5.MediaElement.shouldAutoplay
2092
+
2093
+ // p5.MediaElement.autoplay
2094
+
2095
+ // p5.MediaElement.volume
2096
+
2097
+ // p5.MediaElement.speed
2098
+
2099
+ // p5.MediaElement.time
2100
+
2101
+ // p5.MediaElement.prototype.duration
2102
+
2103
+ // p5.MediaElement.prototype._ensureCanvas
2104
+
2105
+ // p5.MediaElement.prototype.loadPixels
2106
+
2107
+ // p5.MediaElement.prototype.updatePixels
2108
+
2109
+ // p5.MediaElement.prototype.get
2110
+
2111
+ // p5.MediaElement.prototype._getPixel
2112
+
2113
+ // p5.MediaElement.prototype.set
2114
+
2115
+ // p5.MediaElement.prototype.copy
2116
+
2117
+ // p5.MediaElement.prototype.mask
2118
+
2119
+ // p5.MediaElement.prototype.isModified
2120
+
2121
+ // p5.MediaElement.prototype.setModified
2122
+
2123
+ // p5.MediaElement.prototype.onended
2124
+
2125
+ // p5.MediaElement.prototype.connect
2126
+
2127
+ // p5.MediaElement.prototype.disconnect
2128
+
2129
+ // p5.MediaElement.prototype.showControls
2130
+
2131
+ // p5.MediaElement.prototype.hideControls
2132
+
2133
+ // p5.MediaElement.prototype.addCue
2134
+
2135
+ // p5.MediaElement.prototype.removeCue
2136
+
2137
+ // p5.MediaElement.prototype.clearCues
2138
+
2139
+ // p5.MediaElement.prototype._onTimeUpdate
2140
+
2141
+ // p5.File
2142
+
2143
+ // p5.File._createLoader
2144
+
2145
+ // p5.File._load
2146
+ });