diff --git a/src/core/base.js b/src/core/base.js index a4607361a..ead43bc4f 100644 --- a/src/core/base.js +++ b/src/core/base.js @@ -61,6 +61,9 @@ Base.prototype = { on(eventName, eventCallback) { this.$el.on(`${eventName}.${this.name}.patterns`, eventCallback); }, + one(eventName, eventCallback) { + this.$el.one(`${eventName}.${this.name}.patterns`, eventCallback); + }, emit(eventName, args) { // args should be a list if (args === undefined) { diff --git a/src/core/base.test.js b/src/core/base.test.js index 50d888b56..7d0d4499e 100644 --- a/src/core/base.test.js +++ b/src/core/base.test.js @@ -135,13 +135,33 @@ describe("pat-base: The Base class for patterns", function () { new Tmp3($("
"), { option: "value" }); }); - it("has on/emit helpers to prefix events", function () { + it("has on/emit helpers to prefix events", function (done) { var Tmp = Base.extend({ name: "tmp", trigger: ".pat-tmp", init: function () { this.on("something", function (e, arg1) { expect(arg1).toEqual("yaay!"); + done(); + }); + this.emit("somethingelse", ["yaay!"]); + }, + }); + new Tmp( + $("
").on("somethingelse.tmp.patterns", function (e, arg1) { + $(this).trigger("something.tmp.patterns", [arg1]); + }) + ); + }); + + it("has ``one`` helper to prefix events", function (done) { + var Tmp = Base.extend({ + name: "tmp", + trigger: ".pat-tmp", + init: function () { + this.one("something", function (e, arg1) { + expect(arg1).toEqual("yaay!"); + done(); }); this.emit("somethingelse", ["yaay!"]); }, diff --git a/src/core/events.js b/src/core/events.js index ffa6aa3ea..b46d3f612 100644 --- a/src/core/events.js +++ b/src/core/events.js @@ -58,6 +58,41 @@ const remove_event_listener = (el, id) => { } }; +/** + * Await an event to be thrown. + * + * Usage: + * await events.await_event(button, "click"); + * + * @param {DOM Node} el - The element to listen on. + * @param {String} event_name - The event name to listen for. + * + * @returns {Promise} - Returns a Promise which can be used for ``await`` and which will be resolved when the event is throwm. + * + */ +const await_event = (el, event_name) => { + // See: https://stackoverflow.com/a/44746691/1337474 + return new Promise((resolve) => + el.addEventListener(event_name, resolve, { once: true }) + ); +}; + +/** + * Await pattern init. + * + * Usage: + * await events.await_pattern_init(PATTERN); + * + * @param {Pattern instance} pattern - The pattern instance. + * + * @returns {Promise} - Returns a Promise which can be used for ``await`` and which will be resolved when the event is throwm. + * + */ +const await_pattern_init = (pattern) => { + // See: https://stackoverflow.com/a/44746691/1337474 + return new Promise((resolve) => pattern.one("init", resolve)); +}; + /** * Event factories */ @@ -100,6 +135,8 @@ const submit_event = () => { export default { add_event_listener: add_event_listener, remove_event_listener: remove_event_listener, + await_event: await_event, + await_pattern_init: await_pattern_init, click_event: click_event, change_event: change_event, input_event: input_event, diff --git a/src/core/events.test.js b/src/core/events.test.js index 8bc3d21ed..9e6813014 100644 --- a/src/core/events.test.js +++ b/src/core/events.test.js @@ -1,3 +1,4 @@ +import Base from "./base"; import events from "./events"; import utils from "./utils"; @@ -47,6 +48,35 @@ describe("core.events tests", () => { done(); }); + + it("Awaits an event to happen", async () => { + const el = document.createElement("div"); + + window.setTimeout(() => { + el.dispatchEvent(new Event("init")); + }, 1); + + await events.await_event(el, "init"); + + // If test reaches this expect statement, all is fine. + expect(true).toBe(true); + }); + + it("Awaits a pattern to be initialized", async () => { + const pat = Base.extend({ + name: "tmp", + trigger: ".pat-tmp", + init: function () {}, + }); + + const el = document.createElement("div"); + const instance = new pat(el); + + await events.await_pattern_init(instance); + + // If test reaches this expect statement, all is fine. + expect(true).toBe(true); + }); }); describe("2 - event factories", () => {