From ec23bbfc1756999fc89bac04df45a91f2c55e34d Mon Sep 17 00:00:00 2001 From: romellem Date: Thu, 6 Aug 2020 15:08:29 -0500 Subject: [PATCH 01/33] Tests whitespace on template --- test/tests.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/tests.js b/test/tests.js index afbf4e0..d8e9ceb 100644 --- a/test/tests.js +++ b/test/tests.js @@ -75,6 +75,28 @@ describe('yamodal', function () { HTML(`${this.button_html}${template_result}`) ); }); + + it('should trim whitespace on templates', function () { + // Add whitespace before and after + let template_result = ` ${templates.basic()} `; + yamodal({ + template: function basic() { + return template_result; + }, + }); + let button = document.getElementById('button'); + button.click(); + + assert.notStrictEqual( + global.document.documentElement.outerHTML, + HTML(`${this.button_html}${template_result}`) + ); + + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(`${this.button_html}${template_result.trim()}`) + ); + }); }); describe('trigger selector', function () { From 522ef5d35a0a235190b9b702e63785acfdc5f476 Mon Sep 17 00:00:00 2001 From: romellem Date: Thu, 6 Aug 2020 15:31:40 -0500 Subject: [PATCH 02/33] Installs sinon --- package.json | 3 +- yarn.lock | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a459913..1a467e9 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,8 @@ "rollup-plugin-filesize": "^9.0.0", "rollup-plugin-livereload": "^1.0.4", "rollup-plugin-serve": "^1.0.1", - "rollup-plugin-terser": "^6.1.0" + "rollup-plugin-terser": "^6.1.0", + "sinon": "^9.0.2" }, "keywords": [ "modal", diff --git a/yarn.lock b/yarn.lock index b7c71ab..bb3367c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1217,6 +1217,42 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@sinonjs/commons@^1", "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.7.2": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217" + integrity sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^6.0.0", "@sinonjs/fake-timers@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" + integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@sinonjs/formatio@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-5.0.1.tgz#f13e713cb3313b1ab965901b01b0828ea6b77089" + integrity sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ== + dependencies: + "@sinonjs/commons" "^1" + "@sinonjs/samsam" "^5.0.2" + +"@sinonjs/samsam@^5.0.2", "@sinonjs/samsam@^5.0.3": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-5.0.3.tgz#86f21bdb3d52480faf0892a480c9906aa5a52938" + integrity sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ== + dependencies: + "@sinonjs/commons" "^1.6.0" + lodash.get "^4.4.2" + type-detect "^4.0.8" + +"@sinonjs/text-encoding@^0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" + integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -1892,7 +1928,7 @@ dezalgo@^1.0.0: asap "^2.0.0" wrappy "1" -diff@4.0.2: +diff@4.0.2, diff@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== @@ -2605,6 +2641,11 @@ is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" @@ -2818,6 +2859,11 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +just-extend@^4.0.2: + version "4.1.0" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.1.0.tgz#7278a4027d889601640ee0ce0e5a00b992467da4" + integrity sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA== + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -2881,6 +2927,11 @@ lodash.flattendeep@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -3114,6 +3165,17 @@ ms@2.1.2, ms@^2.0.0, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +nise@^4.0.1: + version "4.0.4" + resolved "https://registry.yarnpkg.com/nise/-/nise-4.0.4.tgz#d73dea3e5731e6561992b8f570be9e363c4512dd" + integrity sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A== + dependencies: + "@sinonjs/commons" "^1.7.0" + "@sinonjs/fake-timers" "^6.0.0" + "@sinonjs/text-encoding" "^0.7.1" + just-extend "^4.0.2" + path-to-regexp "^1.7.0" + node-gyp@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-6.1.0.tgz#64e31c61a4695ad304c1d5b82cf6b7c79cc79f3f" @@ -3481,6 +3543,13 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-to-regexp@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== + dependencies: + isarray "0.0.1" + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -3900,6 +3969,19 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== +sinon@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.0.2.tgz#b9017e24633f4b1c98dfb6e784a5f0509f5fd85d" + integrity sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A== + dependencies: + "@sinonjs/commons" "^1.7.2" + "@sinonjs/fake-timers" "^6.0.1" + "@sinonjs/formatio" "^5.0.1" + "@sinonjs/samsam" "^5.0.3" + diff "^4.0.2" + nise "^4.0.1" + supports-color "^7.1.0" + smart-buffer@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba" @@ -4225,6 +4307,11 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +type-detect@4.0.8, type-detect@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.8.0, type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" From 18024da4b1e8abf998bfd241964a2e3684b9abd1 Mon Sep 17 00:00:00 2001 From: romellem Date: Thu, 6 Aug 2020 15:32:39 -0500 Subject: [PATCH 03/33] Creates test block for onAppend --- test/tests.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/tests.js b/test/tests.js index d8e9ceb..fb4cb75 100644 --- a/test/tests.js +++ b/test/tests.js @@ -1,6 +1,7 @@ import yamodal from '../dist/umd/yamodal'; import assert from 'assert'; import jsdom from 'global-jsdom'; +import sinon from 'sinon'; import * as templates from './templates.js'; const DOCTYPE = ``; @@ -272,4 +273,45 @@ describe('yamodal', function () { } }); }); + + describe('onAppend callback', function () { + before(function () { + this.button_html = ``; + }); + + after(function () { + this.button_html = undefined; + }); + + beforeEach(function () { + this.spiedOnAppend = sinon.spy(function onAppend(modal_node, trigger_node, event) { + document.body.insertBefore(modal_node, document.body.firstChild); + }); + this.cleanup = jsdom(DOCTYPE + HTML(this.button_html)); + }); + + afterEach(function () { + sinon.restore(); + this.cleanup(); + }); + + it('should call `onAppend` with exactly three arguments', function () { + yamodal({ + template: templates.basic, + onAppend: this.spiedOnAppend, + }); + + let button = document.getElementById('button'); + button.click(); + + const window = document.defaultView; + let [modal_node, trigger_node, event, ...others] = this.spiedOnAppend.getCall(0).args; + + assert.ok(this.spiedOnAppend.calledOnce); + assert.ok(modal_node instanceof window.HTMLElement); + assert.ok(trigger_node instanceof window.HTMLElement); + assert.ok(event instanceof window.Event); + assert.strictEqual(others.length, 0); + }); + }); }); From 13ae948e5a24ac62013aeae6a8a685d477856ba0 Mon Sep 17 00:00:00 2001 From: romellem Date: Thu, 6 Aug 2020 15:45:26 -0500 Subject: [PATCH 04/33] Creates test block for beforeInsertIntoDom --- test/tests.js | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/test/tests.js b/test/tests.js index fb4cb75..dfcbf29 100644 --- a/test/tests.js +++ b/test/tests.js @@ -314,4 +314,64 @@ describe('yamodal', function () { assert.strictEqual(others.length, 0); }); }); + + describe('beforeInsertIntoDom callback', function () { + before(function () { + this.button_html = ``; + }); + + after(function () { + this.button_html = undefined; + }); + + beforeEach(function () { + this.cleanup = jsdom(DOCTYPE + HTML(this.button_html)); + }); + + afterEach(function () { + sinon.restore(); + this.cleanup(); + }); + + it('should call `beforeInsertIntoDom` with exactly three arguments', function () { + const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom(modal_node, trigger_node, event) { + // Do nothing + }); + yamodal({ + template: templates.basic, + beforeInsertIntoDom: spiedBeforeInsertIntoDom, + }); + + let button = document.getElementById('button'); + button.click(); + + const window = document.defaultView; + let [modal_node, trigger_node, event, ...others] = spiedBeforeInsertIntoDom.getCall(0).args; + + assert.ok(spiedBeforeInsertIntoDom.calledOnce); + assert.ok(modal_node instanceof window.HTMLElement); + assert.ok(trigger_node instanceof window.HTMLElement); + assert.ok(event instanceof window.Event); + assert.strictEqual(others.length, 0); + }); + + it('should not open the modal if `beforeInsertIntoDom` returns false', function () { + const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom(modal_node, trigger_node, event) { + return false; + }); + let modal = yamodal({ + template: templates.basic, + beforeInsertIntoDom: spiedBeforeInsertIntoDom, + }); + + let button = document.getElementById('button'); + button.click(); + + assert.strictEqual(modal.isOpen(), false); + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(this.button_html) + ); + }); + }); }); From df38f9db4bbd49c53f5c4a2eff71c4ec500a1870 Mon Sep 17 00:00:00 2001 From: romellem Date: Thu, 6 Aug 2020 15:59:20 -0500 Subject: [PATCH 05/33] Tests for strictly returning `false` --- test/tests.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/tests.js b/test/tests.js index dfcbf29..b79a062 100644 --- a/test/tests.js +++ b/test/tests.js @@ -373,5 +373,34 @@ describe('yamodal', function () { HTML(this.button_html) ); }); + + it('should still open the modal if `beforeInsertIntoDom` returns a falsy value different from `false`', function () { + // Not including `false` (obviously) and BigInt `0n` + const falsy_values = [0, null, undefined, NaN, '']; + for (let falsy_value of falsy_values) { + this.cleanup = jsdom(DOCTYPE + HTML(this.button_html)); + const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom(modal_node, trigger_node, event) { + return falsy_value; + }); + let template_result = templates.basic(); + let modal = yamodal({ + template: templates.basic, + beforeInsertIntoDom: spiedBeforeInsertIntoDom, + }); + + let button = document.getElementById('button'); + button.click(); + + // Still opens + assert.strictEqual(modal.isOpen(), true); + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(`${this.button_html}${template_result}`) + ); + + this.cleanup(); + sinon.restore(); + } + }); }); }); From d1333dc66cc1aca3a66a7429632782897bb3174a Mon Sep 17 00:00:00 2001 From: romellem Date: Thu, 6 Aug 2020 16:01:11 -0500 Subject: [PATCH 06/33] Checks that modal is closed first --- test/tests.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/tests.js b/test/tests.js index b79a062..50d9b1f 100644 --- a/test/tests.js +++ b/test/tests.js @@ -388,6 +388,7 @@ describe('yamodal', function () { beforeInsertIntoDom: spiedBeforeInsertIntoDom, }); + assert.strictEqual(modal.isOpen(), false); let button = document.getElementById('button'); button.click(); From 06473373c1eec8a2af9413c7982d0d21b8eb289e Mon Sep 17 00:00:00 2001 From: romellem Date: Thu, 6 Aug 2020 16:07:35 -0500 Subject: [PATCH 07/33] Creates test block for afterInsertIntoDom --- test/tests.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/tests.js b/test/tests.js index 50d9b1f..82d52d0 100644 --- a/test/tests.js +++ b/test/tests.js @@ -404,4 +404,45 @@ describe('yamodal', function () { } }); }); + + describe('afterInsertIntoDom callback', function () { + before(function () { + this.button_html = ``; + }); + + after(function () { + this.button_html = undefined; + }); + + beforeEach(function () { + this.spiedAfterInsertIntoDom = sinon.spy(function afterInsertIntoDom(modal_node, trigger_node, event) { + // Do nothing + }); + this.cleanup = jsdom(DOCTYPE + HTML(this.button_html)); + }); + + afterEach(function () { + sinon.restore(); + this.cleanup(); + }); + + it('should call `afterInsertIntoDom` with exactly three arguments', function () { + yamodal({ + template: templates.basic, + afterInsertIntoDom: this.spiedAfterInsertIntoDom, + }); + + let button = document.getElementById('button'); + button.click(); + + const window = document.defaultView; + let [modal_node, trigger_node, event, ...others] = this.spiedAfterInsertIntoDom.getCall(0).args; + + assert.ok(this.spiedAfterInsertIntoDom.calledOnce); + assert.ok(modal_node instanceof window.HTMLElement); + assert.ok(trigger_node instanceof window.HTMLElement); + assert.ok(event instanceof window.Event); + assert.strictEqual(others.length, 0); + }); + }); }); From 6c0b476e239adbe734d7ccf9522bb34a3ec5dd84 Mon Sep 17 00:00:00 2001 From: romellem Date: Fri, 21 Aug 2020 20:25:30 -0500 Subject: [PATCH 08/33] Adds some tests for the API --- test/tests.js | 194 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 180 insertions(+), 14 deletions(-) diff --git a/test/tests.js b/test/tests.js index 82d52d0..0cafb74 100644 --- a/test/tests.js +++ b/test/tests.js @@ -150,10 +150,7 @@ describe('yamodal', function () { button.click(); // It shouldn't open - assert.strictEqual( - global.document.documentElement.outerHTML, - HTML(`${button_html}`) - ); + assert.strictEqual(global.document.documentElement.outerHTML, HTML(`${button_html}`)); }); it('should use the function name for the trigger selector when defined', function () { @@ -334,7 +331,11 @@ describe('yamodal', function () { }); it('should call `beforeInsertIntoDom` with exactly three arguments', function () { - const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom(modal_node, trigger_node, event) { + const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( + modal_node, + trigger_node, + event + ) { // Do nothing }); yamodal({ @@ -346,7 +347,9 @@ describe('yamodal', function () { button.click(); const window = document.defaultView; - let [modal_node, trigger_node, event, ...others] = spiedBeforeInsertIntoDom.getCall(0).args; + let [modal_node, trigger_node, event, ...others] = spiedBeforeInsertIntoDom.getCall( + 0 + ).args; assert.ok(spiedBeforeInsertIntoDom.calledOnce); assert.ok(modal_node instanceof window.HTMLElement); @@ -356,7 +359,11 @@ describe('yamodal', function () { }); it('should not open the modal if `beforeInsertIntoDom` returns false', function () { - const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom(modal_node, trigger_node, event) { + const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( + modal_node, + trigger_node, + event + ) { return false; }); let modal = yamodal({ @@ -368,10 +375,7 @@ describe('yamodal', function () { button.click(); assert.strictEqual(modal.isOpen(), false); - assert.strictEqual( - global.document.documentElement.outerHTML, - HTML(this.button_html) - ); + assert.strictEqual(global.document.documentElement.outerHTML, HTML(this.button_html)); }); it('should still open the modal if `beforeInsertIntoDom` returns a falsy value different from `false`', function () { @@ -379,7 +383,11 @@ describe('yamodal', function () { const falsy_values = [0, null, undefined, NaN, '']; for (let falsy_value of falsy_values) { this.cleanup = jsdom(DOCTYPE + HTML(this.button_html)); - const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom(modal_node, trigger_node, event) { + const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( + modal_node, + trigger_node, + event + ) { return falsy_value; }); let template_result = templates.basic(); @@ -415,7 +423,11 @@ describe('yamodal', function () { }); beforeEach(function () { - this.spiedAfterInsertIntoDom = sinon.spy(function afterInsertIntoDom(modal_node, trigger_node, event) { + this.spiedAfterInsertIntoDom = sinon.spy(function afterInsertIntoDom( + modal_node, + trigger_node, + event + ) { // Do nothing }); this.cleanup = jsdom(DOCTYPE + HTML(this.button_html)); @@ -436,7 +448,9 @@ describe('yamodal', function () { button.click(); const window = document.defaultView; - let [modal_node, trigger_node, event, ...others] = this.spiedAfterInsertIntoDom.getCall(0).args; + let [modal_node, trigger_node, event, ...others] = this.spiedAfterInsertIntoDom.getCall( + 0 + ).args; assert.ok(this.spiedAfterInsertIntoDom.calledOnce); assert.ok(modal_node instanceof window.HTMLElement); @@ -445,4 +459,156 @@ describe('yamodal', function () { assert.strictEqual(others.length, 0); }); }); + + describe('API', function () { + describe('Return Object', function () { + beforeEach(function () { + this.cleanup = jsdom(DOCTYPE + HTML()); + }); + + afterEach(function () { + this.cleanup(); + }); + + it('`yamodal()` returns an object with all API elements', function () { + let modal = yamodal({ + template: templates.basic, + beforeInsertIntoDom: this.spiedBeforeInsertIntoDom, + }); + + let api_keys = Object.keys(modal); + + assert.strictEqual(api_keys.length, 5); + assert.ok(api_keys.includes('modal_node')); + assert.ok(api_keys.includes('open')); + assert.ok(api_keys.includes('close')); + assert.ok(api_keys.includes('isOpen')); + assert.ok(api_keys.includes('destroy')); + + const window = document.defaultView; + assert.ok(modal.modal_node instanceof window.HTMLElement); + assert.strictEqual(typeof modal.open, 'function'); + assert.strictEqual(typeof modal.close, 'function'); + assert.strictEqual(typeof modal.isOpen, 'function'); + assert.strictEqual(typeof modal.destroy, 'function'); + }); + }); + + describe('open API', function () { + beforeEach(function () { + this.spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( + modal_node, + trigger_node, + event + ) { + // Do nothing + }); + this.cleanup = jsdom(DOCTYPE + HTML()); + }); + + afterEach(function () { + sinon.restore(); + this.cleanup(); + }); + + it('Calling `open()` opens the modal', function () { + let template_result = templates.basic(); + let modal = yamodal({ + template: templates.basic, + beforeInsertIntoDom: this.spiedBeforeInsertIntoDom, + }); + + assert.strictEqual(global.document.documentElement.outerHTML, HTML()); + + modal.open(); + assert.ok(this.spiedBeforeInsertIntoDom.calledOnce); + + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(template_result) + ); + }); + + it('Calling `open()` multiple times does nothing while modal is open', function () { + let modal = yamodal({ + template: templates.basic, + beforeInsertIntoDom: this.spiedBeforeInsertIntoDom, + }); + + modal.open(); + assert.ok(this.spiedBeforeInsertIntoDom.calledOnce); + + modal.open(); + assert.ok(this.spiedBeforeInsertIntoDom.calledOnce); + }); + }); + + describe('close API', function () { + beforeEach(function () { + this.spiedBeforeRemoveFromDom = sinon.spy(function beforeRemoveFromDom( + modal_node, + trigger_node, + event + ) { + // Do nothing + }); + this.cleanup = jsdom(DOCTYPE + HTML()); + }); + + afterEach(function () { + sinon.restore(); + this.cleanup(); + }); + + it('Calling `close()` when the modal is not open does nothing', function () { + let modal = yamodal({ + template: templates.basic, + beforeRemoveFromDom: this.spiedBeforeRemoveFromDom, + }); + + modal.close(); + assert.ok(this.spiedBeforeRemoveFromDom.notCalled); + }); + + it('Calling `close()` closes the open modal', function () { + let template_result = templates.basic(); + let modal = yamodal({ + template: templates.basic, + beforeRemoveFromDom: this.spiedBeforeRemoveFromDom, + }); + + modal.open(); + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(template_result) + ); + + assert.ok(this.spiedBeforeRemoveFromDom.notCalled); + + modal.close(); + assert.ok(this.spiedBeforeRemoveFromDom.calledOnce); + + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML() + ); + }); + + it('Calling `close()` multiple times does nothing while modal is closed', function () { + let modal = yamodal({ + template: templates.basic, + beforeRemoveFromDom: this.spiedBeforeRemoveFromDom, + }); + + modal.open(); + assert.ok(this.spiedBeforeRemoveFromDom.notCalled); + + modal.close(); + assert.ok(this.spiedBeforeRemoveFromDom.calledOnce); + + modal.close(); + assert.ok(this.spiedBeforeRemoveFromDom.calledOnce); + }); + }); + }); }); From 6afd3c465dcfcad1ef224beea859cdc3247aa916 Mon Sep 17 00:00:00 2001 From: romellem Date: Fri, 21 Aug 2020 20:32:25 -0500 Subject: [PATCH 09/33] Adds placeholder for context testings --- test/tests.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/tests.js b/test/tests.js index 0cafb74..44b668a 100644 --- a/test/tests.js +++ b/test/tests.js @@ -461,7 +461,7 @@ describe('yamodal', function () { }); describe('API', function () { - describe('Return Object', function () { + describe('return object', function () { beforeEach(function () { this.cleanup = jsdom(DOCTYPE + HTML()); }); @@ -611,4 +611,14 @@ describe('yamodal', function () { }); }); }); + + describe('context', function () { + describe('static context', function () { + + }); + + describe('dynamic context', function () { + + }); + }); }); From 116ecc967481bb27400dc55c4ed26758e70a3ab2 Mon Sep 17 00:00:00 2001 From: romellem Date: Sat, 22 Aug 2020 10:11:23 -0500 Subject: [PATCH 10/33] Tests isOpen --- test/tests.js | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/test/tests.js b/test/tests.js index 44b668a..11542f0 100644 --- a/test/tests.js +++ b/test/tests.js @@ -588,10 +588,7 @@ describe('yamodal', function () { modal.close(); assert.ok(this.spiedBeforeRemoveFromDom.calledOnce); - assert.strictEqual( - global.document.documentElement.outerHTML, - HTML() - ); + assert.strictEqual(global.document.documentElement.outerHTML, HTML()); }); it('Calling `close()` multiple times does nothing while modal is closed', function () { @@ -610,6 +607,40 @@ describe('yamodal', function () { assert.ok(this.spiedBeforeRemoveFromDom.calledOnce); }); }); + + describe('isOpen API', function () { + beforeEach(function () { + this.cleanup = jsdom(DOCTYPE + HTML()); + }); + + afterEach(function () { + this.cleanup(); + }); + + it('Calling `isOpen()` returns the state of the modal', function () { + let template_result = templates.basic(); + let modal = yamodal({ + template: templates.basic, + beforeInsertIntoDom: this.spiedBeforeInsertIntoDom, + }); + + assert.strictEqual(global.document.documentElement.outerHTML, HTML()); + assert.strictEqual(modal.isOpen(), false); + + modal.open(); + + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(template_result) + ); + assert.strictEqual(modal.isOpen(), true); + + modal.close(); + + assert.strictEqual(global.document.documentElement.outerHTML, HTML()); + assert.strictEqual(modal.isOpen(), false); + }); + }); }); describe('context', function () { From 8f713bfd61740a02a9424b7daf57778debf5d655 Mon Sep 17 00:00:00 2001 From: romellem Date: Sat, 22 Aug 2020 10:14:35 -0500 Subject: [PATCH 11/33] Tests modal_node getter --- test/tests.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/tests.js b/test/tests.js index 11542f0..95b241c 100644 --- a/test/tests.js +++ b/test/tests.js @@ -494,6 +494,26 @@ describe('yamodal', function () { }); }); + describe('modal_node API', function () { + beforeEach(function () { + this.cleanup = jsdom(DOCTYPE + HTML()); + }); + + afterEach(function () { + this.cleanup(); + }); + + it('Getting `modal_node` returns the modal Element', function () { + let template_result = templates.basic(); + let modal = yamodal({ + template: templates.basic, + beforeInsertIntoDom: this.spiedBeforeInsertIntoDom, + }); + + assert.strictEqual(modal.modal_node.outerHTML, template_result); + }); + }); + describe('open API', function () { beforeEach(function () { this.spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( From aa94a991119e746da070c73c84d5e3e8c8f662a5 Mon Sep 17 00:00:00 2001 From: romellem Date: Sat, 22 Aug 2020 10:17:25 -0500 Subject: [PATCH 12/33] Tests getter for modal_node --- test/tests.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/tests.js b/test/tests.js index 95b241c..78638d1 100644 --- a/test/tests.js +++ b/test/tests.js @@ -477,6 +477,7 @@ describe('yamodal', function () { }); let api_keys = Object.keys(modal); + let modal_node_descriptor = Object.getOwnPropertyDescriptor(modal, 'modal_node'); assert.strictEqual(api_keys.length, 5); assert.ok(api_keys.includes('modal_node')); @@ -487,6 +488,7 @@ describe('yamodal', function () { const window = document.defaultView; assert.ok(modal.modal_node instanceof window.HTMLElement); + assert.strictEqual(typeof modal_node_descriptor.get, 'function'); assert.strictEqual(typeof modal.open, 'function'); assert.strictEqual(typeof modal.close, 'function'); assert.strictEqual(typeof modal.isOpen, 'function'); From 41d511c6325389785e139ed278680d474ee07ad4 Mon Sep 17 00:00:00 2001 From: romellem Date: Sat, 22 Aug 2020 10:32:22 -0500 Subject: [PATCH 13/33] Removes unused option --- test/tests.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/tests.js b/test/tests.js index 78638d1..81514b5 100644 --- a/test/tests.js +++ b/test/tests.js @@ -641,10 +641,7 @@ describe('yamodal', function () { it('Calling `isOpen()` returns the state of the modal', function () { let template_result = templates.basic(); - let modal = yamodal({ - template: templates.basic, - beforeInsertIntoDom: this.spiedBeforeInsertIntoDom, - }); + let modal = yamodal({ template: templates.basic }); assert.strictEqual(global.document.documentElement.outerHTML, HTML()); assert.strictEqual(modal.isOpen(), false); From 1e87c3ac24b8c71c208d4bfd910ae32f6ca7f84e Mon Sep 17 00:00:00 2001 From: romellem Date: Sat, 22 Aug 2020 10:32:29 -0500 Subject: [PATCH 14/33] Starts destroy API --- test/tests.js | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/test/tests.js b/test/tests.js index 81514b5..74bf279 100644 --- a/test/tests.js +++ b/test/tests.js @@ -660,6 +660,93 @@ describe('yamodal', function () { assert.strictEqual(modal.isOpen(), false); }); }); + + describe('destroy API', function () { + before(function () { + this.open_html = ``; + this.close_html = ``; + }); + + after(function () { + this.open_html = undefined; + this.close_html = undefined; + }); + + beforeEach(function () { + this.spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( + modal_node, + trigger_node, + event + ) { + // Do nothing + }); + this.spiedBeforeRemoveFromDom = sinon.spy(function beforeRemoveFromDom( + modal_node, + trigger_node, + event + ) { + // Do nothing + }); + this.cleanup = jsdom(DOCTYPE + HTML(`${this.open_html}${this.close_html}`)); + }); + + afterEach(function () { + sinon.restore(); + this.cleanup(); + }); + + it('Calling `destroy()` removes our click handlers', function () { + let template_result = templates.basic(); + let modal = yamodal({ + template: templates.basic, + trigger_selector: '#open', + close_selector: '#close', + beforeInsertIntoDom: this.spiedBeforeInsertIntoDom, + beforeRemoveFromDom: this.spiedBeforeRemoveFromDom, + }); + + let open_button = document.getElementById('open'); + let close_button = document.getElementById('close'); + + open_button.click(); + + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(`${this.open_html}${this.close_html}${template_result}`) + ); + assert.ok(this.spiedBeforeInsertIntoDom.calledOnce); + assert.ok(this.spiedBeforeRemoveFromDom.notCalled); + + close_button.click(); + + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(`${this.open_html}${this.close_html}`) + ); + assert.ok(this.spiedBeforeInsertIntoDom.calledOnce); + assert.ok(this.spiedBeforeRemoveFromDom.calledOnce); + + modal.destroy(); + + open_button.click(); + + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(`${this.open_html}${this.close_html}`) + ); + assert.ok(this.spiedBeforeInsertIntoDom.calledOnce); + assert.ok(this.spiedBeforeRemoveFromDom.calledOnce); + + close_button.click(); + + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(`${this.open_html}${this.close_html}`) + ); + assert.ok(this.spiedBeforeInsertIntoDom.calledOnce); + assert.ok(this.spiedBeforeRemoveFromDom.calledOnce); + }); + }); }); describe('context', function () { From 8fef6ed0a1b59e9375bb99fe6129f4abaa36653a Mon Sep 17 00:00:00 2001 From: romellem Date: Sat, 22 Aug 2020 10:32:52 -0500 Subject: [PATCH 15/33] Prettier --- test/tests.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/test/tests.js b/test/tests.js index 74bf279..db58a8f 100644 --- a/test/tests.js +++ b/test/tests.js @@ -666,12 +666,12 @@ describe('yamodal', function () { this.open_html = ``; this.close_html = ``; }); - + after(function () { this.open_html = undefined; this.close_html = undefined; }); - + beforeEach(function () { this.spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( modal_node, @@ -689,7 +689,7 @@ describe('yamodal', function () { }); this.cleanup = jsdom(DOCTYPE + HTML(`${this.open_html}${this.close_html}`)); }); - + afterEach(function () { sinon.restore(); this.cleanup(); @@ -750,12 +750,8 @@ describe('yamodal', function () { }); describe('context', function () { - describe('static context', function () { + describe('static context', function () {}); - }); - - describe('dynamic context', function () { - - }); + describe('dynamic context', function () {}); }); }); From a562881fa659a90111c82e06bf036bcb6a5d5a76 Mon Sep 17 00:00:00 2001 From: romellem Date: Sat, 22 Aug 2020 10:48:57 -0500 Subject: [PATCH 16/33] More tests of destroy API --- test/tests.js | 95 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 22 deletions(-) diff --git a/test/tests.js b/test/tests.js index db58a8f..606c138 100644 --- a/test/tests.js +++ b/test/tests.js @@ -673,36 +673,35 @@ describe('yamodal', function () { }); beforeEach(function () { - this.spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( + this.cleanup = jsdom(DOCTYPE + HTML(`${this.open_html}${this.close_html}`)); + }); + + afterEach(function () { + this.cleanup(); + }); + + it('Calling `destroy()` removes our click handlers', function () { + let template_result = templates.basic(); + const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( modal_node, trigger_node, event ) { // Do nothing }); - this.spiedBeforeRemoveFromDom = sinon.spy(function beforeRemoveFromDom( + const spiedBeforeRemoveFromDom = sinon.spy(function beforeRemoveFromDom( modal_node, trigger_node, event ) { // Do nothing }); - this.cleanup = jsdom(DOCTYPE + HTML(`${this.open_html}${this.close_html}`)); - }); - - afterEach(function () { - sinon.restore(); - this.cleanup(); - }); - - it('Calling `destroy()` removes our click handlers', function () { - let template_result = templates.basic(); let modal = yamodal({ template: templates.basic, trigger_selector: '#open', close_selector: '#close', - beforeInsertIntoDom: this.spiedBeforeInsertIntoDom, - beforeRemoveFromDom: this.spiedBeforeRemoveFromDom, + beforeInsertIntoDom: spiedBeforeInsertIntoDom, + beforeRemoveFromDom: spiedBeforeRemoveFromDom, }); let open_button = document.getElementById('open'); @@ -714,8 +713,8 @@ describe('yamodal', function () { global.document.documentElement.outerHTML, HTML(`${this.open_html}${this.close_html}${template_result}`) ); - assert.ok(this.spiedBeforeInsertIntoDom.calledOnce); - assert.ok(this.spiedBeforeRemoveFromDom.notCalled); + assert.ok(spiedBeforeInsertIntoDom.calledOnce); + assert.ok(spiedBeforeRemoveFromDom.notCalled); close_button.click(); @@ -723,8 +722,8 @@ describe('yamodal', function () { global.document.documentElement.outerHTML, HTML(`${this.open_html}${this.close_html}`) ); - assert.ok(this.spiedBeforeInsertIntoDom.calledOnce); - assert.ok(this.spiedBeforeRemoveFromDom.calledOnce); + assert.ok(spiedBeforeInsertIntoDom.calledOnce); + assert.ok(spiedBeforeRemoveFromDom.calledOnce); modal.destroy(); @@ -734,8 +733,8 @@ describe('yamodal', function () { global.document.documentElement.outerHTML, HTML(`${this.open_html}${this.close_html}`) ); - assert.ok(this.spiedBeforeInsertIntoDom.calledOnce); - assert.ok(this.spiedBeforeRemoveFromDom.calledOnce); + assert.ok(spiedBeforeInsertIntoDom.calledOnce); + assert.ok(spiedBeforeRemoveFromDom.calledOnce); close_button.click(); @@ -743,8 +742,60 @@ describe('yamodal', function () { global.document.documentElement.outerHTML, HTML(`${this.open_html}${this.close_html}`) ); - assert.ok(this.spiedBeforeInsertIntoDom.calledOnce); - assert.ok(this.spiedBeforeRemoveFromDom.calledOnce); + assert.ok(spiedBeforeInsertIntoDom.calledOnce); + assert.ok(spiedBeforeRemoveFromDom.calledOnce); + + sinon.restore(); + }); + + it('Calling `destroy()` on an open modal closes it', function () { + let template_result = templates.basic(); + let modal = yamodal({ + template: templates.basic, + }); + + modal.open(); + + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(`${this.open_html}${this.close_html}${template_result}`) + ); + + modal.destroy(); + + // Need to test the HTML because `destroy` also "no-ops" our `isOpen()` method + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(`${this.open_html}${this.close_html}`) + ); + }); + + it('Calling `destroy()` sets API methods to the same "no ops"', function () { + let modal = yamodal({ + template: templates.basic, + }); + + modal.destroy(); + + assert.strictEqual(modal.open, modal.isOpen); + assert.strictEqual(modal.open, modal.close); + assert.strictEqual(modal.open, modal.destroy); + assert.strictEqual(modal.close, modal.isOpen); + assert.strictEqual(modal.close, modal.destroy); + assert.strictEqual(modal.destroy, modal.isOpen); + + assert.doesNotThrow(() => modal.open()); + assert.doesNotThrow(() => modal.close()); + assert.doesNotThrow(() => modal.isOpen()); + assert.doesNotThrow(() => modal.destroy()); + + assert.strictEqual(modal.open(), undefined); + assert.strictEqual(modal.close(), undefined); + assert.strictEqual(modal.isOpen(), undefined); + assert.strictEqual(modal.destroy(), undefined); + + // `modal_node` isn't no-op'd, but its return value is set to undefined + assert.strictEqual(modal.modal_node, undefined); }); }); }); From e984629b909108b2a48c4cbe8764b0fcc9000376 Mon Sep 17 00:00:00 2001 From: romellem Date: Sat, 22 Aug 2020 12:32:49 -0500 Subject: [PATCH 17/33] Starts dynamic context tests --- test/templates.js | 1 + test/tests.js | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/test/templates.js b/test/templates.js index 007c772..229b83c 100644 --- a/test/templates.js +++ b/test/templates.js @@ -1,3 +1,4 @@ export const basic = () => ``; export const basicWithClose = (close_btn = ``) => ``; +export const basicWithContext = (val = '') => ``; diff --git a/test/tests.js b/test/tests.js index 606c138..f503813 100644 --- a/test/tests.js +++ b/test/tests.js @@ -803,6 +803,48 @@ describe('yamodal', function () { describe('context', function () { describe('static context', function () {}); - describe('dynamic context', function () {}); + describe('dynamic context', function () { + beforeEach(function () { + let random_context_return = String(Math.random()); + this.random_context_return = random_context_return; + this.spiedContext = sinon.spy(function context(trigger_node, event) { + return random_context_return; + }); + this.cleanup = jsdom(DOCTYPE + HTML()); + }); + + afterEach(function () { + this.random_context_return; + sinon.restore(); + this.cleanup(); + }); + + it('should not immediately create a modal_node when a dynamic context is passed', function () { + let modal = yamodal({ + template: templates.basic, + context: this.spiedContext, + }); + + assert.strictEqual(modal.modal_node, undefined); + assert.ok(this.spiedContext.notCalled); + }); + + it(`should pass context's return value to template`, function () { + let spiedTemplate = sinon.spy(templates.basicWithContext); + let modal = yamodal({ + template: spiedTemplate, + context: this.spiedContext, + }); + + modal.open(); + assert.ok(this.spiedContext.calledOnce); + assert.ok(spiedTemplate.calledOnceWith(this.random_context_return)); + spiedTemplate.calledAfter(this.spiedContext); + + modal.close(); + assert.ok(this.spiedContext.calledOnce); + assert.ok(spiedTemplate.calledOnceWith(this.random_context_return)); + }); + }); }); }); From 16f3a480ec9ff771e67d29edd6029bb432fd5df1 Mon Sep 17 00:00:00 2001 From: romellem Date: Sat, 22 Aug 2020 13:56:28 -0500 Subject: [PATCH 18/33] Tests utilities --- test/tests.js | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/test/tests.js b/test/tests.js index f503813..4c7010f 100644 --- a/test/tests.js +++ b/test/tests.js @@ -1,4 +1,7 @@ import yamodal from '../dist/umd/yamodal'; +import createEmptyCustomEvent from '../src/utils/custom-event'; +import once from '../src/utils/once-event-listener'; + import assert from 'assert'; import jsdom from 'global-jsdom'; import sinon from 'sinon'; @@ -7,6 +10,76 @@ import * as templates from './templates.js'; const DOCTYPE = ``; const HTML = (str = '') => `${str}`; +describe('utilies', function () { + beforeEach(function () { + this.cleanup = jsdom(); + }); + + afterEach(function () { + this.cleanup(); + }); + + describe('once event listener', function () { + it('should call event handler only once', function () { + const window = document.defaultView; + let spy = sinon.spy(); + + once(window, 'click', spy); + + assert.ok(spy.notCalled); + + // Trigger a click + let first_click = document.createEvent('HTMLEvents'); + first_click.initEvent('click', true, false); + window.dispatchEvent(first_click); + + assert.ok(spy.calledOnce); + + // Trigger a second click + let second_click = document.createEvent('HTMLEvents'); + second_click.initEvent('click', true, false); + window.dispatchEvent(second_click); + + assert.ok(spy.calledOnce); + }); + + it('should use remove event listener with "destroy" return function', function () { + const window = document.defaultView; + let spy = sinon.spy(); + + let destroy = once(window, 'click', spy); + + assert.strictEqual(typeof destroy, 'function'); + assert.ok(spy.notCalled); + + destroy(); + + let first_click = document.createEvent('HTMLEvents'); + first_click.initEvent('click', true, false); + window.dispatchEvent(first_click); + + assert.ok(spy.notCalled); + }); + }); + + describe('createEmptyCustomEvent', function () { + it('should use `CustomEvent` when supportde', function () { + const window = document.defaultView; + + let event = createEmptyCustomEvent('test'); + assert.ok(event instanceof window.Event); + }); + + it('should use polyfill when `CustomEvent` is not available', function () { + const window = document.defaultView; + delete window.CustomEvent; + + let event = createEmptyCustomEvent('test'); + assert.ok(event instanceof window.Event); + }); + }); +}); + describe('yamodal', function () { describe('errors', function () { beforeEach(function () { From 604c55c91206aee5bce7e371eac4ed00896241f8 Mon Sep 17 00:00:00 2001 From: romellem Date: Sat, 22 Aug 2020 20:52:03 -0500 Subject: [PATCH 19/33] Tests remove_modal_after_event_type --- test/tests.js | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/test/tests.js b/test/tests.js index 4c7010f..785f3c0 100644 --- a/test/tests.js +++ b/test/tests.js @@ -533,6 +533,53 @@ describe('yamodal', function () { }); }); + describe('remove_modal_after_event_type event type', function () { + beforeEach(function () { + this.cleanup = jsdom(DOCTYPE + HTML()); + }); + + afterEach(function () { + this.cleanup(); + }); + + it('should keep an open modal in the DOM until `remove_modal_after_event_type` has fired', function () { + let template_result = templates.basic(); + let modal = yamodal({ + template: templates.basic, + remove_modal_after_event_type: 'transitionend', + }); + + modal.open(); + + assert.strictEqual(modal.isOpen(), true); + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(`${template_result}`) + ); + + modal.close(); + + // Still open + assert.strictEqual(modal.isOpen(), true); + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(`${template_result}`) + ); + + // Trigger a 'transitionend' + let transitionend = document.createEvent('HTMLEvents'); + transitionend.initEvent('transitionend', true, false); + modal.modal_node.dispatchEvent(transitionend); + + // Now closed + assert.strictEqual(modal.isOpen(), false); + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML() + ); + }); + }); + describe('API', function () { describe('return object', function () { beforeEach(function () { From 6ce3ab3efd4f4febb6628f873abc7ff9294ba108 Mon Sep 17 00:00:00 2001 From: romellem Date: Sun, 23 Aug 2020 09:47:18 -0500 Subject: [PATCH 20/33] Tests beforeRemoveFromDom callback --- test/templates.js | 2 +- test/tests.js | 162 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 161 insertions(+), 3 deletions(-) diff --git a/test/templates.js b/test/templates.js index 229b83c..f1e7384 100644 --- a/test/templates.js +++ b/test/templates.js @@ -1,4 +1,4 @@ export const basic = () => ``; -export const basicWithClose = (close_btn = ``) => +export const basicWithClose = (close_btn = ``) => ``; export const basicWithContext = (val = '') => ``; diff --git a/test/tests.js b/test/tests.js index 785f3c0..7f5a011 100644 --- a/test/tests.js +++ b/test/tests.js @@ -403,7 +403,7 @@ describe('yamodal', function () { this.cleanup(); }); - it('should call `beforeInsertIntoDom` with exactly three arguments', function () { + it('should call `beforeInsertIntoDom` with exactly three arguments when the close button is clicked', function () { const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( modal_node, trigger_node, @@ -431,6 +431,33 @@ describe('yamodal', function () { assert.strictEqual(others.length, 0); }); + it('should call `beforeInsertIntoDom` with an undefined `trigger_node` when opened via the `open()` api', function () { + const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( + modal_node, + trigger_node, + event + ) { + // Do nothing + }); + let modal = yamodal({ + template: templates.basic, + beforeInsertIntoDom: spiedBeforeInsertIntoDom, + }); + + modal.open(); + + const window = document.defaultView; + let [modal_node, trigger_node, event, ...others] = spiedBeforeInsertIntoDom.getCall( + 0 + ).args; + + assert.ok(spiedBeforeInsertIntoDom.calledOnce); + assert.ok(modal_node instanceof window.HTMLElement); + assert.ok(trigger_node === undefined); + assert.ok(event instanceof window.Event); + assert.strictEqual(others.length, 0); + }); + it('should not open the modal if `beforeInsertIntoDom` returns false', function () { const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( modal_node, @@ -573,11 +600,142 @@ describe('yamodal', function () { // Now closed assert.strictEqual(modal.isOpen(), false); + assert.strictEqual(global.document.documentElement.outerHTML, HTML()); + }); + }); + + describe('beforeRemoveFromDom callback', function () { + beforeEach(function () { + this.cleanup = jsdom(DOCTYPE + HTML()); + }); + + afterEach(function () { + sinon.restore(); + this.cleanup(); + }); + + it('should call `beforeRemoveFromDom` with exactly three arguments when the close button is clicked', function () { + const spiedBeforeRemoveFromDom = sinon.spy(function beforeRemoveFromDom( + modal_node, + trigger_node, + event + ) { + // Do nothing + }); + + let modal = yamodal({ + template: templates.basicWithClose, + beforeRemoveFromDom: spiedBeforeRemoveFromDom, + }); + + modal.open(); + + assert.ok(spiedBeforeRemoveFromDom.notCalled); + + let button = document.getElementById('close'); + button.click(); + + const window = document.defaultView; + let [modal_node, close_node, event, ...others] = spiedBeforeRemoveFromDom.getCall( + 0 + ).args; + + assert.ok(spiedBeforeRemoveFromDom.calledOnce); + assert.ok(modal_node instanceof window.HTMLElement); + assert.ok(close_node instanceof window.HTMLElement); + assert.ok(event instanceof window.Event); + assert.strictEqual(others.length, 0); + }); + + it('should call `beforeRemoveFromDom` with an undefined `close_node` when closed via the `close()` api', function () { + const spiedBeforeRemoveFromDom = sinon.spy(function beforeRemoveFromDom( + modal_node, + trigger_node, + event + ) { + // Do nothing + }); + + let modal = yamodal({ + template: templates.basicWithClose, + beforeRemoveFromDom: spiedBeforeRemoveFromDom, + }); + + modal.open(); + modal.close(); + + const window = document.defaultView; + + let [modal_node, close_node, event, ...others] = spiedBeforeRemoveFromDom.getCall( + 0 + ).args; + + assert.ok(spiedBeforeRemoveFromDom.calledOnce); + assert.ok(modal_node instanceof window.HTMLElement); + assert.ok(close_node === undefined); + assert.ok(event instanceof window.Event); + assert.strictEqual(others.length, 0); + }); + + it('should not open the modal if `beforeRemoveFromDom` returns false', function () { + const spiedBeforeRemoveFromDom = sinon.spy(function beforeRemoveFromDom( + modal_node, + trigger_node, + event + ) { + return false; + }); + let template_result = templates.basic(); + let modal = yamodal({ + template: templates.basic, + beforeRemoveFromDom: spiedBeforeRemoveFromDom, + }); + + modal.open(); + + assert.ok(spiedBeforeRemoveFromDom.notCalled); + + modal.close(); + + assert.ok(spiedBeforeRemoveFromDom.calledOnce); + assert.strictEqual(modal.isOpen(), true); assert.strictEqual( global.document.documentElement.outerHTML, - HTML() + HTML(`${template_result}`) ); }); + + it('should still close the modal if `beforeRemoveFromDom` returns a falsy value different from `false`', function () { + // Not including `false` (obviously) and BigInt `0n` + const falsy_values = [0, null, undefined, NaN, '']; + for (let falsy_value of falsy_values) { + this.cleanup = jsdom(DOCTYPE + HTML(this.button_html)); + const spiedBeforeRemoveFromDom = sinon.spy(function beforeRemoveFromDom( + modal_node, + trigger_node, + event + ) { + return falsy_value; + }); + let template_result = templates.basic(); + let modal = yamodal({ + template: templates.basic, + beforeRemoveFromDom: spiedBeforeRemoveFromDom, + }); + + modal.open(); + assert.strictEqual(modal.isOpen(), true); + + modal.close(); + + assert.ok(spiedBeforeRemoveFromDom.calledOnce); + assert.strictEqual(modal.isOpen(), false); + assert.strictEqual(global.document.documentElement.outerHTML, HTML()); + + this.cleanup(); + sinon.restore(); + } + }); }); describe('API', function () { From cf8022cd688d97b1c0910d179282353039b21ae9 Mon Sep 17 00:00:00 2001 From: romellem Date: Sun, 23 Aug 2020 09:52:53 -0500 Subject: [PATCH 21/33] afterRemoveFromDom callback --- test/tests.js | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/test/tests.js b/test/tests.js index 7f5a011..0058932 100644 --- a/test/tests.js +++ b/test/tests.js @@ -677,7 +677,7 @@ describe('yamodal', function () { assert.strictEqual(others.length, 0); }); - it('should not open the modal if `beforeRemoveFromDom` returns false', function () { + it('should not close the modal if `beforeRemoveFromDom` returns false', function () { const spiedBeforeRemoveFromDom = sinon.spy(function beforeRemoveFromDom( modal_node, trigger_node, @@ -738,6 +738,69 @@ describe('yamodal', function () { }); }); + describe('afterRemoveFromDom callback', function () { + beforeEach(function () { + this.spiedAfterRemoveFromDom = sinon.spy(function afterRemoveFromDom( + modal_node, + trigger_node, + event + ) { + // Do nothing + }); + this.cleanup = jsdom(DOCTYPE + HTML()); + }); + + afterEach(function () { + sinon.restore(); + this.cleanup(); + }); + + it('should call `afterRemoveFromDom` with exactly three arguments when the close button is clicked', function () { + let modal = yamodal({ + template: templates.basicWithClose, + afterRemoveFromDom: this.spiedAfterRemoveFromDom, + }); + + modal.open(); + + let button = document.getElementById('close'); + button.click(); + + const window = document.defaultView; + let [modal_node, close_node, event, ...others] = this.spiedAfterRemoveFromDom.getCall( + 0 + ).args; + + assert.ok(this.spiedAfterRemoveFromDom.calledOnce); + assert.ok(modal_node instanceof window.HTMLElement); + assert.ok(close_node instanceof window.HTMLElement); + assert.ok(event instanceof window.Event); + assert.strictEqual(others.length, 0); + }); + + it('should call `beforeRemoveFromDom` with an undefined `close_node` when closed via the `close()` api', function () { + let modal = yamodal({ + template: templates.basicWithClose, + afterRemoveFromDom: this.spiedAfterRemoveFromDom, + }); + + modal.open(); + modal.close(); + + const window = document.defaultView; + + let [modal_node, close_node, event, ...others] = this.spiedAfterRemoveFromDom.getCall( + 0 + ).args; + + assert.ok(this.spiedAfterRemoveFromDom.calledOnce); + assert.ok(modal_node instanceof window.HTMLElement); + assert.ok(close_node === undefined); + assert.ok(event instanceof window.Event); + assert.strictEqual(others.length, 0); + }); + }); + describe('API', function () { describe('return object', function () { beforeEach(function () { From 88844e00f54bf7e5c3cc96c2f10a546c6ea5d4e3 Mon Sep 17 00:00:00 2001 From: romellem Date: Sun, 23 Aug 2020 10:07:02 -0500 Subject: [PATCH 22/33] onAfterSetup callback --- test/tests.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/tests.js b/test/tests.js index 0058932..0b412a4 100644 --- a/test/tests.js +++ b/test/tests.js @@ -801,6 +801,37 @@ describe('yamodal', function () { }); }); + describe('onAfterSetup callback', function () { + beforeEach(function () { + this.spiedOnAfterSetup = sinon.spy(function onAfterSetup(modal_node, api) { + // Do nothing + }); + this.cleanup = jsdom(DOCTYPE + HTML()); + }); + + afterEach(function () { + sinon.restore(); + this.cleanup(); + }); + + it('should call `onAfterSetup` with exactly two arguments', function () { + let modal = yamodal({ + template: templates.basic, + onAfterSetup: this.spiedOnAfterSetup, + }); + + assert.ok(this.spiedOnAfterSetup.calledOnce); + const window = document.defaultView; + let [modal_node, api, ...others] = this.spiedOnAfterSetup.getCall(0).args; + + assert.ok(modal_node instanceof window.HTMLElement); + + // The `api` is the same as the return object + assert.strictEqual(modal, api); + assert.strictEqual(others.length, 0); + }); + }); + describe('API', function () { describe('return object', function () { beforeEach(function () { From 0d9f5232bf1297e388b88ed8449f84348aa5d928 Mon Sep 17 00:00:00 2001 From: romellem Date: Sun, 23 Aug 2020 10:11:43 -0500 Subject: [PATCH 23/33] onDestroy callback --- test/tests.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/tests.js b/test/tests.js index 0b412a4..a8e102d 100644 --- a/test/tests.js +++ b/test/tests.js @@ -832,6 +832,35 @@ describe('yamodal', function () { }); }); + describe('onDestroy callback', function () { + beforeEach(function () { + this.spiedOnDestroy = sinon.spy(function onDestroy(modal_node) { + // Do nothing + }); + this.cleanup = jsdom(DOCTYPE + HTML()); + }); + + afterEach(function () { + sinon.restore(); + this.cleanup(); + }); + + it('should call `onDestroy` when destroying instance', function () { + let modal = yamodal({ + template: templates.basic, + onDestroy: this.spiedOnDestroy, + }); + + // Save the modal_node to compare it in our spy later + let modal_node = modal.modal_node; + + assert.ok(this.spiedOnDestroy.notCalled); + modal.destroy(); + + assert.ok(this.spiedOnDestroy.calledOnceWithExactly(modal_node)); + }); + }); + describe('API', function () { describe('return object', function () { beforeEach(function () { From c9e3d987a1c966cc859ff62dab7e7b4a9b5a006e Mon Sep 17 00:00:00 2001 From: romellem Date: Sun, 23 Aug 2020 10:39:01 -0500 Subject: [PATCH 24/33] More tests for dynamic context Found a bug here! If no close selector is passed, and we check this value when creating our dynamic modal_node, we don't check for the fact that a dynamic context may create a modal with the default close selector, and then later may create one without it. --- test/tests.js | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/test/tests.js b/test/tests.js index a8e102d..3af5f1b 100644 --- a/test/tests.js +++ b/test/tests.js @@ -1246,6 +1246,66 @@ describe('yamodal', function () { assert.ok(this.spiedContext.calledOnce); assert.ok(spiedTemplate.calledOnceWith(this.random_context_return)); }); + + it(`should create different modal_node Elements when dynamic context is used`, function () { + let modal = yamodal({ + template: templates.basicWithContext, + context: this.spiedContext, + }); + + modal.open(); + let modal_node_first = modal.modal_node; + + modal.close(); + + modal.open(); + let modal_node_second = modal.modal_node; + + assert.strictEqual(modal_node_first.outerHTML, modal_node_second.outerHTML); + assert.notStrictEqual(modal_node_first, modal_node_second); + }); + + it(`should attach close listener to modal if dynamic context makes the modal not have the default close selector`, function () { + let include_close_button; + let spiedContext = sinon.spy(function contextClosure() { + if (include_close_button) { + // `templates.basicWithClose` has a default close button when called with an undefined context + return undefined; + } else { + return ''; + } + }); + + const window = document.defaultView; + let modal = yamodal({ + template: templates.basicWithClose, + context: spiedContext, + }); + + include_close_button = true; + modal.open(); + assert.strictEqual(modal.isOpen(), true); + assert.ok(spiedContext.calledOnce); + + // Use default_close_selector + let close_button = modal.modal_node.querySelector('[data-modal-close]'); + assert.ok(close_button instanceof window.HTMLElement); + close_button.click(); + assert.strictEqual(modal.isOpen(), false); + + include_close_button = false; + modal.open(); + // console.log(global.document.documentElement.outerHTML) + assert.strictEqual(modal.isOpen(), true); + assert.ok(spiedContext.calledTwice); + + let close_button_doesnt_exist = modal.modal_node.querySelector( + '[data-modal-close]' + ); + assert.ok(close_button_doesnt_exist === null); + modal.modal_node.click(); + assert.strictEqual(modal.isOpen(), false); + }); }); }); }); From 52c463039495912da37ef7f0964d3be1cf0645db Mon Sep 17 00:00:00 2001 From: romellem Date: Sun, 23 Aug 2020 10:45:21 -0500 Subject: [PATCH 25/33] Resets close_selector if needed on dynamic modals --- docs/examples.iife.js | 8 ++++++-- src/yamodal.js | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/examples.iife.js b/docs/examples.iife.js index 0135f68..dff43cb 100644 --- a/docs/examples.iife.js +++ b/docs/examples.iife.js @@ -289,8 +289,12 @@ if (modal_is_dynamic) { modal_node = createModalNode(trigger_node, event); // Always check for the default close selector if none was specified for a dynamic modal - if (no_close_selector_specified && modal_node.querySelector(default_close_selector)) { - close_selector = default_close_selector; + if (no_close_selector_specified) { + if (modal_node.querySelector(default_close_selector)) { + close_selector = default_close_selector; + } else { + close_selector = undefined; + } } } diff --git a/src/yamodal.js b/src/yamodal.js index 742f2b4..85db8a1 100644 --- a/src/yamodal.js +++ b/src/yamodal.js @@ -120,8 +120,12 @@ const initializeModalListener = ({ modal_node = createModalNode(trigger_node, event); // Always check for the default close selector if none was specified for a dynamic modal - if (no_close_selector_specified && modal_node.querySelector(default_close_selector)) { - close_selector = default_close_selector; + if (no_close_selector_specified) { + if (modal_node.querySelector(default_close_selector)) { + close_selector = default_close_selector; + } else { + close_selector = undefined; + } } } From ee77de26cd28c8c658b6234d74f114368e21ca64 Mon Sep 17 00:00:00 2001 From: romellem Date: Sun, 23 Aug 2020 16:33:18 -0500 Subject: [PATCH 26/33] Tests `else` branch on dynamic modal with close selector --- test/tests.js | 56 ++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/test/tests.js b/test/tests.js index 3af5f1b..eaa3c08 100644 --- a/test/tests.js +++ b/test/tests.js @@ -316,30 +316,37 @@ describe('yamodal', function () { }); it('should use the modal itself when modal does not contain default close selector or is set to `null`', function () { - for (let close_selector of [undefined, null]) { - const open_html = ``; - this.cleanup = jsdom(DOCTYPE + HTML(open_html)); - let template_result = templates.basic(); - yamodal({ - template: () => template_result, - trigger_selector: '#open', - close_selector, - }); - let open = document.getElementById('open'); - open.click(); - - assert.strictEqual( - global.document.documentElement.outerHTML, - HTML(`${open_html}${template_result}`) - ); - - let modal = document.getElementById('modal'); - modal.click(); - - assert.strictEqual(global.document.documentElement.outerHTML, HTML(`${open_html}`)); - - // It's OK that this runs twice - this.cleanup(); + // Also text this with static and dynamic contexts + for (let context of [undefined, () => {}]) { + for (let close_selector of [undefined, null]) { + const open_html = ``; + this.cleanup = jsdom(DOCTYPE + HTML(open_html)); + let template_result = templates.basic(); + yamodal({ + template: () => template_result, + trigger_selector: '#open', + close_selector, + context, + }); + let open = document.getElementById('open'); + open.click(); + + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(`${open_html}${template_result}`) + ); + + let modal = document.getElementById('modal'); + modal.click(); + + assert.strictEqual( + global.document.documentElement.outerHTML, + HTML(`${open_html}`) + ); + + // It's OK that this runs twice + this.cleanup(); + } } }); }); @@ -1295,7 +1302,6 @@ describe('yamodal', function () { include_close_button = false; modal.open(); - // console.log(global.document.documentElement.outerHTML) assert.strictEqual(modal.isOpen(), true); assert.ok(spiedContext.calledTwice); From c278dccc81a132e781ce68613d48d43c939df05b Mon Sep 17 00:00:00 2001 From: romellem Date: Sun, 23 Aug 2020 16:40:04 -0500 Subject: [PATCH 27/33] Tests custom events --- test/tests.js | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/test/tests.js b/test/tests.js index eaa3c08..b91cab7 100644 --- a/test/tests.js +++ b/test/tests.js @@ -913,7 +913,7 @@ describe('yamodal', function () { this.cleanup(); }); - it('Getting `modal_node` returns the modal Element', function () { + it('getting `modal_node` returns the modal Element', function () { let template_result = templates.basic(); let modal = yamodal({ template: templates.basic, @@ -941,7 +941,7 @@ describe('yamodal', function () { this.cleanup(); }); - it('Calling `open()` opens the modal', function () { + it('calling `open()` opens the modal', function () { let template_result = templates.basic(); let modal = yamodal({ template: templates.basic, @@ -959,7 +959,7 @@ describe('yamodal', function () { ); }); - it('Calling `open()` multiple times does nothing while modal is open', function () { + it('calling `open()` multiple times does nothing while modal is open', function () { let modal = yamodal({ template: templates.basic, beforeInsertIntoDom: this.spiedBeforeInsertIntoDom, @@ -971,6 +971,19 @@ describe('yamodal', function () { modal.open(); assert.ok(this.spiedBeforeInsertIntoDom.calledOnce); }); + + it('should allow a custom event to be passed into the `open()` method', function () { + let modal = yamodal({ + template: templates.basic, + beforeInsertIntoDom: this.spiedBeforeInsertIntoDom, + }); + + let custom_event = createEmptyCustomEvent('placeholder'); + modal.open(custom_event); + let [, , event] = this.spiedBeforeInsertIntoDom.getCall(0).args; + + assert.strictEqual(custom_event, event); + }); }); describe('close API', function () { @@ -990,7 +1003,7 @@ describe('yamodal', function () { this.cleanup(); }); - it('Calling `close()` when the modal is not open does nothing', function () { + it('calling `close()` when the modal is not open does nothing', function () { let modal = yamodal({ template: templates.basic, beforeRemoveFromDom: this.spiedBeforeRemoveFromDom, @@ -1021,7 +1034,7 @@ describe('yamodal', function () { assert.strictEqual(global.document.documentElement.outerHTML, HTML()); }); - it('Calling `close()` multiple times does nothing while modal is closed', function () { + it('calling `close()` multiple times does nothing while modal is closed', function () { let modal = yamodal({ template: templates.basic, beforeRemoveFromDom: this.spiedBeforeRemoveFromDom, @@ -1036,6 +1049,20 @@ describe('yamodal', function () { modal.close(); assert.ok(this.spiedBeforeRemoveFromDom.calledOnce); }); + + it('should allow a custom event to be passed into the `close()` method', function () { + let modal = yamodal({ + template: templates.basic, + beforeRemoveFromDom: this.spiedBeforeRemoveFromDom, + }); + + let custom_event = createEmptyCustomEvent('placeholder'); + modal.open(); + modal.close(custom_event); + let [, , event] = this.spiedBeforeRemoveFromDom.getCall(0).args; + + assert.strictEqual(custom_event, event); + }); }); describe('isOpen API', function () { @@ -1047,7 +1074,7 @@ describe('yamodal', function () { this.cleanup(); }); - it('Calling `isOpen()` returns the state of the modal', function () { + it('calling `isOpen()` returns the state of the modal', function () { let template_result = templates.basic(); let modal = yamodal({ template: templates.basic }); @@ -1088,7 +1115,7 @@ describe('yamodal', function () { this.cleanup(); }); - it('Calling `destroy()` removes our click handlers', function () { + it('calling `destroy()` removes our click handlers', function () { let template_result = templates.basic(); const spiedBeforeInsertIntoDom = sinon.spy(function beforeInsertIntoDom( modal_node, @@ -1156,7 +1183,7 @@ describe('yamodal', function () { sinon.restore(); }); - it('Calling `destroy()` on an open modal closes it', function () { + it('calling `destroy()` on an open modal closes it', function () { let template_result = templates.basic(); let modal = yamodal({ template: templates.basic, @@ -1178,7 +1205,7 @@ describe('yamodal', function () { ); }); - it('Calling `destroy()` sets API methods to the same "no ops"', function () { + it('calling `destroy()` sets API methods to the same "no ops"', function () { let modal = yamodal({ template: templates.basic, }); From d238175dd8ea76075b8d43456fc880490e00b275 Mon Sep 17 00:00:00 2001 From: romellem Date: Sun, 23 Aug 2020 19:07:24 -0500 Subject: [PATCH 28/33] BREAKING - Replaces custom event name I got this namespace wrong; typically the namespace is listed after the regular event. Of course this doesn't really matter, but seems like something to change before the major version. Before I can publish this, this will request a major version change, which isn't a big deal. --- docs/examples.iife.js | 4 ++-- src/yamodal.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/examples.iife.js b/docs/examples.iife.js index dff43cb..d60e876 100644 --- a/docs/examples.iife.js +++ b/docs/examples.iife.js @@ -381,11 +381,11 @@ }, open: function open() { - var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : createEmptyCustomEvent('yamodal.open'); + var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : createEmptyCustomEvent('open.yamodal'); return onTriggerOpen(event); }, close: function close() { - var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : createEmptyCustomEvent('yamodal.close'); + var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : createEmptyCustomEvent('close.yamodal'); return onTriggerClose(event); }, isOpen: function isOpen() { diff --git a/src/yamodal.js b/src/yamodal.js index 85db8a1..692cf32 100644 --- a/src/yamodal.js +++ b/src/yamodal.js @@ -210,10 +210,10 @@ const initializeModalListener = ({ get modal_node() { return modal_node; }, - open(event = createEmptyCustomEvent('yamodal.open')) { + open(event = createEmptyCustomEvent('open.yamodal')) { return onTriggerOpen(event); }, - close(event = createEmptyCustomEvent('yamodal.close')) { + close(event = createEmptyCustomEvent('close.yamodal')) { return onTriggerClose(event); }, isOpen() { From 3cff9aedac3533d65c1fa48f90a1aed27a48be4c Mon Sep 17 00:00:00 2001 From: romellem Date: Sun, 23 Aug 2020 19:12:24 -0500 Subject: [PATCH 29/33] Adjusts custom event names to match src --- README.md | 10 +++++----- docs/examples.iife.js | 2 +- examples/templates/dynamic-context-reading-event.js | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5c89caa..b217d87 100644 --- a/README.md +++ b/README.md @@ -223,7 +223,7 @@ yamodal({ ```js yamodal({ - template: event => `
This was opened via ${event.type === 'yamodal.open' ? 'the open() API' : 'a click'}
`, + template: event => `
This was opened via ${event.type === 'open.yamodal' ? 'the open() API' : 'a click'}
`, context(trigger_node, event) { return event; }, @@ -537,7 +537,7 @@ _Type:_ `Function` When `isOpen()` is run, it returns `true` if the current modal is open, `false` if otherwise. -#### Return `open(event = new CustomEvent('yamodal.open'))` +#### Return `open(event = new CustomEvent('open.yamodal'))` _Type:_ `Function` @@ -546,7 +546,7 @@ This means that any `beforeInsertIntoDom`, `onAppend`, or `afterInsertIntoDom` functions will also run. Since usually the modal is opened by a click event, programmatic openings have a -"placeholder" event passed in. This event will have a type of `'yamodal.open'`. +"placeholder" event passed in. This event will have a type of `'open.yamodal'`. Optionally, you can send your own custom event to the open handler. ```js @@ -555,7 +555,7 @@ var my_modal = yamodal({ ... }); setTimeout(() => my_modal.open(), 1000); ``` -#### Return `close(event = new CustomEvent('yamodal.close'))` +#### Return `close(event = new CustomEvent('close.yamodal'))` _Type:_ `Function` @@ -563,7 +563,7 @@ When `close()` is run it triggers the same handler that runs when a close elemen This means that any `beforeRemoveFromDom`, or `afterRemoveFromDom` functions will also run. Since the modal is usually closed by a click event, programmatic closings have a -"placeholder" event passed in. This event will have a type of `'yamodal.close'`. +"placeholder" event passed in. This event will have a type of `'close.yamodal'`. Optionally, you can send your own custom event to the close handler. #### Return `destroy()` diff --git a/docs/examples.iife.js b/docs/examples.iife.js index d60e876..cd58116 100644 --- a/docs/examples.iife.js +++ b/docs/examples.iife.js @@ -463,7 +463,7 @@ }; var template$9 = function template(event) { - return "\n
\n
\n
\n This modal was opened via ".concat(event.type === 'yamodal.open' ? 'the open() API' : 'a click', "\n
\n \n
\n
"); + return "\n
\n
\n
\n This modal was opened via ".concat(event.type === 'open.yamodal' ? 'the open() API' : 'a click', "\n
\n \n
\n
"); }; initializeModalListener({ diff --git a/examples/templates/dynamic-context-reading-event.js b/examples/templates/dynamic-context-reading-event.js index 729b049..139e1b9 100644 --- a/examples/templates/dynamic-context-reading-event.js +++ b/examples/templates/dynamic-context-reading-event.js @@ -3,7 +3,7 @@ const template = (event) => `