UNPKG

4.57 kBJavaScriptView Raw
1"use strict";
2
3global.Mocha = require("mocha");
4global.Chai = require("chai");
5global.expect = Chai.expect;
6
7
8/** Check if an element contains one or more CSS classes */
9addToChai(["class", "classes"], function(...classNames){
10 const negated = Chai.util.flag(this, "negate");
11 let subjects = Chai.util.flag(this, "object");
12 subjects = "length" in subjects ? Array.from(subjects) : [subjects];
13
14 for(const subject of subjects){
15 const classList = subject.classList;
16 for(let names of classNames){
17 if(!Array.isArray(names))
18 names = names.split(/\s+/g);
19
20 for(let name of names){
21 const list = subject.classList.length
22 ? `classList "${subject.className}"`
23 : "empty classList";
24
25 this.assert(
26 classList.contains(name),
27 `expected ${list} to include "${name}"`,
28 `expected ${list} not to include "${name}"`
29 );
30 }
31 }
32 }
33});
34
35
36/** Assert that two filesystem paths are the same */
37Chai.Assertion.addMethod("equalPath", function(path){
38 const normalise = require("path").normalize;
39 const subject = Chai.util.flag(this, "object");
40 const expected = normalise(path);
41 const actual = normalise(subject);
42
43 this.assert(
44 actual === expected,
45 "expected path #{act} to equal #{exp}",
46 "expected path #{act} not to equal #{exp}",
47 expected,
48 actual,
49 false
50 );
51});
52
53
54/** Assert that a file exists in the filesystem */
55Chai.Assertion.addProperty("existOnDisk", function(){
56 const path = Chai.util.flag(this, "object");
57 let exists = false;
58
59 try{
60 require("fs").statSync(path);
61 exists = true;
62 } catch(e){}
63
64 this.assert(
65 exists,
66 `expected "${path}" to exist in filesystem`,
67 `expected "${path}" not to exist in filesystem`
68 );
69});
70
71
72/** Assert that an HTML element has user focus */
73Chai.Assertion.addProperty("focus", function(){
74 const ae = document.activeElement;
75
76 let subject = Chai.util.flag(this, "object");
77 if(subject.jquery)
78 subject = subject[0];
79
80 this.assert(
81 ae === subject || ae.contains(subject),
82 "expected element to have focus",
83 "expected element not to have focus"
84 );
85});
86
87
88/** Assert that an HTML element is rendered in the DOM tree */
89Chai.Assertion.addProperty("drawn", function(){
90 let subject = Chai.util.flag(this, "object");
91 if(subject.jquery)
92 subject = subject[0];
93
94 const bounds = subject.getBoundingClientRect();
95 const {top, right, bottom, left} = bounds;
96
97 this.assert(
98 !(top === 0 && right === 0 && bottom === 0 && left === 0),
99 "expected element to be drawn",
100 "expected element not to be drawn"
101 );
102});
103
104
105/** Attach one or more HTML elements to the spec-runner window */
106global.attachToDOM = function(...elements){
107 if(global.atom.getLoadSettings().headless)
108 return;
109
110 const mocha = document.querySelector("#mocha");
111 const body = mocha.parentElement;
112 for(const el of elements)
113 if(el !== mocha && !body.contains(el))
114 body.insertBefore(el, mocha);
115};
116
117
118/** Remove previously-added HTML elements */
119global.resetDOM = function(){
120 if(global.atom.getLoadSettings().headless)
121 return;
122
123 const mocha = document.querySelector("#mocha");
124 for(const el of Array.from(document.body.children))
125 if(el !== mocha) document.body.removeChild(el);
126};
127
128
129/**
130 * @global - Predicate to skip POSIX-only tests.
131 * This avoids marking skipped tests as "pending" if run on Windows.
132 *
133 * @example
134 * unlessOnWindows.describe("Symlinks", …);
135 * unlessOnWindows.it("tests hard-links", …);
136 * unlessOnWindows(posixOnlyFunc => …);
137 *
138 * @property {Function} describe
139 * @property {Function} specify
140 * @property {Function} it
141 * @type {Function}
142 */
143global.unlessOnWindows = (mochFn => {
144 const noope = () => {};
145 const isWin = "win32" === process.platform;
146 const output = cb => (cb && !isWin) ? cb() : noope();
147 for(const name of mochFn){
148 const value = isWin ? noope : (...args) => global[name](...args);
149 Object.defineProperty(output, name, {value});
150 }
151 return output;
152})(["describe", "it", "specify"]);
153
154
155/**
156 * Call `describe()` with "When " prepended to its description.
157 *
158 * Complements the `autoIt` setting and helps specs read more naturally.
159 * Only globalised if `when` doesn't exist in global scope.
160 *
161 * @example when("it loads the page", () => it("does this", fn)));
162 * @param {String} text
163 * @param {...*} args
164 * @type {Function}
165 */
166function when(text, ...args){
167 return describe("When " + text, ...args);
168}
169
170if(null == global.when)
171 global.when = when;
172
173
174/** Thin wrapper around Chai.Assertion.addMethod to permit plugin aliases */
175function addToChai(names, fn){
176 for(const name of names)
177 Chai.Assertion.addMethod(name, fn);
178}