@operato/layout 10.29.46 → 10.29.49

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/coverage/lcov-report/index.html +222 -177
  3. package/coverage/lcov.info +37542 -35151
  4. package/dist/src/actions/entity360-door.d.ts +28 -0
  5. package/dist/src/actions/entity360-door.js +45 -0
  6. package/dist/src/actions/entity360-door.js.map +1 -1
  7. package/dist/src/actions/entity360-registry.d.ts +13 -3
  8. package/dist/src/actions/entity360-registry.js +49 -8
  9. package/dist/src/actions/entity360-registry.js.map +1 -1
  10. package/dist/src/actions/entity360.d.ts +2 -0
  11. package/dist/src/actions/entity360.js +4 -0
  12. package/dist/src/actions/entity360.js.map +1 -1
  13. package/dist/src/actions/id-lens.d.ts +67 -0
  14. package/dist/src/actions/id-lens.js +51 -0
  15. package/dist/src/actions/id-lens.js.map +1 -0
  16. package/dist/src/actions/layout.d.ts +5 -0
  17. package/dist/src/actions/layout.js.map +1 -1
  18. package/dist/src/components/ox-entity360-dock.d.ts +18 -2
  19. package/dist/src/components/ox-entity360-dock.js +39 -17
  20. package/dist/src/components/ox-entity360-dock.js.map +1 -1
  21. package/dist/src/components/ox-id-lens.d.ts +58 -0
  22. package/dist/src/components/ox-id-lens.js +362 -0
  23. package/dist/src/components/ox-id-lens.js.map +1 -0
  24. package/dist/src/index.d.ts +1 -0
  25. package/dist/src/index.js +1 -0
  26. package/dist/src/index.js.map +1 -1
  27. package/dist/src/layouts/ox-aside-bar.js +134 -6
  28. package/dist/src/layouts/ox-aside-bar.js.map +1 -1
  29. package/dist/test/entity360-companion.test.d.ts +1 -0
  30. package/dist/test/entity360-companion.test.js +127 -0
  31. package/dist/test/entity360-companion.test.js.map +1 -0
  32. package/dist/test/entity360-kind.test.js +136 -10
  33. package/dist/test/entity360-kind.test.js.map +1 -1
  34. package/dist/test/entity360-section.test.js +31 -1
  35. package/dist/test/entity360-section.test.js.map +1 -1
  36. package/dist/test/entity360.test.js +29 -6
  37. package/dist/test/entity360.test.js.map +1 -1
  38. package/dist/test/id-lens.test.d.ts +2 -0
  39. package/dist/test/id-lens.test.js +162 -0
  40. package/dist/test/id-lens.test.js.map +1 -0
  41. package/dist/tsconfig.tsbuildinfo +1 -1
  42. package/package.json +11 -6
  43. package/test/entity360-companion.test.ts +110 -0
  44. package/test/entity360-kind.test.ts +145 -11
  45. package/test/entity360-section.test.ts +34 -1
  46. package/test/entity360.test.ts +31 -6
  47. package/test/id-lens.test.ts +198 -0
