@schukai/monster 3.32.0 → 3.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +1 -1
- package/source/dom/customelement.mjs +1 -52
- package/source/dom/dimension.mjs +105 -0
- package/source/dom/slotted.mjs +111 -0
- package/source/types/version.mjs +1 -1
- package/source/util/runtime.mjs +96 -0
- package/test/cases/dom/assembler.mjs +0 -2
- package/test/cases/dom/attributes.mjs +0 -1
- package/test/cases/dom/customelement.mjs +1 -37
- package/test/cases/dom/dimension.mjs +128 -0
- package/test/cases/dom/find.mjs +16 -25
- package/test/cases/dom/slotted-nodes.mjs +14 -0
- package/test/cases/monster.mjs +1 -1
- package/test/util/chai-dom.mjs +2 -2
- package/test/util/jsdom.mjs +3 -1
- package/test/web/import.js +6 -0
- package/test/web/test.html +4 -4
- package/test/web/tests.js +3594 -2134
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ We do try to work around some browser bugs, but on the whole we don't use polyfi
|
|
|
73
73
|
However, many functions can be mapped via [polyfill.io](https://polyfill.io/) and thus the compatibility can be increased.
|
|
74
74
|
|
|
75
75
|
```html
|
|
76
|
-
<script id="polyfill" src="https://polyfill.io/v3/polyfill.min.js?features=Array.from,Array.isArray,Array.prototype.entries,Array.prototype.fill,Array.prototype.filter,Array.prototype.forEach,Array.prototype.indexOf,Array.prototype.keys,Array.prototype.lastIndexOf,Array.prototype.map,Array.prototype.reduce,Array.prototype.sort,ArrayBuffer,atob,Blob,CustomEvent,DataView,document,Document,DocumentFragment,Element,Event,fetch,globalThis,HTMLDocument,HTMLTemplateElement,Intl,JSON,Map,Math.log2,Number.isInteger,Object.assign,Object.defineProperty,Object.entries,Object.freeze,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.keys,Promise,Reflect,Reflect.defineProperty,Reflect.get,Reflect.getOwnPropertyDescriptor,Reflect.setPrototypeOf,Set,String.prototype.endsWith,String.prototype.matchAll,String.prototype.padStart,String.prototype.startsWith,String.prototype.trim,Symbol,Symbol.for,Symbol.hasInstance,Symbol.iterator,Uint16Array,Uint8Array,URL,WeakMap,WeakSet"
|
|
76
|
+
<script id="polyfill" src="https://polyfill.io/v3/polyfill.min.js?features=Array.from,Array.isArray,Array.prototype.entries,Array.prototype.fill,Array.prototype.filter,Array.prototype.forEach,Array.prototype.includes,Array.prototype.indexOf,Array.prototype.keys,Array.prototype.lastIndexOf,Array.prototype.map,Array.prototype.reduce,Array.prototype.sort,ArrayBuffer,atob,Blob,CustomEvent,DataView,document,Document,DocumentFragment,Element,Event,fetch,globalThis,HTMLDocument,HTMLTemplateElement,Intl,JSON,Map,Math.log2,Number.isInteger,Object.assign,Object.defineProperty,Object.entries,Object.freeze,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.keys,Promise,Reflect,Reflect.defineProperty,Reflect.get,Reflect.getOwnPropertyDescriptor,Reflect.setPrototypeOf,Set,String.prototype.endsWith,String.prototype.includes,String.prototype.matchAll,String.prototype.padStart,String.prototype.startsWith,String.prototype.trim,Symbol,Symbol.for,Symbol.hasInstance,Symbol.iterator,Uint16Array,Uint8Array,URL,WeakMap,WeakSet"
|
|
77
77
|
crossorigin="anonymous"
|
|
78
78
|
referrerpolicy="no-referrer"></script>
|
|
79
79
|
```
|
package/package.json
CHANGED
|
@@ -29,6 +29,7 @@ import {findDocumentTemplate, Template} from "./template.mjs";
|
|
|
29
29
|
import {addObjectWithUpdaterToElement} from "./updater.mjs";
|
|
30
30
|
import {instanceSymbol} from "../constants.mjs";
|
|
31
31
|
import {getDocumentTranslations, Translations} from "../i18n/translations.mjs";
|
|
32
|
+
import {getSlottedElements} from "./slotted.mjs";
|
|
32
33
|
|
|
33
34
|
export {
|
|
34
35
|
CustomElement,
|
|
@@ -599,58 +600,6 @@ class CustomElement extends HTMLElement {
|
|
|
599
600
|
}
|
|
600
601
|
}
|
|
601
602
|
|
|
602
|
-
/**
|
|
603
|
-
* @private
|
|
604
|
-
* @param {String|undefined} query
|
|
605
|
-
* @param {String|undefined|null} name name of the slot (if the parameter is undefined, all slots are searched, if the parameter has the value null, all slots without a name are searched. if a string is specified, the slots with this name are searched.)
|
|
606
|
-
* @return {*}
|
|
607
|
-
* @this CustomElement
|
|
608
|
-
* @license AGPLv3
|
|
609
|
-
* @since 1.23.0
|
|
610
|
-
* @throws {Error} query must be a string
|
|
611
|
-
*/
|
|
612
|
-
function getSlottedElements(query, name) {
|
|
613
|
-
const self = this;
|
|
614
|
-
const result = new Set();
|
|
615
|
-
|
|
616
|
-
if (!(self.shadowRoot instanceof ShadowRoot)) {
|
|
617
|
-
return result;
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
let selector = "slot";
|
|
621
|
-
if (name !== undefined) {
|
|
622
|
-
if (name === null) {
|
|
623
|
-
selector += ":not([name])";
|
|
624
|
-
} else {
|
|
625
|
-
selector += `[name=${validateString(name)}]`;
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
const slots = self.shadowRoot.querySelectorAll(selector);
|
|
630
|
-
|
|
631
|
-
for (const [, slot] of Object.entries(slots)) {
|
|
632
|
-
slot.assignedElements().forEach(function (node) {
|
|
633
|
-
if (!(node instanceof HTMLElement)) return;
|
|
634
|
-
|
|
635
|
-
if (isString(query)) {
|
|
636
|
-
node.querySelectorAll(query).forEach(function (n) {
|
|
637
|
-
result.add(n);
|
|
638
|
-
});
|
|
639
|
-
|
|
640
|
-
if (node.matches(query)) {
|
|
641
|
-
result.add(node);
|
|
642
|
-
}
|
|
643
|
-
} else if (query !== undefined) {
|
|
644
|
-
throw new Error("query must be a string");
|
|
645
|
-
} else {
|
|
646
|
-
result.add(node);
|
|
647
|
-
}
|
|
648
|
-
});
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
return result;
|
|
652
|
-
}
|
|
653
|
-
|
|
654
603
|
/**
|
|
655
604
|
* @this CustomElement
|
|
656
605
|
* @private
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright schukai GmbH and contributors 2023. All Rights Reserved.
|
|
3
|
+
* Node module: @schukai/monster
|
|
4
|
+
* This file is licensed under the AGPLv3 License.
|
|
5
|
+
* License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {getWindow} from './util.mjs';
|
|
9
|
+
|
|
10
|
+
export {convertToPixels, getDeviceDPI}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Stores the DPI of the device.
|
|
15
|
+
*
|
|
16
|
+
* @returns {number}
|
|
17
|
+
* @type {number}
|
|
18
|
+
*/
|
|
19
|
+
let CURRENT_DEVICE_DPI = function () {
|
|
20
|
+
let i = 0;
|
|
21
|
+
for (i = 56; i < 2000; i++) {
|
|
22
|
+
if (getWindow().matchMedia("(max-resolution: " + i + "dpi)").matches === true) {
|
|
23
|
+
return i;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return i;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Returns the DPI of the device.
|
|
31
|
+
*
|
|
32
|
+
* @returns {number}
|
|
33
|
+
*/
|
|
34
|
+
function getDeviceDPI() {
|
|
35
|
+
// only call the function once
|
|
36
|
+
if (typeof CURRENT_DEVICE_DPI === 'function') {
|
|
37
|
+
CURRENT_DEVICE_DPI = CURRENT_DEVICE_DPI();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return getWindow().devicePixelRatio * CURRENT_DEVICE_DPI;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Converts a CSS value to pixels.
|
|
46
|
+
*
|
|
47
|
+
* As Example:
|
|
48
|
+
*
|
|
49
|
+
* ```js
|
|
50
|
+
* convertToPixels('1em') // returns the current font size in pixels
|
|
51
|
+
* convertToPixels('1rem') // returns the current root font size in pixels
|
|
52
|
+
* convertToPixels('1px') // returns 1
|
|
53
|
+
* convertToPixels('100%') // returns the current width of the parent element in pixels
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* Following units are supported:
|
|
57
|
+
* - px
|
|
58
|
+
* - em
|
|
59
|
+
* - rem
|
|
60
|
+
* - %
|
|
61
|
+
*
|
|
62
|
+
* @param value
|
|
63
|
+
* @param parentElement
|
|
64
|
+
* @param fontSizeElement
|
|
65
|
+
* @returns {number}
|
|
66
|
+
* @license AGPLv3
|
|
67
|
+
* @since 1.6.0
|
|
68
|
+
* @copyright schukai GmbH
|
|
69
|
+
* @memberOf Monster.DOM
|
|
70
|
+
* @throws {Error} Unsupported unit
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
function convertToPixels(value, parentElement = document.documentElement, fontSizeElement = document.documentElement) {
|
|
74
|
+
const regex = /^([\d.]+)(.*)$/;
|
|
75
|
+
const [, num, unit] = value.match(regex);
|
|
76
|
+
const number = parseFloat(num);
|
|
77
|
+
const dpi = getDeviceDPI();
|
|
78
|
+
|
|
79
|
+
if (unit === 'px') {
|
|
80
|
+
return number;
|
|
81
|
+
} else if (unit === 'em') {
|
|
82
|
+
const fontSize = parseFloat(window.getComputedStyle(fontSizeElement).fontSize);
|
|
83
|
+
return number * fontSize;
|
|
84
|
+
} else if (unit === 'rem') {
|
|
85
|
+
const rootFontSize = parseFloat(window.getComputedStyle(parentElement).fontSize);
|
|
86
|
+
return number * rootFontSize;
|
|
87
|
+
} else if (unit === '%') {
|
|
88
|
+
const parentWidth = parseFloat(window.getComputedStyle(parentElement).width);
|
|
89
|
+
return (number * parentWidth) / 100;
|
|
90
|
+
} else if (unit === 'in') {
|
|
91
|
+
return number * dpi;
|
|
92
|
+
} else if (unit === 'cm') {
|
|
93
|
+
return (number * dpi) / 2.54;
|
|
94
|
+
} else if (unit === 'mm') {
|
|
95
|
+
return (number * dpi) / 25.4;
|
|
96
|
+
} else if (unit === 'pt') {
|
|
97
|
+
return (number * dpi) / 72;
|
|
98
|
+
} else if (unit === 'pc') {
|
|
99
|
+
return (number * dpi) / 6;
|
|
100
|
+
} else {
|
|
101
|
+
throw new Error(`Unsupported unit: ${unit}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import {isString} from "../types/is.mjs";
|
|
2
|
+
import {validateString} from "../types/validate.mjs";
|
|
3
|
+
|
|
4
|
+
export {getSlottedElements, getSlottedNodes};
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @private
|
|
8
|
+
* @param {String|undefined} query
|
|
9
|
+
* @param {String|undefined|null} name name of the slot (if the parameter is undefined, all slots are searched, if the parameter has the value null, all slots without a name are searched. if a string is specified, the slots with this name are searched.)
|
|
10
|
+
* @return {*}
|
|
11
|
+
* @this CustomElement
|
|
12
|
+
* @license AGPLv3
|
|
13
|
+
* @since 3.33.0
|
|
14
|
+
* @throws {Error} query must be a string
|
|
15
|
+
*/
|
|
16
|
+
function getSlottedNodes(query, name) {
|
|
17
|
+
const self = this;
|
|
18
|
+
const result = new Set();
|
|
19
|
+
|
|
20
|
+
if (!self.shadowRoot) {
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let selector = "slot";
|
|
25
|
+
if (name !== undefined) {
|
|
26
|
+
if (name === null) {
|
|
27
|
+
selector += ":not([name])";
|
|
28
|
+
} else {
|
|
29
|
+
selector += `[name=${validateString(name)}]`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const slots = self.shadowRoot.querySelectorAll(selector);
|
|
34
|
+
|
|
35
|
+
for (const [, slot] of Object.entries(slots)) {
|
|
36
|
+
slot.assignedNodes().forEach(function (node) {
|
|
37
|
+
if (node === null || node === undefined) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (isString(query)) {
|
|
42
|
+
node.querySelectorAll(query).forEach(function (n) {
|
|
43
|
+
result.add(n);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (node.matches(query)) {
|
|
47
|
+
result.add(node);
|
|
48
|
+
}
|
|
49
|
+
} else if (query !== undefined) {
|
|
50
|
+
throw new Error("query must be a string");
|
|
51
|
+
} else {
|
|
52
|
+
result.add(node);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @private
|
|
63
|
+
* @param {String|undefined} query
|
|
64
|
+
* @param {String|undefined|null} name name of the slot (if the parameter is undefined, all slots are searched, if the parameter has the value null, all slots without a name are searched. if a string is specified, the slots with this name are searched.)
|
|
65
|
+
* @return {*}
|
|
66
|
+
* @this CustomElement
|
|
67
|
+
* @license AGPLv3
|
|
68
|
+
* @since 1.23.0
|
|
69
|
+
* @throws {Error} query must be a string
|
|
70
|
+
*/
|
|
71
|
+
function getSlottedElements(query, name) {
|
|
72
|
+
const self = this;
|
|
73
|
+
const result = new Set();
|
|
74
|
+
|
|
75
|
+
if (!(self.shadowRoot instanceof ShadowRoot)) {
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let selector = "slot";
|
|
80
|
+
if (name !== undefined) {
|
|
81
|
+
if (name === null) {
|
|
82
|
+
selector += ":not([name])";
|
|
83
|
+
} else {
|
|
84
|
+
selector += `[name=${validateString(name)}]`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const slots = self.shadowRoot.querySelectorAll(selector);
|
|
89
|
+
|
|
90
|
+
for (const [, slot] of Object.entries(slots)) {
|
|
91
|
+
slot.assignedElements().forEach(function (node) {
|
|
92
|
+
if (!(node instanceof HTMLElement)) return;
|
|
93
|
+
|
|
94
|
+
if (isString(query)) {
|
|
95
|
+
node.querySelectorAll(query).forEach(function (n) {
|
|
96
|
+
result.add(n);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
if (node.matches(query)) {
|
|
100
|
+
result.add(node);
|
|
101
|
+
}
|
|
102
|
+
} else if (query !== undefined) {
|
|
103
|
+
throw new Error("query must be a string");
|
|
104
|
+
} else {
|
|
105
|
+
result.add(node);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return result;
|
|
111
|
+
}
|
package/source/types/version.mjs
CHANGED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright schukai GmbH and contributors 2023. All Rights Reserved.
|
|
3
|
+
* Node module: @schukai/monster
|
|
4
|
+
* This file is licensed under the AGPLv3 License.
|
|
5
|
+
* License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const ENV_AWS_LAMBDA = 'aws-lambda';
|
|
9
|
+
const ENV_GOOGLE_FUNCTIONS = 'google-functions';
|
|
10
|
+
const ENV_ELECTRON = 'electron';
|
|
11
|
+
const ENV_NODE = 'node';
|
|
12
|
+
const ENV_BROWSER = 'browser';
|
|
13
|
+
const ENV_WEB_WORKER = 'web-worker';
|
|
14
|
+
const ENV_DENO = 'deno';
|
|
15
|
+
const ENV_UNKNOWN = 'unknown';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Detects and returns the current runtime environment.
|
|
19
|
+
*
|
|
20
|
+
* - 'aws-lambda': AWS Lambda environment
|
|
21
|
+
* - 'google-functions': Google Cloud Functions environment
|
|
22
|
+
* - 'electron': Electron environment
|
|
23
|
+
* - 'node': Node.js environment
|
|
24
|
+
* - 'browser': Browser environment
|
|
25
|
+
* - 'web-worker': Web Worker environment
|
|
26
|
+
* - 'deno': Deno environment
|
|
27
|
+
* - 'react-native': React Native environment
|
|
28
|
+
* - 'unknown': Unknown environment
|
|
29
|
+
*
|
|
30
|
+
* @returns {string} The detected runtime environment. Possible values are:
|
|
31
|
+
*/
|
|
32
|
+
function detectRuntimeEnvironment() {
|
|
33
|
+
// AWS Lambda environment
|
|
34
|
+
if (
|
|
35
|
+
typeof process !== 'undefined' &&
|
|
36
|
+
process.env != null &&
|
|
37
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME
|
|
38
|
+
) {
|
|
39
|
+
return ENV_AWS_LAMBDA;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Google Cloud Functions environment
|
|
43
|
+
if (
|
|
44
|
+
typeof process !== 'undefined' &&
|
|
45
|
+
process.env != null &&
|
|
46
|
+
process.env.FUNCTION_NAME
|
|
47
|
+
) {
|
|
48
|
+
return ENV_GOOGLE_FUNCTIONS;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Node.js environment
|
|
52
|
+
if (
|
|
53
|
+
typeof process !== 'undefined' &&
|
|
54
|
+
process.versions != null &&
|
|
55
|
+
process.versions.node != null
|
|
56
|
+
) {
|
|
57
|
+
// Electron environment
|
|
58
|
+
if (process.versions.electron != null) {
|
|
59
|
+
return ENV_ELECTRON;
|
|
60
|
+
}
|
|
61
|
+
return ENV_NODE;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Browser environment
|
|
65
|
+
if (
|
|
66
|
+
typeof window !== 'undefined' &&
|
|
67
|
+
typeof window.document !== 'undefined' &&
|
|
68
|
+
typeof navigator !== 'undefined' &&
|
|
69
|
+
typeof navigator.userAgent === 'string'
|
|
70
|
+
) {
|
|
71
|
+
// Web Worker environment
|
|
72
|
+
if (typeof self === 'object' && typeof importScripts === 'function') {
|
|
73
|
+
return ENV_WEB_WORKER;
|
|
74
|
+
}
|
|
75
|
+
return ENV_BROWSER;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Deno environment
|
|
79
|
+
if (typeof Deno !== 'undefined') {
|
|
80
|
+
return ENV_DENO;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Unknown environment
|
|
84
|
+
return ENV_UNKNOWN;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export {
|
|
88
|
+
ENV_AWS_LAMBDA,
|
|
89
|
+
ENV_GOOGLE_FUNCTIONS,
|
|
90
|
+
ENV_ELECTRON,
|
|
91
|
+
ENV_NODE,
|
|
92
|
+
ENV_BROWSER,
|
|
93
|
+
ENV_WEB_WORKER,
|
|
94
|
+
ENV_DENO,
|
|
95
|
+
ENV_UNKNOWN,
|
|
96
|
+
detectRuntimeEnvironment}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import chai from "chai"
|
|
4
4
|
import {internalSymbol} from "../../../../application/source/constants.mjs";
|
|
5
|
-
import {ATTRIBUTE_OPTIONS
|
|
5
|
+
import {ATTRIBUTE_OPTIONS} from "../../../../application/source/dom/constants.mjs";
|
|
6
6
|
import {getDocument} from "../../../../application/source/dom/util.mjs";
|
|
7
7
|
import {ProxyObserver} from "../../../../application/source/types/proxyobserver.mjs";
|
|
8
8
|
import {addObjectWithUpdaterToElement} from "../../../../application/source/dom/updater.mjs";
|
|
@@ -32,42 +32,6 @@ describe('DOM', function () {
|
|
|
32
32
|
|
|
33
33
|
let CustomElement, registerCustomElement, TestComponent, document, TestComponent2,assignUpdaterToElement;
|
|
34
34
|
|
|
35
|
-
// This allows us to inspect the addEventListener calls
|
|
36
|
-
|
|
37
|
-
// let addEventListener = EventTarget.prototype.addEventListener;
|
|
38
|
-
// let removeEventListener = EventTarget.prototype.removeEventListener;
|
|
39
|
-
//
|
|
40
|
-
// before(function (done) {
|
|
41
|
-
// initJSDOM().then(() => {
|
|
42
|
-
//
|
|
43
|
-
// EventTarget.prototype.addEventListener = function (type, callback, options) {
|
|
44
|
-
// /* store args and then… */
|
|
45
|
-
// // callback = (e) => {
|
|
46
|
-
// // console.log("event fired" + e);
|
|
47
|
-
// // callback(e);
|
|
48
|
-
// // };
|
|
49
|
-
//
|
|
50
|
-
// addEventListener.call(this, type, callback, options);
|
|
51
|
-
// };
|
|
52
|
-
//
|
|
53
|
-
// EventTarget.prototype.removeEventListener = function (type, callback, options) {
|
|
54
|
-
// /* remove from stored args and then… */
|
|
55
|
-
// removeEventListener.call(this, type, callback, options);
|
|
56
|
-
// };
|
|
57
|
-
//
|
|
58
|
-
// done(e);
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
// });
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
// })
|
|
65
|
-
//
|
|
66
|
-
// after(function () {
|
|
67
|
-
// EventTarget.prototype.addEventListener = addEventListener;
|
|
68
|
-
// EventTarget.prototype.removeEventListener = removeEventListener;
|
|
69
|
-
// });
|
|
70
|
-
|
|
71
35
|
|
|
72
36
|
describe("assignUpdaterToElement", function () {
|
|
73
37
|
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {convertToPixels, getDeviceDPI} from "../../../../application/source/dom/dimension.mjs";
|
|
3
|
+
import {getWindow} from "../../../../application/source/dom/util.mjs";
|
|
4
|
+
import {initJSDOM, isBrowser, JSDOMExport as JSDOM} from "../../util/jsdom.mjs";
|
|
5
|
+
import {getGlobal} from "../../../../application/source/types/global.mjs";
|
|
6
|
+
import {detectRuntimeEnvironment} from "../../../../application/source/util/runtime.mjs";
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
function getMockWindow(dpi) {
|
|
10
|
+
|
|
11
|
+
if(detectRuntimeEnvironment() === 'browser') {
|
|
12
|
+
return getWindow();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
const dom = new JSDOM('', {
|
|
17
|
+
pretendToBeVisual: true,
|
|
18
|
+
resources: 'usable',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
dom.window.matchMedia = (query) => {
|
|
22
|
+
const dpiRegex = /\(max-resolution: (\d+)dpi\)/;
|
|
23
|
+
const match = query.match(dpiRegex);
|
|
24
|
+
|
|
25
|
+
if (match) {
|
|
26
|
+
const maxDpi = parseInt(match[1], 10);
|
|
27
|
+
return {matches: dpi <= maxDpi};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {matches: false};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return dom.window;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe('dimension', () => {
|
|
37
|
+
let currentEnvironment;
|
|
38
|
+
|
|
39
|
+
before(function (done) {
|
|
40
|
+
initJSDOM().then(() => {
|
|
41
|
+
//chaiDom(getDocument());
|
|
42
|
+
done();
|
|
43
|
+
});
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
beforeEach(() => {
|
|
47
|
+
|
|
48
|
+
const testDpi = 96;
|
|
49
|
+
const testWindow = getMockWindow(testDpi);
|
|
50
|
+
getGlobal().window = testWindow;
|
|
51
|
+
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
afterEach(() => {
|
|
55
|
+
delete getGlobal().window;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('convertToPixels', () => {
|
|
59
|
+
it('should correctly convert px values', () => {
|
|
60
|
+
const result = convertToPixels('100px');
|
|
61
|
+
expect(result).to.equal(100);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should correctly convert em values', () => {
|
|
65
|
+
const testElement = document.createElement('div');
|
|
66
|
+
testElement.style.fontSize = '16px';
|
|
67
|
+
document.body.appendChild(testElement);
|
|
68
|
+
|
|
69
|
+
const result = convertToPixels('2em', testElement, testElement);
|
|
70
|
+
expect(result).to.equal(32);
|
|
71
|
+
|
|
72
|
+
document.body.removeChild(testElement);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should correctly convert rem values', () => {
|
|
76
|
+
const testElement = document.createElement('div');
|
|
77
|
+
testElement.style.fontSize = '16px';
|
|
78
|
+
document.documentElement.appendChild(testElement);
|
|
79
|
+
|
|
80
|
+
const result = convertToPixels('2rem', testElement);
|
|
81
|
+
expect(result).to.equal(32);
|
|
82
|
+
|
|
83
|
+
document.documentElement.removeChild(testElement);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should correctly convert percentage values', () => {
|
|
87
|
+
const testElement = document.createElement('div');
|
|
88
|
+
testElement.style.width = '500px';
|
|
89
|
+
document.body.appendChild(testElement);
|
|
90
|
+
|
|
91
|
+
const result = convertToPixels('50%', testElement);
|
|
92
|
+
expect(result).to.equal(250);
|
|
93
|
+
|
|
94
|
+
document.body.removeChild(testElement);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should throw an error for unsupported units', () => {
|
|
98
|
+
expect(() => convertToPixels('10unsupportedUnit')).to.throw('Unsupported unit: unsupportedUnit');
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
describe('getDeviceDPI', () => {
|
|
104
|
+
it('should return the correct device DPI', () => {
|
|
105
|
+
const testDpi = 96;
|
|
106
|
+
const testWindow = getMockWindow(testDpi);
|
|
107
|
+
getGlobal().window = testWindow;
|
|
108
|
+
|
|
109
|
+
const deviceDpi = getDeviceDPI();
|
|
110
|
+
expect(deviceDpi).to.equal(testDpi * testWindow.devicePixelRatio);
|
|
111
|
+
|
|
112
|
+
delete getGlobal().window;
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('should cache the result and return the same value', () => {
|
|
116
|
+
const testDpi = 96;
|
|
117
|
+
const testWindow = getMockWindow(testDpi);
|
|
118
|
+
getGlobal().window = testWindow;
|
|
119
|
+
|
|
120
|
+
const deviceDpi1 = getDeviceDPI();
|
|
121
|
+
const deviceDpi2 = getDeviceDPI();
|
|
122
|
+
expect(deviceDpi1).to.equal(deviceDpi2);
|
|
123
|
+
|
|
124
|
+
delete getGlobal().window;
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
});
|
package/test/cases/dom/find.mjs
CHANGED
|
@@ -2,30 +2,16 @@ import {
|
|
|
2
2
|
findElementWithIdUpwards
|
|
3
3
|
} from "../../../../application/source/dom/util.mjs";
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
let originalEnvironment;
|
|
5
|
+
import {expect} from 'chai';
|
|
6
|
+
import {initJSDOM} from "../../util/jsdom.mjs";
|
|
9
7
|
|
|
10
8
|
function setupTestEnvironment() {
|
|
11
|
-
const { window } = new JSDOM('<!DOCTYPE html>', { pretendToBeVisual: true });
|
|
12
9
|
|
|
13
|
-
const { document, customElements, HTMLElement } = window;
|
|
14
|
-
originalEnvironment = {
|
|
15
|
-
document: globalThis.document,
|
|
16
|
-
customElements: globalThis.customElements,
|
|
17
|
-
HTMLElement: globalThis.HTMLElement,
|
|
18
|
-
ShadowRoot: globalThis.ShadowRoot,
|
|
19
|
-
};
|
|
20
|
-
globalThis.document = document;
|
|
21
|
-
globalThis.customElements = customElements;
|
|
22
|
-
globalThis.HTMLElement = HTMLElement;
|
|
23
|
-
globalThis.ShadowRoot = window.ShadowRoot || class ShadowRoot {}; // Fallback for JSDOM
|
|
24
10
|
|
|
25
11
|
class TestComponent extends HTMLElement {
|
|
26
12
|
constructor() {
|
|
27
13
|
super();
|
|
28
|
-
this.attachShadow({
|
|
14
|
+
this.attachShadow({mode: 'open'});
|
|
29
15
|
}
|
|
30
16
|
}
|
|
31
17
|
|
|
@@ -35,12 +21,16 @@ function setupTestEnvironment() {
|
|
|
35
21
|
}
|
|
36
22
|
|
|
37
23
|
function cleanupTestEnvironment() {
|
|
38
|
-
|
|
24
|
+
let mocks = document.getElementById('mocks');
|
|
25
|
+
mocks.innerHTML = "";
|
|
39
26
|
}
|
|
40
27
|
|
|
41
28
|
describe('findElementWithIdUpwards', () => {
|
|
42
|
-
before(() => {
|
|
43
|
-
|
|
29
|
+
before((done) => {
|
|
30
|
+
initJSDOM().then(() => {
|
|
31
|
+
setupTestEnvironment();
|
|
32
|
+
done()
|
|
33
|
+
});
|
|
44
34
|
});
|
|
45
35
|
|
|
46
36
|
after(() => {
|
|
@@ -49,17 +39,18 @@ describe('findElementWithIdUpwards', () => {
|
|
|
49
39
|
|
|
50
40
|
beforeEach(() => {
|
|
51
41
|
// Set up the DOM
|
|
52
|
-
|
|
53
|
-
|
|
42
|
+
|
|
43
|
+
let mocks = document.getElementById('mocks');
|
|
44
|
+
mocks.innerHTML = `
|
|
45
|
+
<div id="container">
|
|
54
46
|
<div id="parent">
|
|
55
47
|
<div id="child"></div>
|
|
56
48
|
</div>
|
|
57
|
-
</div
|
|
58
|
-
`;
|
|
49
|
+
</div>`;
|
|
59
50
|
|
|
60
51
|
const shadowHost = document.createElement('div');
|
|
61
52
|
document.body.appendChild(shadowHost);
|
|
62
|
-
const shadowRoot = shadowHost.attachShadow({
|
|
53
|
+
const shadowRoot = shadowHost.attachShadow({mode: 'open'});
|
|
63
54
|
const innerElement = document.createElement('div');
|
|
64
55
|
innerElement.id = 'inner';
|
|
65
56
|
shadowRoot.appendChild(innerElement);
|