@atlaskit/top-layer 0.2.0 → 0.4.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/CHANGELOG.md +35 -0
- package/dist/cjs/testing/polyfill.js +817 -0
- package/dist/cjs/testing/to-be-visible.js +92 -0
- package/dist/es2019/testing/polyfill.js +831 -0
- package/dist/es2019/testing/to-be-visible.js +85 -0
- package/dist/esm/testing/polyfill.js +815 -0
- package/dist/esm/testing/to-be-visible.js +89 -0
- package/dist/types/testing/polyfill.d.ts +25 -0
- package/dist/types/testing/to-be-visible.d.ts +23 -0
- package/dist/types-ts4.5/testing/polyfill.d.ts +25 -0
- package/dist/types-ts4.5/testing/to-be-visible.d.ts +23 -0
- package/package.json +3 -2
- package/testing/polyfill/package.json +17 -0
- package/testing/to-be-visible/package.json +17 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/* eslint-disable compat/compat */
|
|
2
|
+
/* global expect */
|
|
3
|
+
/**
|
|
4
|
+
* Patches `toBeVisible()` to understand popover and dialog visibility.
|
|
5
|
+
*
|
|
6
|
+
* jest-dom's `toBeVisible()` does not know about the Popover API. In real
|
|
7
|
+
* browsers the UA stylesheet hides `[popover]` with `display: none`, but
|
|
8
|
+
* jsdom has no such stylesheet — so closed popovers incorrectly appear visible.
|
|
9
|
+
*
|
|
10
|
+
* Raw jest-dom results in jsdom:
|
|
11
|
+
*
|
|
12
|
+
* closed popover / child → true (WRONG — should be false)
|
|
13
|
+
* open popover / child → true (correct)
|
|
14
|
+
* closed dialog / child → false (correct — jsdom natively hides <dialog>)
|
|
15
|
+
* open dialog / child → true (correct)
|
|
16
|
+
*
|
|
17
|
+
* We correct both false positives and false negatives:
|
|
18
|
+
* 1. Delegate to the original first.
|
|
19
|
+
* 2. If it says "visible" → check for closed top-layer hosts (false positive).
|
|
20
|
+
* 3. If it says "not visible" → check for open top-layer hosts (false negative).
|
|
21
|
+
*
|
|
22
|
+
* Must load via `setupFilesAfterEnv` (after jest-dom registers its matchers).
|
|
23
|
+
* Polyfills live in `./polyfill` (loaded via `setupFiles`).
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
// Delegating to jest-dom's matcher; types come from @testing-library/jest-dom.
|
|
27
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
28
|
+
import { toBeVisible as originalToBeVisible } from '@testing-library/jest-dom/matchers';
|
|
29
|
+
/**
|
|
30
|
+
* Finds the nearest popover or dialog ancestor (including the element itself)
|
|
31
|
+
* and returns its state: 'open', 'closed', or null if no top-layer ancestor exists.
|
|
32
|
+
*
|
|
33
|
+
* Checking the *nearest* ancestor handles nesting correctly:
|
|
34
|
+
* a closed popover inside an open popover → nearest is closed → not visible.
|
|
35
|
+
*/
|
|
36
|
+
function nearestTopLayerState(element) {
|
|
37
|
+
if (!element) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
if (element.hasAttribute('popover')) {
|
|
41
|
+
return element.hasAttribute('data-popover-open') ? 'open' : 'closed';
|
|
42
|
+
}
|
|
43
|
+
if (element.nodeName === 'DIALOG') {
|
|
44
|
+
return element.hasAttribute('open') ? 'open' : 'closed';
|
|
45
|
+
}
|
|
46
|
+
return nearestTopLayerState(element.parentElement);
|
|
47
|
+
}
|
|
48
|
+
function getNearestTopLayerType(element) {
|
|
49
|
+
if (!element.closest) {
|
|
50
|
+
return 'top-layer element';
|
|
51
|
+
}
|
|
52
|
+
if (element.closest('[popover]')) {
|
|
53
|
+
return 'popover';
|
|
54
|
+
}
|
|
55
|
+
return 'dialog';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// `expect` is registered globally by jest before this file runs.
|
|
59
|
+
|
|
60
|
+
expect.extend({
|
|
61
|
+
toBeVisible: function toBeVisible(element) {
|
|
62
|
+
var originalResult = originalToBeVisible.call(this, element);
|
|
63
|
+
var topLayerState = nearestTopLayerState(element);
|
|
64
|
+
if (originalResult.pass) {
|
|
65
|
+
// Original says visible — override if nearest top-layer host is closed.
|
|
66
|
+
if (topLayerState === 'closed') {
|
|
67
|
+
return {
|
|
68
|
+
pass: false,
|
|
69
|
+
message: function message() {
|
|
70
|
+
return "expected element to be visible, but it is inside a closed ".concat(getNearestTopLayerType(element));
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return originalResult;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Original says not visible — override if nearest top-layer host is open.
|
|
78
|
+
// jsdom may hide [popover] elements even when they are logically open.
|
|
79
|
+
if (topLayerState === 'open') {
|
|
80
|
+
return {
|
|
81
|
+
pass: true,
|
|
82
|
+
message: function message() {
|
|
83
|
+
return "expected element not to be visible, but it is inside an open ".concat(getNearestTopLayerType(element));
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return originalResult;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Popover API & HTMLDialogElement polyfills for jsdom.
|
|
3
|
+
*
|
|
4
|
+
* jsdom does not implement the Popover API or the HTMLDialogElement methods
|
|
5
|
+
* (showModal, show, close). This polyfill provides faithful implementations,
|
|
6
|
+
* including timing semantics validated against Chromium via Playwright.
|
|
7
|
+
*
|
|
8
|
+
* Behaviour:
|
|
9
|
+
* - beforetoggle: sync, cancelable on popover show only. toggle: async task, never cancelable.
|
|
10
|
+
* - Rapid show/hide coalesces into one toggle event (originalOldState to finalNewState).
|
|
11
|
+
* - Dialog: showModal/show fire beforetoggle+toggle. close fires toggle then close event.
|
|
12
|
+
* - Popover open state tracked via `data-popover-open` (no `:popover-open` in jsdom).
|
|
13
|
+
* - Auto popovers: maintain an open stack, perform light-dismiss on document mousedown
|
|
14
|
+
* outside the open chain, and dismiss the topmost on Escape.
|
|
15
|
+
* - On open, removes any inline `opacity: 0` from the popover element so callers that
|
|
16
|
+
* rely on a `ResizeObserver` reveal callback (e.g. `use-anchor-positioning`) become
|
|
17
|
+
* visible in jsdom, where layout-driven RO callbacks never fire.
|
|
18
|
+
*
|
|
19
|
+
* Companion `toBeVisible` patch lives at `./to-be-visible`.
|
|
20
|
+
*
|
|
21
|
+
* Importing this module has the side-effect of patching the relevant
|
|
22
|
+
* prototypes. It is safe to import multiple times; each branch is guarded
|
|
23
|
+
* to avoid overwriting native implementations or re-patching.
|
|
24
|
+
*/
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Patches `toBeVisible()` to understand popover and dialog visibility.
|
|
3
|
+
*
|
|
4
|
+
* jest-dom's `toBeVisible()` does not know about the Popover API. In real
|
|
5
|
+
* browsers the UA stylesheet hides `[popover]` with `display: none`, but
|
|
6
|
+
* jsdom has no such stylesheet — so closed popovers incorrectly appear visible.
|
|
7
|
+
*
|
|
8
|
+
* Raw jest-dom results in jsdom:
|
|
9
|
+
*
|
|
10
|
+
* closed popover / child → true (WRONG — should be false)
|
|
11
|
+
* open popover / child → true (correct)
|
|
12
|
+
* closed dialog / child → false (correct — jsdom natively hides <dialog>)
|
|
13
|
+
* open dialog / child → true (correct)
|
|
14
|
+
*
|
|
15
|
+
* We correct both false positives and false negatives:
|
|
16
|
+
* 1. Delegate to the original first.
|
|
17
|
+
* 2. If it says "visible" → check for closed top-layer hosts (false positive).
|
|
18
|
+
* 3. If it says "not visible" → check for open top-layer hosts (false negative).
|
|
19
|
+
*
|
|
20
|
+
* Must load via `setupFilesAfterEnv` (after jest-dom registers its matchers).
|
|
21
|
+
* Polyfills live in `./polyfill` (loaded via `setupFiles`).
|
|
22
|
+
*/
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Popover API & HTMLDialogElement polyfills for jsdom.
|
|
3
|
+
*
|
|
4
|
+
* jsdom does not implement the Popover API or the HTMLDialogElement methods
|
|
5
|
+
* (showModal, show, close). This polyfill provides faithful implementations,
|
|
6
|
+
* including timing semantics validated against Chromium via Playwright.
|
|
7
|
+
*
|
|
8
|
+
* Behaviour:
|
|
9
|
+
* - beforetoggle: sync, cancelable on popover show only. toggle: async task, never cancelable.
|
|
10
|
+
* - Rapid show/hide coalesces into one toggle event (originalOldState to finalNewState).
|
|
11
|
+
* - Dialog: showModal/show fire beforetoggle+toggle. close fires toggle then close event.
|
|
12
|
+
* - Popover open state tracked via `data-popover-open` (no `:popover-open` in jsdom).
|
|
13
|
+
* - Auto popovers: maintain an open stack, perform light-dismiss on document mousedown
|
|
14
|
+
* outside the open chain, and dismiss the topmost on Escape.
|
|
15
|
+
* - On open, removes any inline `opacity: 0` from the popover element so callers that
|
|
16
|
+
* rely on a `ResizeObserver` reveal callback (e.g. `use-anchor-positioning`) become
|
|
17
|
+
* visible in jsdom, where layout-driven RO callbacks never fire.
|
|
18
|
+
*
|
|
19
|
+
* Companion `toBeVisible` patch lives at `./to-be-visible`.
|
|
20
|
+
*
|
|
21
|
+
* Importing this module has the side-effect of patching the relevant
|
|
22
|
+
* prototypes. It is safe to import multiple times; each branch is guarded
|
|
23
|
+
* to avoid overwriting native implementations or re-patching.
|
|
24
|
+
*/
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Patches `toBeVisible()` to understand popover and dialog visibility.
|
|
3
|
+
*
|
|
4
|
+
* jest-dom's `toBeVisible()` does not know about the Popover API. In real
|
|
5
|
+
* browsers the UA stylesheet hides `[popover]` with `display: none`, but
|
|
6
|
+
* jsdom has no such stylesheet — so closed popovers incorrectly appear visible.
|
|
7
|
+
*
|
|
8
|
+
* Raw jest-dom results in jsdom:
|
|
9
|
+
*
|
|
10
|
+
* closed popover / child → true (WRONG — should be false)
|
|
11
|
+
* open popover / child → true (correct)
|
|
12
|
+
* closed dialog / child → false (correct — jsdom natively hides <dialog>)
|
|
13
|
+
* open dialog / child → true (correct)
|
|
14
|
+
*
|
|
15
|
+
* We correct both false positives and false negatives:
|
|
16
|
+
* 1. Delegate to the original first.
|
|
17
|
+
* 2. If it says "visible" → check for closed top-layer hosts (false positive).
|
|
18
|
+
* 3. If it says "not visible" → check for open top-layer hosts (false negative).
|
|
19
|
+
*
|
|
20
|
+
* Must load via `setupFilesAfterEnv` (after jest-dom registers its matchers).
|
|
21
|
+
* Polyfills live in `./polyfill` (loaded via `setupFiles`).
|
|
22
|
+
*/
|
|
23
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/top-layer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Low-level layering primitives based on popover and dialog",
|
|
5
5
|
"homepage": "https://atlassian.design/components/top-layer",
|
|
6
6
|
"repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
|
|
@@ -52,13 +52,14 @@
|
|
|
52
52
|
"@af/visual-regression": "workspace:^",
|
|
53
53
|
"@atlaskit/button": "^23.11.0",
|
|
54
54
|
"@atlaskit/heading": "^5.4.0",
|
|
55
|
-
"@atlaskit/lozenge": "^13.
|
|
55
|
+
"@atlaskit/lozenge": "^13.8.0",
|
|
56
56
|
"@atlaskit/primitives": "^19.0.0",
|
|
57
57
|
"@atlaskit/ssr": "workspace:^",
|
|
58
58
|
"@atlaskit/textfield": "^8.3.0",
|
|
59
59
|
"@atlassian/react-compiler-gating": "workspace:^",
|
|
60
60
|
"@atlassian/ssr-tests": "workspace:^",
|
|
61
61
|
"@atlassian/testing-library": "^0.5.0",
|
|
62
|
+
"@testing-library/jest-dom": "^6.4.5",
|
|
62
63
|
"@testing-library/react": "^16.3.0",
|
|
63
64
|
"@types/raf-schd": "^4.0.1",
|
|
64
65
|
"tiny-invariant": "^1.2.0"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/top-layer/testing/polyfill",
|
|
3
|
+
"main": "../../dist/cjs/testing/polyfill.js",
|
|
4
|
+
"module": "../../dist/esm/testing/polyfill.js",
|
|
5
|
+
"module:es2019": "../../dist/es2019/testing/polyfill.js",
|
|
6
|
+
"sideEffects": [
|
|
7
|
+
"*.compiled.css"
|
|
8
|
+
],
|
|
9
|
+
"types": "../../dist/types/testing/polyfill.d.ts",
|
|
10
|
+
"typesVersions": {
|
|
11
|
+
">=4.5 <5.9": {
|
|
12
|
+
"*": [
|
|
13
|
+
"../../dist/types-ts4.5/testing/polyfill.d.ts"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/top-layer/testing/to-be-visible",
|
|
3
|
+
"main": "../../dist/cjs/testing/to-be-visible.js",
|
|
4
|
+
"module": "../../dist/esm/testing/to-be-visible.js",
|
|
5
|
+
"module:es2019": "../../dist/es2019/testing/to-be-visible.js",
|
|
6
|
+
"sideEffects": [
|
|
7
|
+
"*.compiled.css"
|
|
8
|
+
],
|
|
9
|
+
"types": "../../dist/types/testing/to-be-visible.d.ts",
|
|
10
|
+
"typesVersions": {
|
|
11
|
+
">=4.5 <5.9": {
|
|
12
|
+
"*": [
|
|
13
|
+
"../../dist/types-ts4.5/testing/to-be-visible.d.ts"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|