@@ -1 +1 @@
1
- {"version":3,"file":"ox-aside-bar.js","sourceRoot":"","sources":["../../../src/layouts/ox-aside-bar.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/popup/ox-floating-overlay.js'\nimport '../components/ox-resize-splitter.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { customElement, property } from 'lit/decorators.js'\nimport { LayoutController } from '@operato/shell'\n\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { Viewpart, VIEWPART_LEVEL } from '../actions/layout.js'\n\n@customElement('ox-aside-bar')\nclass AsideBar extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-flow: row-reverse nowrap;\n align-items: stretch;\n\n position: relative;\n }\n\n *[asidebar] {\n display: block;\n overflow-y: auto;\n }\n `\n ]\n\n private _layout = new LayoutController(this)\n\n @property({ type: Boolean, attribute: 'fullbleed' }) fullbleed: boolean = false\n\n private _startWidth: number = 0\n\n render() {\n var viewparts = this._layout.viewparts\n var asidebars = Object.keys(viewparts)\n .map(name => {\n return {\n name,\n ...viewparts[name]\n }\n })\n .filter(viewpart => viewpart.position == 'asidebar' && (!this.fullbleed || viewpart.hovering || viewpart.persistent))\n\n asidebars = [\n ...asidebars.filter(viewpart => viewpart.level == VIEWPART_LEVEL.TOPMOST),\n ...asidebars.filter(viewpart => viewpart.level !== VIEWPART_LEVEL.TOPMOST)\n ]\n\n return html`\n ${asidebars.map(asidebar =>\n !asidebar.show\n ? html``\n : asidebar.hovering\n ? html`\n <ox-floating-overlay\n .backdrop=${asidebar.backdrop}\n direction=\"left\"\n .hovering=${asidebar.hovering}\n .name=${asidebar.name}\n .size=${asidebar.size}\n .title=${asidebar.title}\n .help=${asidebar.help}\n .closable=${asidebar.closable}\n .templateProperties=${asidebar.templateProperties}\n .historical=${true}\n .search=${asidebar.search}\n .movable=${asidebar.movable}\n .escapable=${asidebar.escapable !== false}\n .filter=${asidebar.filter}\n z-index=${ifDefined(asidebar.zIndex)}\n >${asidebar.template}</ox-floating-overlay\n >\n `\n : html`\n <div asidebar>${asidebar.template}</div>\n ${asidebar.resizable\n ? html`\n <ox-resize-splitter\n @splitter-dragstart=${(e: CustomEvent) => this.resizeStart(e)}\n @splitter-drag=${(e: CustomEvent) => this.resizeDrag(e)}\n vertical\n ></ox-resize-splitter>\n `\n : html``}\n `\n )}\n `\n }\n\n resizeStart(e: CustomEvent) {\n this._startWidth = ((e.target as HTMLElement)?.previousElementSibling as HTMLElement)?.offsetWidth\n }\n\n resizeDrag(e: CustomEvent) {\n var delta = e.detail\n\n var x = ((e.target as HTMLElement)?.previousElementSibling as HTMLElement)?.children\n Array.from(x).forEach(ele => {\n ;(ele as HTMLElement).style.width = `${this._startWidth - delta.x}px`\n })\n }\n\n}\n"]}
1
+ {"version":3,"file":"ox-aside-bar.js","sourceRoot":"","sources":["../../../src/layouts/ox-aside-bar.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/popup/ox-floating-overlay.js'\nimport '../components/ox-resize-splitter.js'\n\nimport { css, html, LitElement, nothing } from 'lit'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { LayoutController } from '@operato/shell'\n\nimport { i18next } from '@operato/i18n'\nimport type { OxEntity360Dock } from '../components/ox-entity360-dock.js'\nimport { ButtonStyles, ScrollbarStyles } from '@operato/styles'\n\nimport { Viewpart, VIEWPART_LEVEL } from '../actions/layout.js'\n\n@customElement('ox-aside-bar')\nclass AsideBar extends LitElement {\n static styles = [\n ScrollbarStyles, ButtonStyles,\n css`\n :host {\n display: flex;\n flex-flow: row-reverse nowrap;\n align-items: stretch;\n\n position: relative;\n }\n\n :host([shared-fullscreen]) {\n position: fixed; inset: 0; width: 100vw; height: 100dvh; z-index: 901;\n display: grid; grid-template-columns: minmax(0, 1fr) 420px; grid-template-rows: minmax(0, 1fr);\n background: var(--md-sys-color-surface, white); color: var(--md-sys-color-on-surface, #222);\n }\n :host([shared-fullscreen]) [asidebar] { min-width: 0; min-height: 0; overflow: hidden; }\n :host([shared-fullscreen]) [workspace-main] { grid-column: 1; grid-row: 1; }\n :host([shared-fullscreen]) [workspace-companion] { grid-column: 2; grid-row: 1; }\n :host([shared-fullscreen]) [workspace-companion] > * {\n position: relative; inset: auto; width: 100%; max-width: none; height: 100%; z-index: auto;\n }\n [hidden] { display: none !important; }\n .workspace-switch { display: none; }\n @media (max-width: 1023.98px) {\n :host([shared-fullscreen]) { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }\n :host([shared-fullscreen]) [workspace-main], :host([shared-fullscreen]) [workspace-companion] { grid-column: 1; grid-row: 2; }\n .workspace-switch { display: flex; gap: var(--spacing-small, 4px); padding: var(--spacing-small, 4px); min-width: 0; border-bottom: 1px solid var(--ui-line, #ccc); }\n .workspace-switch button { min-width: 0; max-width: 50%; white-space: normal; overflow-wrap: anywhere; }\n .workspace-switch button[aria-pressed=true] { background: var(--md-sys-color-secondary-container, #ddd); }\n }\n\n *[asidebar] {\n display: block;\n overflow-y: auto;\n }\n `\n ]\n\n private _layout = new LayoutController(this)\n\n @property({ type: Boolean, attribute: 'fullbleed' }) fullbleed: boolean = false\n\n private _startWidth: number = 0\n @state() private expandedDock?: OxEntity360Dock\n @state() private pane: 'main' | 'companion' = 'main'\n @state() private compact = matchMedia('(max-width: 1023.98px)').matches\n private media = matchMedia('(max-width: 1023.98px)')\n private shared = false\n private companionName?: string\n private revealCompanion = false\n private onPresentation = (event: Event) => {\n this.expandedDock = event.composedPath()[0] as OxEntity360Dock\n this.requestUpdate()\n }\n private onMedia = () => { this.compact = this.media.matches }\n private onFocus = (event: Event) => {\n if (!this.shared) return\n const path = event.composedPath()\n if (path.some(one => (one as Element).hasAttribute?.('workspace-companion'))) this.pane = 'companion'\n else if (path.some(one => (one as Element).hasAttribute?.('workspace-main'))) this.pane = 'main'\n }\n private onKey = (event: KeyboardEvent) => {\n if (!this.shared || event.defaultPrevented) return\n // An actual overlay above the workspace owns its keys. The supporting dock is itself an overlay entry.\n if (history.state?.overlay && history.state.overlay.name !== this.companionName) return\n if (event.key === 'Escape') {\n if (event.composedPath().includes(this.expandedDock!)) { event.preventDefault(); this.expandedDock?.view?.onClose() }\n return\n }\n if (event.key !== 'Tab') return\n const walk = (root: ParentNode): HTMLElement[] => Array.from(root.querySelectorAll<HTMLElement>('*'))\n .flatMap(el => [el, ...(el.shadowRoot ? walk(el.shadowRoot) : [])])\n // Follow visual order: switch, primary work, supporting conversation. No background controls are reached.\n const roots = ['.workspace-switch', '[workspace-main]', '[workspace-companion]'].map(selector => this.renderRoot.querySelector(selector)).filter(Boolean) as HTMLElement[]\n const controls = roots.flatMap(root => root.hidden ? [] : walk(root)).filter(el =>\n el.matches('button,a[href],input,select,textarea,summary,[tabindex]') && el.tabIndex >= 0 &&\n !el.hasAttribute('disabled') && !el.closest('[inert]') && el.getClientRects().length && getComputedStyle(el).visibility !== 'hidden')\n if (!controls.length) return\n const index = controls.indexOf(event.composedPath()[0] as HTMLElement)\n event.preventDefault()\n controls[index < 0 ? (event.shiftKey ? controls.length - 1 : 0) : (index + (event.shiftKey ? -1 : 1) + controls.length) % controls.length].focus()\n }\n connectedCallback() {\n super.connectedCallback()\n this.addEventListener('entity360-presentation', this.onPresentation)\n this.renderRoot.addEventListener('focusin', this.onFocus)\n this.media.addEventListener('change', this.onMedia)\n document.addEventListener('keydown', this.onKey)\n }\n disconnectedCallback() {\n this.expandedDock && (this.expandedDock.contained = false)\n this.removeEventListener('entity360-presentation', this.onPresentation)\n this.renderRoot.removeEventListener('focusin', this.onFocus)\n this.media.removeEventListener('change', this.onMedia)\n document.removeEventListener('keydown', this.onKey)\n super.disconnectedCallback()\n }\n updated() {\n this.toggleAttribute('shared-fullscreen', this.shared)\n if (this.shared) {\n this.setAttribute('role', 'dialog')\n this.setAttribute('aria-modal', 'true')\n this.setAttribute('aria-label', this.expandedDock?.view?.title ?? '')\n } else {\n this.removeAttribute('role'); this.removeAttribute('aria-modal'); this.removeAttribute('aria-label')\n }\n if (this.expandedDock) this.expandedDock.contained = this.shared\n if (this.revealCompanion) {\n this.revealCompanion = false\n this.pane = 'companion'\n void this.updateComplete.then(() => this.renderRoot.querySelectorAll<HTMLButtonElement>('.workspace-switch button')[1]?.focus())\n }\n }\n\n render() {\n var viewparts = this._layout.viewparts\n var asidebars = Object.keys(viewparts)\n .map(name => {\n return {\n name,\n ...viewparts[name]\n }\n })\n .filter(viewpart => viewpart.position == 'asidebar' && (!this.fullbleed || viewpart.hovering || viewpart.persistent))\n\n asidebars = [\n ...asidebars.filter(viewpart => viewpart.level == VIEWPART_LEVEL.TOPMOST),\n ...asidebars.filter(viewpart => viewpart.level !== VIEWPART_LEVEL.TOPMOST)\n ]\n\n const companion = asidebars.find(one => one.show && !one.hovering && one.expansionCompanion)\n const main = asidebars.find(one => one.show && !one.hovering && one.name === 'entity360')\n this.shared = !!(main && companion && this.expandedDock?.isConnected && this.expandedDock.fullscreen)\n this.revealCompanion = this.shared && this.compact && !!companion && this.companionName !== companion.name\n this.companionName = companion?.name\n return html`\n ${this.shared ? html`<nav class=\"workspace-switch\">\n <button quiet small aria-pressed=${this.pane === 'main'} @click=${() => this.pane = 'main'}>${this.expandedDock?.view?.title}</button>\n <button quiet small aria-pressed=${this.pane === 'companion'} @click=${() => this.pane = 'companion'}>${i18next.t(companion!.expansionCompanion!.labelKey, { defaultValue: companion!.expansionCompanion!.defaultLabel })}</button>\n </nav>` : nothing}\n ${asidebars.map(asidebar =>\n !asidebar.show\n ? html``\n : asidebar.hovering\n ? html`\n <ox-floating-overlay\n .backdrop=${asidebar.backdrop}\n direction=\"left\"\n .hovering=${asidebar.hovering}\n .name=${asidebar.name}\n .size=${asidebar.size}\n .title=${asidebar.title}\n .help=${asidebar.help}\n .closable=${asidebar.closable}\n .templateProperties=${asidebar.templateProperties}\n .historical=${true}\n .search=${asidebar.search}\n .movable=${asidebar.movable}\n .escapable=${asidebar.escapable !== false}\n .filter=${asidebar.filter}\n z-index=${ifDefined(asidebar.zIndex)}\n >${asidebar.template}</ox-floating-overlay\n >\n `\n : html`\n <div asidebar\n ?workspace-main=${asidebar.name === main?.name}\n ?workspace-companion=${asidebar.name === companion?.name}\n ?hidden=${this.shared && (asidebar.name !== main?.name && asidebar.name !== companion?.name || this.compact && (this.pane === 'main' ? asidebar.name !== main?.name : asidebar.name !== companion?.name))}\n >${asidebar.template}</div>\n ${asidebar.resizable && !this.shared\n ? html`\n <ox-resize-splitter\n @splitter-dragstart=${(e: CustomEvent) => this.resizeStart(e)}\n @splitter-drag=${(e: CustomEvent) => this.resizeDrag(e)}\n vertical\n ></ox-resize-splitter>\n `\n : html``}\n `\n )}\n `\n }\n\n resizeStart(e: CustomEvent) {\n this._startWidth = ((e.target as HTMLElement)?.previousElementSibling as HTMLElement)?.offsetWidth\n }\n\n resizeDrag(e: CustomEvent) {\n var delta = e.detail\n\n var x = ((e.target as HTMLElement)?.previousElementSibling as HTMLElement)?.children\n Array.from(x).forEach(ele => {\n ;(ele as HTMLElement).style.width = `${this._startWidth - delta.x}px`\n })\n }\n\n}\n"]}
@@ -0,0 +1 @@
1
+ import '../src/index.js';
@@ -0,0 +1,127 @@
1
+ import { expect, fixture, elementUpdated } from '@open-wc/testing';
2
+ import { css, html, LitElement } from 'lit';
3
+ import { setViewport } from '@web/test-runner-commands';
4
+ import '../src/index.js';
5
+ import { appendViewpart, removeViewpart, showEntity360, hideEntity360, VIEWPART_POSITION, VIEWPART_LEVEL } from '../src/index.js';
6
+ class CompanionProbe extends LitElement {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.connections = 0;
10
+ }
11
+ connectedCallback() { super.connectedCallback(); this.connections++; }
12
+ render() { return html `<textarea aria-label="Conversation"></textarea><button>Send</button>`; }
13
+ }
14
+ CompanionProbe.styles = css `:host { display: flex; flex-direction: column; width: 420px; height: 100%; }`;
15
+ customElements.define('test-companion-probe', CompanionProbe);
16
+ const owner = {};
17
+ const labels = { close: 'Close', expand: 'Expand', collapse: 'Collapse', resize: 'Resize', back: 'Back' };
18
+ const settle = () => new Promise(resolve => setTimeout(resolve, 60));
19
+ let bar, companion, dock;
20
+ const input = () => dock.shadowRoot.querySelector('ox-entity360-content').shadowRoot.querySelector('input');
21
+ const textarea = () => companion.shadowRoot.querySelector('textarea');
22
+ const openCompanion = () => appendViewpart({ name: 'test-companion', position: VIEWPART_POSITION.ASIDEBAR, viewpart: { show: true, persistent: true, level: VIEWPART_LEVEL.TOPMOST, expansionCompanion: { labelKey: 'test.conversation', defaultLabel: 'Conversation' }, template: html `${companion}` } });
23
+ describe('expanded entity workspace with a supporting dock', () => {
24
+ beforeEach(async () => {
25
+ await setViewport({ width: 1440, height: 900 });
26
+ bar = await fixture(html `<ox-aside-bar></ox-aside-bar>`);
27
+ companion = document.createElement('test-companion-probe');
28
+ openCompanion();
29
+ showEntity360(owner, { key: 'one', title: 'Contract', context: 'same subject', labels, content: html `<input value="initial">`, onClose: () => hideEntity360(owner) });
30
+ await settle();
31
+ dock = bar.shadowRoot.querySelector('ox-entity360-dock');
32
+ });
33
+ afterEach(async () => { hideEntity360(owner); removeViewpart('test-companion'); await setViewport({ width: 800, height: 600 }); });
34
+ it('shares the expanded width without recreating either editor or changing its values', async () => {
35
+ const originalInput = input(), originalChat = textarea(), connections = companion.connections;
36
+ originalInput.value = 'allocation draft';
37
+ originalChat.value = 'question draft';
38
+ dock.expanded = true;
39
+ await settle();
40
+ expect(bar.hasAttribute('shared-fullscreen')).to.equal(true);
41
+ expect(bar.getAttribute('aria-modal')).to.equal('true');
42
+ expect(dock.shadowRoot.querySelector('[aria-modal]')).to.equal(null);
43
+ const main = dock.getBoundingClientRect(), chat = companion.getBoundingClientRect();
44
+ expect(main.width).to.equal(1020);
45
+ expect(chat.width).to.equal(420);
46
+ expect(main.right).to.equal(chat.left);
47
+ dock.expanded = false;
48
+ await settle();
49
+ expect(input()).to.equal(originalInput);
50
+ expect(textarea()).to.equal(originalChat);
51
+ expect(originalInput.value).to.equal('allocation draft');
52
+ expect(originalChat.value).to.equal('question draft');
53
+ expect(companion.connections).to.equal(connections);
54
+ expect(bar.hasAttribute('shared-fullscreen')).to.equal(false);
55
+ });
56
+ it('Tab crosses from the last main control into the conversation and returns with Shift+Tab', async () => {
57
+ dock.expanded = true;
58
+ await settle();
59
+ input().focus();
60
+ input().dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab', bubbles: true, composed: true, cancelable: true }));
61
+ expect(companion.shadowRoot.activeElement).to.equal(textarea());
62
+ textarea().dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab', shiftKey: true, bubbles: true, composed: true, cancelable: true }));
63
+ expect(input().getRootNode() instanceof ShadowRoot && input().getRootNode().activeElement).to.equal(input());
64
+ });
65
+ it('narrowing keeps the focused conversation visible, then switches panes without disconnecting it', async () => {
66
+ dock.expanded = true;
67
+ await settle();
68
+ textarea().value = 'still writing';
69
+ textarea().focus();
70
+ expect(bar.pane).to.equal('companion', 'focused pane remembered');
71
+ const connections = companion.connections;
72
+ await setViewport({ width: 390, height: 844 });
73
+ await settle();
74
+ expect(companion.getBoundingClientRect().width).to.equal(390);
75
+ expect(dock.getBoundingClientRect().width).to.equal(0);
76
+ const switches = bar.shadowRoot.querySelectorAll('.workspace-switch button');
77
+ switches[0].click();
78
+ await settle();
79
+ expect(dock.getBoundingClientRect().width).to.equal(390);
80
+ expect(companion.getBoundingClientRect().width).to.equal(0);
81
+ switches[1].click();
82
+ await settle();
83
+ expect(textarea().value).to.equal('still writing');
84
+ expect(companion.connections).to.equal(connections);
85
+ await setViewport({ width: 1440, height: 900 });
86
+ await settle();
87
+ expect(dock.getBoundingClientRect().width).to.equal(1020);
88
+ });
89
+ it('closing the companion gives the full width back; expansion does not open it again', async () => {
90
+ dock.expanded = true;
91
+ await settle();
92
+ removeViewpart('test-companion');
93
+ await settle();
94
+ expect(dock.contained).to.equal(false);
95
+ expect(dock.getBoundingClientRect().width).to.equal(1440);
96
+ dock.expanded = false;
97
+ await elementUpdated(dock);
98
+ dock.expanded = true;
99
+ await settle();
100
+ expect(bar.shadowRoot.querySelector('test-companion-probe')).to.equal(null);
101
+ });
102
+ it('explicitly opening a companion in a narrow expanded workspace reveals it', async () => {
103
+ removeViewpart('test-companion');
104
+ await settle();
105
+ dock.expanded = true;
106
+ await setViewport({ width: 390, height: 844 });
107
+ await settle();
108
+ openCompanion();
109
+ await settle();
110
+ expect(companion.getBoundingClientRect().width).to.equal(390);
111
+ expect(dock.getBoundingClientRect().width).to.equal(0);
112
+ expect(bar.shadowRoot.activeElement).to.equal(bar.shadowRoot.querySelectorAll('.workspace-switch button')[1]);
113
+ });
114
+ it('a modal above the shared workspace keeps ownership of Tab and Escape', async () => {
115
+ dock.expanded = true;
116
+ await settle();
117
+ const state = history.state;
118
+ history.replaceState({ ...state, overlay: { name: 'confirmation' } }, '');
119
+ const tab = new KeyboardEvent('keydown', { key: 'Tab', bubbles: true, composed: true, cancelable: true });
120
+ input().dispatchEvent(tab);
121
+ expect(tab.defaultPrevented).to.equal(false);
122
+ input().dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true, composed: true, cancelable: true }));
123
+ expect(dock.isConnected).to.equal(true);
124
+ history.replaceState(state, '');
125
+ });
126
+ });
127
+ //# sourceMappingURL=entity360-companion.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity360-companion.test.js","sourceRoot":"","sources":["../../test/entity360-companion.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture, elementUpdated } from '@open-wc/testing'\nimport { css, html, LitElement } from 'lit'\nimport { setViewport } from '@web/test-runner-commands'\nimport '../src/index.js'\nimport { appendViewpart, removeViewpart, showEntity360, hideEntity360, VIEWPART_POSITION, VIEWPART_LEVEL, type OxEntity360Dock } from '../src/index.js'\n\nclass CompanionProbe extends LitElement {\n static styles = css`:host { display: flex; flex-direction: column; width: 420px; height: 100%; }`\n connections = 0\n connectedCallback() { super.connectedCallback(); this.connections++ }\n render() { return html`<textarea aria-label=\"Conversation\"></textarea><button>Send</button>` }\n}\ncustomElements.define('test-companion-probe', CompanionProbe)\nconst owner = {}\nconst labels = { close:'Close', expand:'Expand', collapse:'Collapse', resize:'Resize', back:'Back' }\nconst settle = () => new Promise(resolve => setTimeout(resolve, 60))\nlet bar: HTMLElement, companion: CompanionProbe, dock: OxEntity360Dock\nconst input = () => dock.shadowRoot!.querySelector('ox-entity360-content')!.shadowRoot!.querySelector('input')!\nconst textarea = () => companion.shadowRoot!.querySelector('textarea')!\nconst openCompanion = () => appendViewpart({ name:'test-companion', position:VIEWPART_POSITION.ASIDEBAR, viewpart:{ show:true, persistent:true, level:VIEWPART_LEVEL.TOPMOST, expansionCompanion:{labelKey:'test.conversation',defaultLabel:'Conversation'}, template:html`${companion}` } })\n\ndescribe('expanded entity workspace with a supporting dock', () => {\n beforeEach(async () => {\n await setViewport({ width:1440,height:900 })\n bar = await fixture(html`<ox-aside-bar></ox-aside-bar>`)\n companion = document.createElement('test-companion-probe') as CompanionProbe\n openCompanion()\n showEntity360(owner, { key:'one', title:'Contract', context:'same subject', labels, content:html`<input value=\"initial\">`, onClose:()=>hideEntity360(owner) })\n await settle()\n dock = bar.shadowRoot!.querySelector('ox-entity360-dock') as OxEntity360Dock\n })\n afterEach(async () => { hideEntity360(owner); removeViewpart('test-companion'); await setViewport({width:800,height:600}) })\n\n it('shares the expanded width without recreating either editor or changing its values', async () => {\n const originalInput = input(), originalChat = textarea(), connections = companion.connections\n originalInput.value='allocation draft'; originalChat.value='question draft'\n dock.expanded=true; await settle()\n expect(bar.hasAttribute('shared-fullscreen')).to.equal(true)\n expect(bar.getAttribute('aria-modal')).to.equal('true')\n expect(dock.shadowRoot!.querySelector('[aria-modal]')).to.equal(null)\n const main = dock.getBoundingClientRect(), chat = companion.getBoundingClientRect()\n expect(main.width).to.equal(1020); expect(chat.width).to.equal(420)\n expect(main.right).to.equal(chat.left)\n dock.expanded=false; await settle()\n expect(input()).to.equal(originalInput); expect(textarea()).to.equal(originalChat)\n expect(originalInput.value).to.equal('allocation draft'); expect(originalChat.value).to.equal('question draft')\n expect(companion.connections).to.equal(connections)\n expect(bar.hasAttribute('shared-fullscreen')).to.equal(false)\n })\n\n it('Tab crosses from the last main control into the conversation and returns with Shift+Tab', async () => {\n dock.expanded=true; await settle()\n input().focus()\n input().dispatchEvent(new KeyboardEvent('keydown',{key:'Tab',bubbles:true,composed:true,cancelable:true}))\n expect(companion.shadowRoot!.activeElement).to.equal(textarea())\n textarea().dispatchEvent(new KeyboardEvent('keydown',{key:'Tab',shiftKey:true,bubbles:true,composed:true,cancelable:true}))\n expect(input().getRootNode() instanceof ShadowRoot && (input().getRootNode() as ShadowRoot).activeElement).to.equal(input())\n })\n\n it('narrowing keeps the focused conversation visible, then switches panes without disconnecting it', async () => {\n dock.expanded=true; await settle()\n textarea().value='still writing'; textarea().focus()\n expect((bar as any).pane).to.equal('companion', 'focused pane remembered')\n const connections=companion.connections\n await setViewport({width:390,height:844}); await settle()\n expect(companion.getBoundingClientRect().width).to.equal(390)\n expect(dock.getBoundingClientRect().width).to.equal(0)\n const switches=bar.shadowRoot!.querySelectorAll<HTMLButtonElement>('.workspace-switch button')\n switches[0].click(); await settle()\n expect(dock.getBoundingClientRect().width).to.equal(390)\n expect(companion.getBoundingClientRect().width).to.equal(0)\n switches[1].click(); await settle()\n expect(textarea().value).to.equal('still writing')\n expect(companion.connections).to.equal(connections)\n await setViewport({width:1440,height:900}); await settle()\n expect(dock.getBoundingClientRect().width).to.equal(1020)\n })\n\n it('closing the companion gives the full width back; expansion does not open it again', async () => {\n dock.expanded=true; await settle()\n removeViewpart('test-companion'); await settle()\n expect(dock.contained).to.equal(false)\n expect(dock.getBoundingClientRect().width).to.equal(1440)\n dock.expanded=false; await elementUpdated(dock)\n dock.expanded=true; await settle()\n expect(bar.shadowRoot!.querySelector('test-companion-probe')).to.equal(null)\n })\n\n it('explicitly opening a companion in a narrow expanded workspace reveals it', async () => {\n removeViewpart('test-companion'); await settle()\n dock.expanded=true\n await setViewport({width:390,height:844}); await settle()\n openCompanion(); await settle()\n expect(companion.getBoundingClientRect().width).to.equal(390)\n expect(dock.getBoundingClientRect().width).to.equal(0)\n expect(bar.shadowRoot!.activeElement).to.equal(bar.shadowRoot!.querySelectorAll('.workspace-switch button')[1])\n })\n\n it('a modal above the shared workspace keeps ownership of Tab and Escape', async () => {\n dock.expanded=true; await settle()\n const state=history.state\n history.replaceState({...state,overlay:{name:'confirmation'}},'')\n const tab=new KeyboardEvent('keydown',{key:'Tab',bubbles:true,composed:true,cancelable:true})\n input().dispatchEvent(tab)\n expect(tab.defaultPrevented).to.equal(false)\n input().dispatchEvent(new KeyboardEvent('keydown',{key:'Escape',bubbles:true,composed:true,cancelable:true}))\n expect(dock.isConnected).to.equal(true)\n history.replaceState(state,'')\n })\n})\n"]}
@@ -1,8 +1,9 @@
1
1
  import { expect, fixture } from '@open-wc/testing';
