Repository navigation
Expand file tree
/
Copy pathutil.js
More file actions
200 lines (173 loc) · 5.94 KB
/
Copy pathutil.js
File metadata and controls
200 lines (173 loc) · 5.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
"use strict";
const path = require("path");
const jsdom = require("../lib/jsdom");
const fs = require("fs");
const exceptionTable = require("../lib/jsdom/web-idl/dom-exception-table.json");
const request = require("request");
const Canvas = require("../lib/jsdom/utils").Canvas;
function toPathname(dirname, relativePath) {
let pathname = path.resolve(dirname, relativePath).replace(/\\/g, "/");
if (pathname[0] !== "/") {
pathname = "/" + pathname;
}
return pathname;
}
function toFileUrl(dirname, relativePath) {
return "file://" + toPathname(dirname, relativePath);
}
exports.toFileUrl = dirname => {
return function (relativePath) {
return toFileUrl(dirname, relativePath);
};
};
exports.toPathname = dirname => {
return function (relativePath) {
return toPathname(dirname, relativePath);
};
};
exports.load = dirname => {
const fileCache = Object.create(null);
return function (name, options) {
options = options || {};
const file = path.resolve(dirname, "files/" + name + ".html");
if (!options.url) {
options.url = toFileUrl(dirname, file);
}
const contents = fileCache[file] || fs.readFileSync(file, "utf8");
const doc = jsdom.jsdom(null, options);
const window = doc.defaultView;
doc.parent = window;
window.loadComplete = function () {};
doc.write(contents);
doc.close();
fileCache[file] = contents;
return doc;
};
};
/**
* @param {Document} document
* @param {String} name
* @return {Function} A function that tests if the given
* exception is a `DOMException` of the specified `code`
*
* @example t.throws(function () {
* // ...
* }, domExceptionPredicate(doc, "NoModificationAllowedError"));
*/
exports.domExceptionPredicate = (document, name) => {
return function (error) {
return error instanceof document.defaultView.DOMException &&
error.name === name &&
error.code === exceptionTable[name].legacyCodeValue;
};
};
exports.todo = (test, fn) => {
fn({
ok(value, message) {
test.ok(!value, "Marked as TODO: " + message);
}
// add more as needed
});
};
exports.injectIFrame = document => {
return exports.injectIFrameWithScript(document);
};
exports.injectIFrameWithScript = (document, scriptStr) => {
scriptStr = scriptStr || "";
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const scriptTag = iframe.contentWindow.document.createElement("script");
scriptTag.textContent = scriptStr;
iframe.contentWindow.document.body.appendChild(scriptTag);
return iframe;
};
/**
* Create a new Promise and call the given function with a resolver function which can be passed as a node
* style callback.
*
* Node style callbacks expect their first argument to be an Error object or null. The returned promise will
* be rejected if this first argument is set. Otherwise the promise will be resolved with the second argument of
* the callback, or with an array of arguments if there are more arguments.
*
* @example nodeResolverPromise(nodeResolver => fs.readFile('foo.png', nodeResolver)).then(content => {});
* @param {Function} fn
* @returns {Promise}
*/
exports.nodeResolverPromise = fn => {
return new Promise((resolve, reject) => {
fn(function (error, result) {
if (error) {
reject(error);
} else if (arguments.length > 2) {
// pass all the arguments as an array,
// skipping the error param
const arrayResult = new Array(arguments.length - 1);
for (let i = 1; i < arguments.length; ++i) {
arrayResult[i - 1] = arguments[i];
}
resolve(arrayResult);
} else {
resolve(result);
}
});
});
};
/**
* Is this script currently running within a Web Worker context?
* @returns {boolean}
*/
exports.inWebWorkerContext = () => {
/* globals WorkerGlobalScope, self */
return typeof WorkerGlobalScope !== "undefined" && self instanceof WorkerGlobalScope;
};
/**
* Is this script currently running within a browser context?
* Note: also returns true within a Web Worker context
* @returns {boolean}
*/
exports.inBrowserContext = () => {
/* globals window */
return (typeof window === "object" && window === window.self) || exports.inWebWorkerContext();
};
/**
* Resolves a path to a static fixture file to a file or http URL.
* If running tests from node, a valid file url will be returned.
* If running tests using karma, a http url to the file be returned (this file is served by karma)
* @param {string} relativePath Relative path within the test directory. For example "jsdom/files/reddit.html"
* @returns {string} URL
*/
exports.getTestFixtureUrl = relativePath => {
/* globals location */
if (exports.inBrowserContext()) {
// location is a Location or WorkerLocation
return location.origin + "/base/test" + (relativePath[0] === "/" ? "" : "/") + relativePath;
}
return toFileUrl(__dirname, relativePath);
};
/**
* Reads a static fixture file as utf8.
* If running tests from node, the file will be read from the file system
* If running tests using karma, a http request will be performed to retrieve the file using karma's server.
* @param {string} relativePath Relative path within the test directory. For example "jsdom/files/reddit.html"
*/
exports.readTestFixture = relativePath => {
const useRequest = exports.inBrowserContext();
return exports.nodeResolverPromise(nodeResolver => {
if (useRequest) {
request.get(exports.getTestFixtureUrl(relativePath), { timeout: 5000 }, nodeResolver);
} else {
fs.readFile(path.resolve(__dirname, relativePath), { encoding: "utf8" }, nodeResolver);
}
})
// request passes (error, response, content) to the callback
// we are only interested in the `content`
.then(result => useRequest ? result[1] : result);
exports.isCanvasInstalled = t => {
if (!Canvas) {
t.ok(true, "test ignored; not running with the canvas npm package installed");
t.done();
return false;
}
return true;
};