share-this
Version:
Medium-like text selection sharing without dependencies
127 lines (116 loc) • 5.08 kB
JavaScript
/* eslint-disable consistent-return, no-undef, no-unused-expressions */
import chai, { expect } from "chai";
import { spy } from "sinon";
import sinonChai from "sinon-chai";
import { JSDOM } from "jsdom";
import * as popover from "../src/popover.js";
chai.use(sinonChai);
const fakeHTML = "<ul><li data-share-via=\"foo\">Hello, world!</li></ul>";
describe("Popover methods", () => {
describe("lifeCycleFactory", () => {
it("must be a factory function", () => {
expect(popover.lifeCycleFactory).to.be.a("function");
const result = popover.lifeCycleFactory(null);
expect(result).to.be.an("object");
});
it("must create an object with a createPopover method", () => {
const { result } = initLifeCycle();
expect(result.createPopover).to.be.a("function");
});
it("must create an object with an attachPopover method", () => {
const { result } = initLifeCycle();
expect(result.attachPopover).to.be.a("function");
});
it("must create an object with a removePopover method", () => {
const { result } = initLifeCycle();
expect(result.removePopover).to.be.a("function");
});
describe("createPopover", () => {
it("must create a DOM element", () => {
const { result, window } = initLifeCycle();
const element = result.createPopover();
expect(element instanceof window.HTMLElement).to.be.true;
});
it("must attach an onclick event listener to the created element", () => {
let attached = false;
const fakeElement = {
addEventListener(type, fn) {
expect(attached).to.be.false;
expect(type).to.equal("click");
expect(fn).to.be.a("function");
attached = true;
}
};
const fakeDocument = {
createElement(tagName) {
expect(tagName).to.be.a("string");
return fakeElement;
}
};
const { createPopover } = popover.lifeCycleFactory(fakeDocument);
const fakePopover = createPopover();
expect(fakePopover).to.equal(fakeElement);
});
});
describe("attachPopover", () => {
it("must append the given element to document.body", () => {
const { result, window } = initLifeCycle();
const fakePopover = window.document.createElement("foo");
result.attachPopover(fakePopover);
expect(fakePopover.parentNode).to.equal(window.document.body);
});
});
describe("removePopover", () => {
it("must detach the given element from document.body", () => {
const { result, window: { document: body } } = initLifeCycle();
const fakePopover = body.firstChild;
result.removePopover(fakePopover);
expect(body.childNodes.length).to.equal(0);
expect(fakePopover.parentNode).to.be.null;
});
});
});
describe("popoverClick", () => {
it("must call the sharer's `action` method", () => {
const { window } = new JSDOM(fakeHTML);
const sharer = {
name: "foo",
action: spy()
};
const target = window.document.body.firstChild.firstChild;
const event = new window.Event("click");
target.dispatchEvent(event);
popover.popoverClick([ sharer ], event);
expect(sharer.action).to.be.calledOnce;
});
it("must get out soon if the sharer isn't found", () => {
const { window } = new JSDOM(fakeHTML);
const sharer = {
name: "bar",
action: spy()
};
const target = window.document.body.firstChild.firstChild;
const event = new window.Event("click");
target.dispatchEvent(event);
popover.popoverClick([ sharer ], event);
expect(sharer.action).to.not.be.called;
});
it("must get out soon if the element isn't found", () => {
const { window } = new JSDOM(fakeHTML);
const sharer = {
name: "foo",
action: spy()
};
const target = window.document.body.firstChild.firstChild;
target.removeAttribute("data-share-via");
const event = new window.Event("click");
target.dispatchEvent(event);
popover.popoverClick([ sharer ], event);
expect(sharer.action).to.not.be.called;
});
});
});
function initLifeCycle() {
const { window } = new JSDOM(fakeHTML);
return { result: popover.lifeCycleFactory(window.document), window };
}