2
- import { html, render } from 'lit';
2
+ import { html, render, LitElement } from 'lit';
3
+ import { OxPrompt } from '@operato/popup/ox-prompt.js';
3
4
  import { store, UPDATE_CONTEXT } from '@operato/shell';
4
5
  import '../src/index.js';
5
- import { closeEntity360, entity360Link, onEntity360Change, openEntity360Kind, redrawEntity360, registerEntity360Kind } from '../src/index.js';
6
+ import { closeEntity360, entity360Link, onEntity360Change, openEntity360Kind, registerEntity360Kind, registerEntity360Section, setEntity360Value, ENTITY360_UNKEPT } from '../src/index.js';
6
7
  /**
7
8
  * A 360 opened by kind and id, the dock's own back trail, and the assistant subject it stands in for.
8
9
  *
@@ -17,14 +18,42 @@ const back = (go = () => history.back()) => new Promise(resolve => {
17
18
  go();
18
19
  });
19
20
  let bar;
21
+ /**
22
+ * Links drawn straight into the page. `fixture` waits for an animation frame, and a page the runner keeps in the
23
+ * background (files run side by side) may not get one before the test times out.
24
+ */
25
+ const drawn = (template) => {
26
+ const host = document.body.appendChild(document.createElement('div'));
27
+ render(template, host);
28
+ return host;
29
+ };
20
30
  const dock = () => bar.shadowRoot.querySelector('ox-entity360-dock');
21
31
  const subject = () => { var _a, _b; return (_b = (_a = store.getState().route) === null || _a === void 0 ? void 0 : _a.context) === null || _b === void 0 ? void 0 : _b.subject; };
22
32
  const address = () => new URLSearchParams(location.search).get('f');
23
33
  registerEntity360Kind({ kind: 'kx-order', typenames: [], title: s => `order ${s.id}`, assistantSubject: true });
24
34
  registerEntity360Kind({ kind: 'kx-place', typenames: [], title: s => `place ${s.id}`, assistantSubject: true });
25
35
  registerEntity360Kind({ kind: 'kx-quiet', typenames: [], title: s => `quiet ${s.id}` });
26
- let late = '';
27
- registerEntity360Kind({ kind: 'kx-late', typenames: [], title: s => late || s.id });
36
+ registerEntity360Kind({ kind: 'kx-late', typenames: [], title: s => s.value.name || s.id });
37
+ /* A kind whose one identifier is its name, the way a lot is (ADR-0067 decision 6). */
38
+ registerEntity360Kind({ kind: 'kx-lot', typenames: ['KxLot'], id: value => value.name, title: s => s.value.name || s.id });
39
+ /** A section the way modules write one: it takes the subject and reads whenever the subject changes. */
40
+ const reads = [];
41
+ class KxSection extends LitElement {
42
+ createRenderRoot() {
43
+ return this;
44
+ }
45
+ updated(changed) {
46
+ if (changed.has('subject') && this.subject)
47
+ reads.push({ section: this, subject: this.subject });
48
+ }
49
+ render() {
50
+ return html `<input />`;
51
+ }
52
+ }
53
+ KxSection.properties = { subject: { attribute: false } };
54
+ customElements.define('kx-section', KxSection);
55
+ registerEntity360Section('kx-lot', { name: 'facts', render: subject => html `<kx-section .subject=${subject}></kx-section>` });
56
+ const section = () => dock().shadowRoot.querySelector('ox-entity360-content').shadowRoot.querySelector('kx-section');
28
57
  describe('entity 360 by kind', () => {
29
58
  beforeEach(async () => {
30
59
  history.replaceState(null, '', location.pathname);
@@ -41,7 +70,7 @@ describe('entity 360 by kind', () => {
41
70
  expect(host.textContent).to.include('X-1');
42
71
  });
43
72
  it('★ a click on the link opens that kind with that id', async () => {
44
- const host = await fixture(html `<div>${entity360Link('kx-order', 'SO-2')}</div>`);
73
+ const host = drawn(html `${entity360Link('kx-order', 'SO-2')}`);
45
74
  host.querySelector('a').click();
46
75
  await settle();
47
76
  expect(dock().view.title).to.equal('order SO-2');
@@ -116,21 +145,118 @@ describe('entity 360 by kind', () => {
116
145
  expect(dock()).to.equal(null);
117
146
  expect(address()).to.equal(null);
118
147
  });
119
- it('redraw reads the title again - for a title its section learns later', async () => {
120
- late = '';
148
+ it('★ what a section reads names the subject: the heading is drawn from it, the sections stay', async () => {
149
+ openEntity360Kind('kx-lot', { id: 'L-9', name: 'L-9' });
150
+ await settle();
151
+ expect(dock().view.title).to.equal('L-9');
152
+ const first = section();
153
+ setEntity360Value({ kind: 'kx-lot', id: 'L-9' }, { name: 'L-9', definitionId: 'M-1' });
121
154
  openEntity360Kind('kx-late', { id: 'X-9' });
122
155
  await settle();
123
156
  expect(dock().view.title).to.equal('X-9');
124
- late = 'named later';
125
- redrawEntity360();
157
+ setEntity360Value({ kind: 'kx-late', id: 'X-9' }, { name: 'named later' });
126
158
  await settle();
127
159
  expect(dock().view.title).to.equal('named later');
160
+ expect(first.isConnected).to.equal(false);
161
+ });
162
+ it('★ a kind that declares its identifier: a typed value, a link and the address all open the same subject', async () => {
163
+ reads.length = 0;
164
+ const host = drawn(html `${entity360Link('kx-lot', 'L-1')}`);
165
+ host.querySelector('a').click();
166
+ await settle();
167
+ expect(address()).to.equal('kx-lot:L-1');
168
+ dock().view.onClose();
169
+ await settle();
170
+ openEntity360Kind('kx-lot', { __typename: 'KxLot', id: '0c9e-uuid', name: 'L-1' });
171
+ await settle();
172
+ expect(address()).to.equal('kx-lot:L-1');
173
+ expect(reads.map(read => read.subject.id)).to.deep.equal(['L-1', 'L-1']);
174
+ });
175
+ it('★ a shared link brings only the id - the sections still read by it', async () => {
176
+ var _a, _b;
177
+ reads.length = 0;
178
+ const url = new URL(location.href);
179
+ url.searchParams.set('f', 'kx-lot:L-shared');
180
+ history.pushState(null, '', url);
181
+ window.dispatchEvent(new PopStateEvent('popstate', { state: null }));
182
+ await settle();
183
+ expect(dock().view.title).to.equal('L-shared');
184
+ expect((_a = reads[reads.length - 1]) === null || _a === void 0 ? void 0 : _a.subject).to.deep.include({ kind: 'kx-lot', id: 'L-shared' });
185
+ expect((_b = reads[reads.length - 1]) === null || _b === void 0 ? void 0 : _b.subject.value).to.deep.equal({ id: 'L-shared' });
186
+ });
187
+ it('★ refresh gives the sections a new subject of the same id; they read again and are not made anew', async () => {
188
+ openEntity360Kind('kx-lot', { id: 'L-2', name: 'L-2' });
189
+ await settle();
190
+ const before = section();
191
+ const input = before.querySelector('input');
192
+ input.value = 'typed';
193
+ reads.length = 0;
194
+ dock().view.onRefresh();
195
+ await settle();
196
+ expect(section()).to.equal(before);
197
+ expect(input.value).to.equal('typed');
198
+ expect(reads.length).to.equal(1);
199
+ expect(reads[0].subject.id).to.equal('L-2');
200
+ });
201
+ it('★ leaving a subject whose entry no draft keeps is asked about; keeping it stays put', async () => {
202
+ const open = OxPrompt.open;
203
+ let asked = 0;
204
+ let answer = false;
205
+ OxPrompt.open = async () => (asked++, answer);
206
+ try {
207
+ openEntity360Kind('kx-lot', { id: 'L-3', name: 'L-3' });
208
+ await settle();
209
+ const input = section().querySelector('input');
210
+ input.dispatchEvent(new CustomEvent(ENTITY360_UNKEPT, { bubbles: true, composed: true, detail: { unkept: true } }));
211
+ openEntity360Kind('kx-lot', { id: 'L-4', name: 'L-4' });
212
+ await settle();
213
+ expect(asked).to.equal(1);
214
+ expect(address()).to.equal('kx-lot:L-3');
215
+ expect(input.isConnected).to.equal(true);
216
+ answer = true;
217
+ openEntity360Kind('kx-lot', { id: 'L-4', name: 'L-4' });
218
+ await settle();
219
+ expect(asked).to.equal(2);
220
+ expect(address()).to.equal('kx-lot:L-4');
221
+ }
222
+ finally {
223
+ ;
224
+ OxPrompt.open = open;
225
+ }
226
+ });
227
+ it('★ opening the subject already shown does not hand the sections a new subject', async () => {
228
+ const url = new URL(location.href);
229
+ url.searchParams.set('f', 'kx-lot:L-7');
230
+ history.pushState(null, '', url);
231
+ window.dispatchEvent(new PopStateEvent('popstate', { state: null }));
232
+ await settle();
233
+ reads.length = 0;
234
+ openEntity360Kind('kx-lot', { id: 'L-7', name: 'L-7' });
235
+ await settle();
236
+ expect(reads.length).to.equal(0);
237
+ });
238
+ it('a kept entry - or none - is left without a question', async () => {
239
+ const open = OxPrompt.open;
240
+ let asked = 0;
241
+ OxPrompt.open = async () => (asked++, false);
242
+ try {
243
+ openEntity360Kind('kx-lot', { id: 'L-5', name: 'L-5' });
244
+ await settle();
245
+ openEntity360Kind('kx-lot', { id: 'L-6', name: 'L-6' });
246
+ await settle();
247
+ expect(asked).to.equal(0);
248
+ expect(address()).to.equal('kx-lot:L-6');
249
+ }
250
+ finally {
251
+ ;
252
+ OxPrompt.open = open;
253
+ }
128
254
  });
129
255
  it('a link carries more for the sections, beside the id', async () => {
130
256
  var _a;
131
257
  const heard = [];
132
258
  const stop = onEntity360Change(subject => heard.push(subject));
133
- const host = await fixture(html `<div>${entity360Link('kx-order', 'SO-10', undefined, { instanceId: 'twin-2' })}</div>`);
259
+ const host = drawn(html `${entity360Link('kx-order', 'SO-10', undefined, { instanceId: 'twin-2' })}`);
134
260
  host.querySelector('a').click();
135
261
  await settle();
136
262
  stop();
@@ -1 +1 @@
1
- {"version":3,"file":"entity360-kind.test.js","sourceRoot":"","sources":["../../test/entity360-kind.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture } from '@open-wc/testing'\nimport { html, render } from 'lit'\nimport { store, UPDATE_CONTEXT } from '@operato/shell'\nimport '../src/index.js'\nimport {\n closeEntity360,\n entity360Link,\n onEntity360Change,\n openEntity360Kind,\n redrawEntity360,\n registerEntity360Kind,\n type Entity360Subject,\n type OxEntity360Dock\n} from '../src/index.js'\n\n/**\n * A 360 opened by kind and id, the dock's own back trail, and the assistant subject it stands in for.\n *\n * A screen often holds an identifier, not a typed value: a location inside a stock line, an order\n * inside a task's 360. It still opens the 360 of that kind, with the same link as entity360Name.\n * Opening is a step in the address (f=kind:id), so back - the dock's or the browser's - returns to the one before.\n */\n\nconst settle = () => new Promise(resolve => setTimeout(resolve, 50))\n/** Go back and wait for the address to arrive - a late popstate would land in the next test. */\nconst back = (go: () => void = () => history.back()) =>\n new Promise<void>(resolve => {\n window.addEventListener('popstate', () => setTimeout(resolve, 0), { once: true })\n go()\n })\nlet bar: HTMLElement\nconst dock = () => bar.shadowRoot!.querySelector('ox-entity360-dock') as OxEntity360Dock\nconst subject = () => (store.getState() as any).route?.context?.subject\nconst address = () => new URLSearchParams(location.search).get('f')\n\nregisterEntity360Kind({ kind: 'kx-order', typenames: [], title: s => `order ${s.id}`, assistantSubject: true })\nregisterEntity360Kind({ kind: 'kx-place', typenames: [], title: s => `place ${s.id}`, assistantSubject: true })\nregisterEntity360Kind({ kind: 'kx-quiet', typenames: [], title: s => `quiet ${s.id}` })\nlet late = ''\nregisterEntity360Kind({ kind: 'kx-late', typenames: [], title: s => late || s.id })\n\ndescribe('entity 360 by kind', () => {\n beforeEach(async () => {\n history.replaceState(null, '', location.pathname)\n bar = await fixture(html`<ox-aside-bar></ox-aside-bar>`)\n store.dispatch({ type: UPDATE_CONTEXT, context: { title: 'page', subject: { type: 'page', id: 'P' } } })\n })\n afterEach(() => dock()?.view?.onClose())\n\n it('★ an identifier of a registered kind is the same link as a name; an unregistered one stays text', async () => {\n const host = document.createElement('div')\n render(html`${entity360Link('kx-order', 'SO-1')}|${entity360Link('nobody', 'X-1')}|${entity360Link('kx-order', '')}`, host)\n\n const anchors = host.querySelectorAll('a[data-entity360]')\n expect(anchors.length).to.equal(1)\n expect(anchors[0].textContent).to.equal('SO-1')\n expect(host.textContent).to.include('X-1')\n })\n\n it('★ a click on the link opens that kind with that id', async () => {\n const host = await fixture(html`<div>${entity360Link('kx-order', 'SO-2')}</div>`)\n ;(host.querySelector('a') as HTMLElement).click()\n await settle()\n\n expect(dock().view!.title).to.equal('order SO-2')\n })\n\n it('★ opening is a step in the address; back returns to the 360 before', async () => {\n openEntity360Kind('kx-order', { id: 'SO-3' })\n await settle()\n expect(address()).to.equal('kx-order:SO-3')\n expect(dock().view!.onBack).to.equal(undefined)\n\n openEntity360Kind('kx-place', { id: 'L-1' })\n await settle()\n expect(address()).to.equal('kx-place:L-1')\n\n await back(() => dock().view!.onBack!())\n expect(dock().view!.title).to.equal('order SO-3')\n expect(address()).to.equal('kx-order:SO-3')\n })\n\n it('★ an id with colons (an EPC) survives the address', async () => {\n openEntity360Kind('kx-order', { id: 'SO-6' })\n await settle()\n openEntity360Kind('kx-place', { id: 'urn:epc:id:sgln:0614141.00001.0' })\n await settle()\n openEntity360Kind('kx-order', { id: 'SO-7' })\n await settle()\n /* Back only from a step this test took - otherwise it would leave the test page. */\n expect(address()).to.equal('kx-order:SO-7')\n expect(dock().view!.onBack).to.be.a('function')\n\n await back()\n expect(dock().view!.title).to.equal('place urn:epc:id:sgln:0614141.00001.0')\n })\n\n it('★ closing leaves the address without a 360', async () => {\n openEntity360Kind('kx-order', { id: 'SO-4' })\n await settle()\n dock().view!.onClose()\n await settle()\n\n expect(address()).to.equal(null)\n expect(dock()).to.equal(null)\n })\n\n it('★ while open, the 360 is the page subject; closing gives the page its own back', async () => {\n openEntity360Kind('kx-order', { id: 'SO-5' })\n await settle()\n expect(subject()).to.deep.equal({ type: 'kx-order', id: 'SO-5' })\n\n openEntity360Kind('kx-place', { id: 'L-3' })\n await settle()\n expect(subject()).to.deep.equal({ type: 'kx-place', id: 'L-3' })\n\n dock().view!.onClose()\n await settle()\n expect(subject()).to.deep.equal({ type: 'page', id: 'P' })\n })\n\n it('a kind that does not stand in for the page leaves the page subject alone', async () => {\n openEntity360Kind('kx-quiet', { id: 'Q-1' })\n await settle()\n expect(subject()).to.deep.equal({ type: 'page', id: 'P' })\n })\n\n it('★ an app hears what the dock shows - open, back, and close', async () => {\n const heard: (Entity360Subject | undefined)[] = []\n const stop = onEntity360Change(subject => heard.push(subject))\n\n openEntity360Kind('kx-order', { id: 'SO-8' })\n await settle()\n openEntity360Kind('kx-place', { id: 'L-8' })\n await settle()\n await back(() => dock().view!.onBack!())\n dock().view!.onClose()\n await settle()\n stop()\n\n expect(heard.map(one => (one ? `${one.kind}:${one.id}` : 'closed'))).to.deep.equal(['kx-order:SO-8', 'kx-place:L-8', 'kx-order:SO-8', 'closed'])\n })\n\n it('an app that let go of its selection closes the 360 and its step', async () => {\n openEntity360Kind('kx-order', { id: 'SO-9' })\n await settle()\n closeEntity360()\n await settle()\n\n expect(dock()).to.equal(null)\n expect(address()).to.equal(null)\n })\n\n it('redraw reads the title again - for a title its section learns later', async () => {\n late = ''\n openEntity360Kind('kx-late', { id: 'X-9' })\n await settle()\n expect(dock().view!.title).to.equal('X-9')\n\n late = 'named later'\n redrawEntity360()\n await settle()\n expect(dock().view!.title).to.equal('named later')\n })\n\n it('a link carries more for the sections, beside the id', async () => {\n const heard: (Entity360Subject | undefined)[] = []\n const stop = onEntity360Change(subject => heard.push(subject))\n const host = await fixture(html`<div>${entity360Link('kx-order', 'SO-10', undefined, { instanceId: 'twin-2' })}</div>`)\n ;(host.querySelector('a') as HTMLElement).click()\n await settle()\n stop()\n\n expect(heard[0]?.value).to.include({ id: 'SO-10', instanceId: 'twin-2' })\n })\n})\n"]}
1
+ {"version":3,"file":"entity360-kind.test.js","sourceRoot":"","sources":["../../test/entity360-kind.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture } from '@open-wc/testing'\nimport { html, render, LitElement } from 'lit'\nimport { OxPrompt } from '@operato/popup/ox-prompt.js'\nimport { store, UPDATE_CONTEXT } from '@operato/shell'\nimport '../src/index.js'\nimport {\n closeEntity360,\n entity360Link,\n onEntity360Change,\n openEntity360Kind,\n registerEntity360Kind,\n registerEntity360Section,\n setEntity360Value,\n ENTITY360_UNKEPT,\n type Entity360Subject,\n type OxEntity360Dock\n} from '../src/index.js'\n\n/**\n * A 360 opened by kind and id, the dock's own back trail, and the assistant subject it stands in for.\n *\n * A screen often holds an identifier, not a typed value: a location inside a stock line, an order\n * inside a task's 360. It still opens the 360 of that kind, with the same link as entity360Name.\n * Opening is a step in the address (f=kind:id), so back - the dock's or the browser's - returns to the one before.\n */\n\nconst settle = () => new Promise(resolve => setTimeout(resolve, 50))\n/** Go back and wait for the address to arrive - a late popstate would land in the next test. */\nconst back = (go: () => void = () => history.back()) =>\n new Promise<void>(resolve => {\n window.addEventListener('popstate', () => setTimeout(resolve, 0), { once: true })\n go()\n })\nlet bar: HTMLElement\n/**\n * Links drawn straight into the page. `fixture` waits for an animation frame, and a page the runner keeps in the\n * background (files run side by side) may not get one before the test times out.\n */\nconst drawn = (template: unknown) => {\n const host = document.body.appendChild(document.createElement('div'))\n render(template, host)\n return host\n}\nconst dock = () => bar.shadowRoot!.querySelector('ox-entity360-dock') as OxEntity360Dock\nconst subject = () => (store.getState() as any).route?.context?.subject\nconst address = () => new URLSearchParams(location.search).get('f')\n\nregisterEntity360Kind({ kind: 'kx-order', typenames: [], title: s => `order ${s.id}`, assistantSubject: true })\nregisterEntity360Kind({ kind: 'kx-place', typenames: [], title: s => `place ${s.id}`, assistantSubject: true })\nregisterEntity360Kind({ kind: 'kx-quiet', typenames: [], title: s => `quiet ${s.id}` })\nregisterEntity360Kind({ kind: 'kx-late', typenames: [], title: s => s.value.name || s.id })\n\n/* A kind whose one identifier is its name, the way a lot is (ADR-0067 decision 6). */\nregisterEntity360Kind({ kind: 'kx-lot', typenames: ['KxLot'], id: value => value.name, title: s => s.value.name || s.id })\n\n/** A section the way modules write one: it takes the subject and reads whenever the subject changes. */\nconst reads: { section: Element; subject: Entity360Subject }[] = []\nclass KxSection extends LitElement {\n static properties = { subject: { attribute: false } }\n subject?: Entity360Subject\n createRenderRoot() {\n return this\n }\n updated(changed: Map<string, unknown>) {\n if (changed.has('subject') && this.subject) reads.push({ section: this, subject: this.subject })\n }\n render() {\n return html`<input />`\n }\n}\ncustomElements.define('kx-section', KxSection)\nregisterEntity360Section('kx-lot', { name: 'facts', render: subject => html`<kx-section .subject=${subject}></kx-section>` })\nconst section = () => dock().shadowRoot!.querySelector('ox-entity360-content')!.shadowRoot!.querySelector('kx-section') as KxSection\n\ndescribe('entity 360 by kind', () => {\n beforeEach(async () => {\n history.replaceState(null, '', location.pathname)\n bar = await fixture(html`<ox-aside-bar></ox-aside-bar>`)\n store.dispatch({ type: UPDATE_CONTEXT, context: { title: 'page', subject: { type: 'page', id: 'P' } } })\n })\n afterEach(() => dock()?.view?.onClose())\n\n it('★ an identifier of a registered kind is the same link as a name; an unregistered one stays text', async () => {\n const host = document.createElement('div')\n render(html`${entity360Link('kx-order', 'SO-1')}|${entity360Link('nobody', 'X-1')}|${entity360Link('kx-order', '')}`, host)\n\n const anchors = host.querySelectorAll('a[data-entity360]')\n expect(anchors.length).to.equal(1)\n expect(anchors[0].textContent).to.equal('SO-1')\n expect(host.textContent).to.include('X-1')\n })\n\n it('★ a click on the link opens that kind with that id', async () => {\n const host = drawn(html`${entity360Link('kx-order', 'SO-2')}`)\n ;(host.querySelector('a') as HTMLElement).click()\n await settle()\n\n expect(dock().view!.title).to.equal('order SO-2')\n })\n\n it('★ opening is a step in the address; back returns to the 360 before', async () => {\n openEntity360Kind('kx-order', { id: 'SO-3' })\n await settle()\n expect(address()).to.equal('kx-order:SO-3')\n expect(dock().view!.onBack).to.equal(undefined)\n\n openEntity360Kind('kx-place', { id: 'L-1' })\n await settle()\n expect(address()).to.equal('kx-place:L-1')\n\n await back(() => dock().view!.onBack!())\n expect(dock().view!.title).to.equal('order SO-3')\n expect(address()).to.equal('kx-order:SO-3')\n })\n\n it('★ an id with colons (an EPC) survives the address', async () => {\n openEntity360Kind('kx-order', { id: 'SO-6' })\n await settle()\n openEntity360Kind('kx-place', { id: 'urn:epc:id:sgln:0614141.00001.0' })\n await settle()\n openEntity360Kind('kx-order', { id: 'SO-7' })\n await settle()\n /* Back only from a step this test took - otherwise it would leave the test page. */\n expect(address()).to.equal('kx-order:SO-7')\n expect(dock().view!.onBack).to.be.a('function')\n\n await back()\n expect(dock().view!.title).to.equal('place urn:epc:id:sgln:0614141.00001.0')\n })\n\n it('★ closing leaves the address without a 360', async () => {\n openEntity360Kind('kx-order', { id: 'SO-4' })\n await settle()\n dock().view!.onClose()\n await settle()\n\n expect(address()).to.equal(null)\n expect(dock()).to.equal(null)\n })\n\n it('★ while open, the 360 is the page subject; closing gives the page its own back', async () => {\n openEntity360Kind('kx-order', { id: 'SO-5' })\n await settle()\n expect(subject()).to.deep.equal({ type: 'kx-order', id: 'SO-5' })\n\n openEntity360Kind('kx-place', { id: 'L-3' })\n await settle()\n expect(subject()).to.deep.equal({ type: 'kx-place', id: 'L-3' })\n\n dock().view!.onClose()\n await settle()\n expect(subject()).to.deep.equal({ type: 'page', id: 'P' })\n })\n\n it('a kind that does not stand in for the page leaves the page subject alone', async () => {\n openEntity360Kind('kx-quiet', { id: 'Q-1' })\n await settle()\n expect(subject()).to.deep.equal({ type: 'page', id: 'P' })\n })\n\n it('★ an app hears what the dock shows - open, back, and close', async () => {\n const heard: (Entity360Subject | undefined)[] = []\n const stop = onEntity360Change(subject => heard.push(subject))\n\n openEntity360Kind('kx-order', { id: 'SO-8' })\n await settle()\n openEntity360Kind('kx-place', { id: 'L-8' })\n await settle()\n await back(() => dock().view!.onBack!())\n dock().view!.onClose()\n await settle()\n stop()\n\n expect(heard.map(one => (one ? `${one.kind}:${one.id}` : 'closed'))).to.deep.equal(['kx-order:SO-8', 'kx-place:L-8', 'kx-order:SO-8', 'closed'])\n })\n\n it('an app that let go of its selection closes the 360 and its step', async () => {\n openEntity360Kind('kx-order', { id: 'SO-9' })\n await settle()\n closeEntity360()\n await settle()\n\n expect(dock()).to.equal(null)\n expect(address()).to.equal(null)\n })\n\n it('★ what a section reads names the subject: the heading is drawn from it, the sections stay', async () => {\n openEntity360Kind('kx-lot', { id: 'L-9', name: 'L-9' })\n await settle()\n expect(dock().view!.title).to.equal('L-9')\n const first = section()\n\n setEntity360Value({ kind: 'kx-lot', id: 'L-9' }, { name: 'L-9', definitionId: 'M-1' })\n openEntity360Kind('kx-late', { id: 'X-9' })\n await settle()\n expect(dock().view!.title).to.equal('X-9')\n setEntity360Value({ kind: 'kx-late', id: 'X-9' }, { name: 'named later' })\n await settle()\n expect(dock().view!.title).to.equal('named later')\n expect(first.isConnected).to.equal(false)\n })\n\n it('★ a kind that declares its identifier: a typed value, a link and the address all open the same subject', async () => {\n reads.length = 0\n const host = drawn(html`${entity360Link('kx-lot', 'L-1')}`)\n ;(host.querySelector('a') as HTMLElement).click()\n await settle()\n expect(address()).to.equal('kx-lot:L-1')\n dock().view!.onClose()\n await settle()\n\n openEntity360Kind('kx-lot', { __typename: 'KxLot', id: '0c9e-uuid', name: 'L-1' })\n await settle()\n expect(address()).to.equal('kx-lot:L-1')\n expect(reads.map(read => read.subject.id)).to.deep.equal(['L-1', 'L-1'])\n })\n\n it('★ a shared link brings only the id - the sections still read by it', async () => {\n reads.length = 0\n const url = new URL(location.href)\n url.searchParams.set('f', 'kx-lot:L-shared')\n history.pushState(null, '', url)\n window.dispatchEvent(new PopStateEvent('popstate', { state: null }))\n await settle()\n expect(dock().view!.title).to.equal('L-shared')\n expect(reads[reads.length - 1]?.subject).to.deep.include({ kind: 'kx-lot', id: 'L-shared' })\n expect(reads[reads.length - 1]?.subject.value).to.deep.equal({ id: 'L-shared' })\n })\n\n it('★ refresh gives the sections a new subject of the same id; they read again and are not made anew', async () => {\n openEntity360Kind('kx-lot', { id: 'L-2', name: 'L-2' })\n await settle()\n const before = section()\n const input = before.querySelector('input')!\n input.value = 'typed'\n reads.length = 0\n dock().view!.onRefresh!()\n await settle()\n expect(section()).to.equal(before)\n expect(input.value).to.equal('typed')\n expect(reads.length).to.equal(1)\n expect(reads[0].subject.id).to.equal('L-2')\n })\n\n it('★ leaving a subject whose entry no draft keeps is asked about; keeping it stays put', async () => {\n const open = OxPrompt.open\n let asked = 0\n let answer = false\n ;(OxPrompt as any).open = async () => (asked++, answer)\n try {\n openEntity360Kind('kx-lot', { id: 'L-3', name: 'L-3' })\n await settle()\n const input = section().querySelector('input')!\n input.dispatchEvent(new CustomEvent(ENTITY360_UNKEPT, { bubbles: true, composed: true, detail: { unkept: true } }))\n\n openEntity360Kind('kx-lot', { id: 'L-4', name: 'L-4' })\n await settle()\n expect(asked).to.equal(1)\n expect(address()).to.equal('kx-lot:L-3')\n expect(input.isConnected).to.equal(true)\n\n answer = true\n openEntity360Kind('kx-lot', { id: 'L-4', name: 'L-4' })\n await settle()\n expect(asked).to.equal(2)\n expect(address()).to.equal('kx-lot:L-4')\n } finally {\n ;(OxPrompt as any).open = open\n }\n })\n\n it('★ opening the subject already shown does not hand the sections a new subject', async () => {\n const url = new URL(location.href)\n url.searchParams.set('f', 'kx-lot:L-7')\n history.pushState(null, '', url)\n window.dispatchEvent(new PopStateEvent('popstate', { state: null }))\n await settle()\n reads.length = 0\n openEntity360Kind('kx-lot', { id: 'L-7', name: 'L-7' })\n await settle()\n expect(reads.length).to.equal(0)\n })\n\n it('a kept entry - or none - is left without a question', async () => {\n const open = OxPrompt.open\n let asked = 0\n ;(OxPrompt as any).open = async () => (asked++, false)\n try {\n openEntity360Kind('kx-lot', { id: 'L-5', name: 'L-5' })\n await settle()\n openEntity360Kind('kx-lot', { id: 'L-6', name: 'L-6' })\n await settle()\n expect(asked).to.equal(0)\n expect(address()).to.equal('kx-lot:L-6')\n } finally {\n ;(OxPrompt as any).open = open\n }\n })\n\n it('a link carries more for the sections, beside the id', async () => {\n const heard: (Entity360Subject | undefined)[] = []\n const stop = onEntity360Change(subject => heard.push(subject))\n const host = drawn(html`${entity360Link('kx-order', 'SO-10', undefined, { instanceId: 'twin-2' })}`)\n ;(host.querySelector('a') as HTMLElement).click()\n await settle()\n stop()\n\n expect(heard[0]?.value).to.include({ id: 'SO-10', instanceId: 'twin-2' })\n })\n})\n"]}
@@ -1,13 +1,43 @@
1
1
  import { expect, fixture } from '@open-wc/testing';
2
2
  import { html } from 'lit';
3
3
  import '../src/index.js';
4
- import { readEntity360Door } from '../src/index.js';
4
+ import { askEntity360Door, Entity360Reads, readEntity360Door } from '../src/index.js';
5
5
  /**
6
6
  * A 360 section says what its door answered (ADR-0067): something, nothing, may-not-see, or failed.
7
7
  * The axis that matters is the second against the third - a refused viewer must not be told "none".
8
8
  */
9
9
  const refused = { data: null, errors: [{ message: 'not allowed', extensions: { code: 'FORBIDDEN' } }] };
10
10
  describe('entity 360 door', () => {
11
+ it('★ a request that throws is failed, with its own message - never left loading (ADR-0067 decision 7)', async () => {
12
+ const answer = await askEntity360Door(Promise.reject(new Error('Failed to fetch')), d => d === null || d === void 0 ? void 0 : d.items);
13
+ expect(answer).to.deep.equal({ state: 'failed', message: 'Failed to fetch' });
14
+ });
15
+ it('★ a client that throws on a refusal still says forbidden', async () => {
16
+ const thrown = Object.assign(new Error('not allowed'), { graphQLErrors: refused.errors });
17
+ expect((await askEntity360Door(Promise.reject(thrown), d => d === null || d === void 0 ? void 0 : d.items)).state).to.equal('forbidden');
18
+ });
19
+ it('★ only the newest read answers - a second read of the same id drops the first', async () => {
20
+ var _a;
21
+ const reads = new Entity360Reads();
22
+ let release;
23
+ const first = reads.ask(() => new Promise(resolve => (release = resolve)), d => d.items);
24
+ const second = reads.ask(() => Promise.resolve({ data: { items: [2] } }), d => d.items);
25
+ release({ data: { items: [1] } });
26
+ expect(await first).to.equal(undefined);
27
+ expect((_a = (await second)) === null || _a === void 0 ? void 0 : _a.data).to.deep.equal([2]);
28
+ });
29
+ it('a read that throws synchronously still ends failed; forget drops one on its way', async () => {
30
+ var _a;
31
+ const reads = new Entity360Reads();
32
+ expect((_a = (await reads.ask(() => { throw new Error('no client'); }, d => d))) === null || _a === void 0 ? void 0 : _a.state).to.equal('failed');
33
+ const pending = reads.ask(() => Promise.resolve({ data: { items: [1] } }), d => d.items);
34
+ reads.forget();
35
+ expect(await pending).to.equal(undefined);
36
+ });
37
+ it('a request that answers is read as readEntity360Door reads it', async () => {
38
+ expect((await askEntity360Door(Promise.resolve({ data: { items: [] } }), d => d.items)).state).to.equal('none');
39
+ expect((await askEntity360Door(Promise.resolve({ data: { items: [1] } }), d => d.items)).data).to.deep.equal([1]);
40
+ });
11
41
  it('★ a refusal is forbidden, not none - even when data came back empty beside it', () => {
12
42
  expect(readEntity360Door(refused, d => d === null || d === void 0 ? void 0 : d.items).state).to.equal('forbidden');
13
43
  expect(readEntity360Door({ ...refused, data: { items: [] } }, d => d.items).state).to.equal('forbidden');