@operato/layout 10.29.46 → 10.29.50

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 (54) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/src/actions/entity360-door.d.ts +28 -0
  3. package/dist/src/actions/entity360-door.js +45 -0
  4. package/dist/src/actions/entity360-door.js.map +1 -1
  5. package/dist/src/actions/entity360-registry.d.ts +13 -3
  6. package/dist/src/actions/entity360-registry.js +49 -8
  7. package/dist/src/actions/entity360-registry.js.map +1 -1
  8. package/dist/src/actions/entity360.d.ts +2 -0
  9. package/dist/src/actions/entity360.js +4 -0
  10. package/dist/src/actions/entity360.js.map +1 -1
  11. package/dist/src/actions/id-lens.d.ts +67 -0
  12. package/dist/src/actions/id-lens.js +51 -0
  13. package/dist/src/actions/id-lens.js.map +1 -0
  14. package/dist/src/actions/layout.d.ts +5 -0
  15. package/dist/src/actions/layout.js.map +1 -1
  16. package/dist/src/components/ox-entity360-dock.d.ts +18 -2
  17. package/dist/src/components/ox-entity360-dock.js +39 -17
  18. package/dist/src/components/ox-entity360-dock.js.map +1 -1
  19. package/dist/src/components/ox-id-lens.d.ts +58 -0
  20. package/dist/src/components/ox-id-lens.js +362 -0
  21. package/dist/src/components/ox-id-lens.js.map +1 -0
  22. package/dist/src/index.d.ts +1 -0
  23. package/dist/src/index.js +1 -0
  24. package/dist/src/index.js.map +1 -1
  25. package/dist/src/layouts/ox-aside-bar.js +134 -6
  26. package/dist/src/layouts/ox-aside-bar.js.map +1 -1
  27. package/dist/test/entity360-companion.test.d.ts +1 -0
  28. package/dist/test/entity360-companion.test.js +127 -0
  29. package/dist/test/entity360-companion.test.js.map +1 -0
  30. package/dist/test/entity360-kind.test.js +136 -10
  31. package/dist/test/entity360-kind.test.js.map +1 -1
  32. package/dist/test/entity360-section.test.js +31 -1
  33. package/dist/test/entity360-section.test.js.map +1 -1
  34. package/dist/test/entity360.test.js +29 -6
  35. package/dist/test/entity360.test.js.map +1 -1
  36. package/dist/test/id-lens.test.d.ts +2 -0
  37. package/dist/test/id-lens.test.js +162 -0
  38. package/dist/test/id-lens.test.js.map +1 -0
  39. package/dist/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +11 -6
  41. package/test/entity360-companion.test.ts +110 -0
  42. package/test/entity360-kind.test.ts +145 -11
  43. package/test/entity360-section.test.ts +34 -1
  44. package/test/entity360.test.ts +31 -6
  45. package/test/id-lens.test.ts +198 -0
  46. package/coverage/lcov-report/base.css +0 -224
  47. package/coverage/lcov-report/block-navigation.js +0 -87
  48. package/coverage/lcov-report/favicon.png +0 -0
  49. package/coverage/lcov-report/index.html +0 -1136
  50. package/coverage/lcov-report/prettify.css +0 -1
  51. package/coverage/lcov-report/prettify.js +0 -2
  52. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  53. package/coverage/lcov-report/sorter.js +0 -210
  54. package/coverage/lcov.info +0 -63268
@@ -1 +1 @@
1
- {"version":3,"file":"entity360-section.test.js","sourceRoot":"","sources":["../../test/entity360-section.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture } from '@open-wc/testing'\nimport { html } from 'lit'\nimport '../src/index.js'\nimport { readEntity360Door, type OxEntity360Section } from '../src/index.js'\n\n/**\n * A 360 section says what its door answered (ADR-0067): something, nothing, may-not-see, or failed.\n * The axis that matters is the second against the third - a refused viewer must not be told \"none\".\n */\n\nconst refused = { data: null, errors: [{ message: 'not allowed', extensions: { code: 'FORBIDDEN' } }] }\n\ndescribe('entity 360 door', () => {\n it('★ a refusal is forbidden, not none - even when data came back empty beside it', () => {\n expect(readEntity360Door(refused, d => d?.items).state).to.equal('forbidden')\n expect(readEntity360Door({ ...refused, data: { items: [] } }, d => d.items).state).to.equal('forbidden')\n })\n\n it('★ an answer with nothing in it is none', () => {\n expect(readEntity360Door({ data: { items: [] } }, d => d.items).state).to.equal('none')\n expect(readEntity360Door({ data: { one: null } }, d => d.one).state).to.equal('none')\n })\n\n it('an answer with something is ready and carries it', () => {\n const answer = readEntity360Door({ data: { items: [1] } }, d => d.items)\n expect(answer).to.deep.equal({ state: 'ready', data: [1] })\n })\n\n it('any other error is failed and keeps the server sentence', () => {\n const answer = readEntity360Door({ data: null, errors: [{ message: 'db down' }] }, d => d)\n expect(answer).to.deep.equal({ state: 'failed', message: 'db down' })\n expect(readEntity360Door(undefined, d => d).state).to.equal('failed')\n })\n\n it('a section decides for itself what empty means', () => {\n const zero = readEntity360Door({ data: { n: { a: 0 } } }, d => d.n, n => n.a === 0)\n expect(zero.state).to.equal('none')\n })\n})\n\ndescribe('ox-entity360-section', () => {\n const said = (el: OxEntity360Section) => el.shadowRoot!.querySelector('p')?.dataset.state\n\n it('★ draws the slot only when ready', async () => {\n const el = await fixture<OxEntity360Section>(\n html`<ox-entity360-section heading=\"h\" state=\"forbidden\"><span>secret</span></ox-entity360-section>`\n )\n expect(said(el)).to.equal('forbidden')\n expect(el.shadowRoot!.querySelector('slot')).to.equal(null)\n\n el.state = 'ready'\n await el.updateComplete\n expect(el.shadowRoot!.querySelector('slot')).to.not.equal(null)\n })\n\n it('says none, loading and failed apart', async () => {\n const el = await fixture<OxEntity360Section>(html`<ox-entity360-section heading=\"h\"></ox-entity360-section>`)\n expect(said(el)).to.equal('loading')\n el.state = 'none'\n await el.updateComplete\n expect(said(el)).to.equal('none')\n el.state = 'failed'\n el.message = 'db down'\n await el.updateComplete\n expect(el.shadowRoot!.querySelector('p')!.textContent!.trim()).to.equal('db down')\n el.message = ''\n await el.updateComplete\n expect(el.shadowRoot!.querySelector('p')!.textContent!.trim()).to.not.equal('')\n })\n})\n\ndescribe('entity 360 section as a drop area', () => {\n it('shows where a dragged file would land, and only then', async () => {\n const section = (await fixture(html`<ox-entity360-section heading=\"papers\" state=\"ready\"></ox-entity360-section>`)) as OxEntity360Section\n section.style.setProperty('--md-sys-color-primary', 'rgb(0, 0, 255)')\n\n expect(getComputedStyle(section).outlineStyle).to.equal('none')\n\n section.classList.add('candrop')\n expect(getComputedStyle(section).outlineStyle, 'no mark while a file is over it').to.equal('dashed')\n\n section.classList.remove('candrop')\n expect(getComputedStyle(section).outlineStyle).to.equal('none')\n })\n})\n\ndescribe('entity 360 section heading', () => {\n it('keeps the heading level with an action that grows a second line', async () => {\n const section = (await fixture(html`<ox-entity360-section heading=\"papers\" state=\"ready\">\n <span slot=\"actions\" style=\"display: inline-flex; flex-wrap: wrap; width: 120px\">\n <button style=\"height: 26px\">attach</button>\n </span>\n </ox-entity360-section>`)) as OxEntity360Section\n\n const heading = section.shadowRoot!.querySelector('h3')!\n const actions = section.querySelector('[slot=\"actions\"]') as HTMLElement\n const before = heading.getBoundingClientRect().top\n\n const refusal = document.createElement('div')\n refusal.style.flexBasis = '100%'\n refusal.textContent = 'memo.txt: not a type taken here'\n actions.append(refusal)\n\n expect(heading.getBoundingClientRect().top, 'the heading moved down with the second line').to.equal(before)\n })\n})\n\ndescribe('entity 360 section actions', () => {\n it('tells what sits in the actions slot to line up at the end', async () => {\n const section = (await fixture(html`<ox-entity360-section heading=\"papers\" state=\"ready\">\n <span slot=\"actions\">attach</span>\n </ox-entity360-section>`)) as OxEntity360Section\n\n const actions = section.querySelector('[slot=\"actions\"]') as HTMLElement\n expect(getComputedStyle(actions).getPropertyValue('--ox-actions-align').trim()).to.equal('end')\n })\n})\n"]}
1
+ {"version":3,"file":"entity360-section.test.js","sourceRoot":"","sources":["../../test/entity360-section.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture } from '@open-wc/testing'\nimport { html } from 'lit'\nimport '../src/index.js'\nimport { askEntity360Door, Entity360Reads, readEntity360Door, type OxEntity360Section } from '../src/index.js'\n\n/**\n * A 360 section says what its door answered (ADR-0067): something, nothing, may-not-see, or failed.\n * The axis that matters is the second against the third - a refused viewer must not be told \"none\".\n */\n\nconst refused = { data: null, errors: [{ message: 'not allowed', extensions: { code: 'FORBIDDEN' } }] }\n\ndescribe('entity 360 door', () => {\n it('★ a request that throws is failed, with its own message - never left loading (ADR-0067 decision 7)', async () => {\n const answer = await askEntity360Door(Promise.reject(new Error('Failed to fetch')), d => d?.items)\n expect(answer).to.deep.equal({ state: 'failed', message: 'Failed to fetch' })\n })\n\n it('★ a client that throws on a refusal still says forbidden', async () => {\n const thrown = Object.assign(new Error('not allowed'), { graphQLErrors: refused.errors })\n expect((await askEntity360Door(Promise.reject(thrown), d => d?.items)).state).to.equal('forbidden')\n })\n\n it('★ only the newest read answers - a second read of the same id drops the first', async () => {\n const reads = new Entity360Reads()\n let release!: (value: any) => void\n const first = reads.ask(() => new Promise(resolve => (release = resolve)), d => d.items)\n const second = reads.ask(() => Promise.resolve({ data: { items: [2] } }), d => d.items)\n release({ data: { items: [1] } })\n expect(await first).to.equal(undefined)\n expect((await second)?.data).to.deep.equal([2])\n })\n\n it('a read that throws synchronously still ends failed; forget drops one on its way', async () => {\n const reads = new Entity360Reads()\n expect((await reads.ask(() => { throw new Error('no client') }, d => d))?.state).to.equal('failed')\n const pending = reads.ask(() => Promise.resolve({ data: { items: [1] } }), d => d.items)\n reads.forget()\n expect(await pending).to.equal(undefined)\n })\n\n it('a request that answers is read as readEntity360Door reads it', async () => {\n expect((await askEntity360Door(Promise.resolve({ data: { items: [] } }), d => d.items)).state).to.equal('none')\n expect((await askEntity360Door(Promise.resolve({ data: { items: [1] } }), d => d.items)).data).to.deep.equal([1])\n })\n\n it('★ a refusal is forbidden, not none - even when data came back empty beside it', () => {\n expect(readEntity360Door(refused, d => d?.items).state).to.equal('forbidden')\n expect(readEntity360Door({ ...refused, data: { items: [] } }, d => d.items).state).to.equal('forbidden')\n })\n\n it('★ an answer with nothing in it is none', () => {\n expect(readEntity360Door({ data: { items: [] } }, d => d.items).state).to.equal('none')\n expect(readEntity360Door({ data: { one: null } }, d => d.one).state).to.equal('none')\n })\n\n it('an answer with something is ready and carries it', () => {\n const answer = readEntity360Door({ data: { items: [1] } }, d => d.items)\n expect(answer).to.deep.equal({ state: 'ready', data: [1] })\n })\n\n it('any other error is failed and keeps the server sentence', () => {\n const answer = readEntity360Door({ data: null, errors: [{ message: 'db down' }] }, d => d)\n expect(answer).to.deep.equal({ state: 'failed', message: 'db down' })\n expect(readEntity360Door(undefined, d => d).state).to.equal('failed')\n })\n\n it('a section decides for itself what empty means', () => {\n const zero = readEntity360Door({ data: { n: { a: 0 } } }, d => d.n, n => n.a === 0)\n expect(zero.state).to.equal('none')\n })\n})\n\ndescribe('ox-entity360-section', () => {\n const said = (el: OxEntity360Section) => el.shadowRoot!.querySelector('p')?.dataset.state\n\n it('★ draws the slot only when ready', async () => {\n const el = await fixture<OxEntity360Section>(\n html`<ox-entity360-section heading=\"h\" state=\"forbidden\"><span>secret</span></ox-entity360-section>`\n )\n expect(said(el)).to.equal('forbidden')\n expect(el.shadowRoot!.querySelector('slot')).to.equal(null)\n\n el.state = 'ready'\n await el.updateComplete\n expect(el.shadowRoot!.querySelector('slot')).to.not.equal(null)\n })\n\n it('says none, loading and failed apart', async () => {\n const el = await fixture<OxEntity360Section>(html`<ox-entity360-section heading=\"h\"></ox-entity360-section>`)\n expect(said(el)).to.equal('loading')\n el.state = 'none'\n await el.updateComplete\n expect(said(el)).to.equal('none')\n el.state = 'failed'\n el.message = 'db down'\n await el.updateComplete\n expect(el.shadowRoot!.querySelector('p')!.textContent!.trim()).to.equal('db down')\n el.message = ''\n await el.updateComplete\n expect(el.shadowRoot!.querySelector('p')!.textContent!.trim()).to.not.equal('')\n })\n})\n\ndescribe('entity 360 section as a drop area', () => {\n it('shows where a dragged file would land, and only then', async () => {\n const section = (await fixture(html`<ox-entity360-section heading=\"papers\" state=\"ready\"></ox-entity360-section>`)) as OxEntity360Section\n section.style.setProperty('--md-sys-color-primary', 'rgb(0, 0, 255)')\n\n expect(getComputedStyle(section).outlineStyle).to.equal('none')\n\n section.classList.add('candrop')\n expect(getComputedStyle(section).outlineStyle, 'no mark while a file is over it').to.equal('dashed')\n\n section.classList.remove('candrop')\n expect(getComputedStyle(section).outlineStyle).to.equal('none')\n })\n})\n\ndescribe('entity 360 section heading', () => {\n it('keeps the heading level with an action that grows a second line', async () => {\n const section = (await fixture(html`<ox-entity360-section heading=\"papers\" state=\"ready\">\n <span slot=\"actions\" style=\"display: inline-flex; flex-wrap: wrap; width: 120px\">\n <button style=\"height: 26px\">attach</button>\n </span>\n </ox-entity360-section>`)) as OxEntity360Section\n\n const heading = section.shadowRoot!.querySelector('h3')!\n const actions = section.querySelector('[slot=\"actions\"]') as HTMLElement\n const before = heading.getBoundingClientRect().top\n\n const refusal = document.createElement('div')\n refusal.style.flexBasis = '100%'\n refusal.textContent = 'memo.txt: not a type taken here'\n actions.append(refusal)\n\n expect(heading.getBoundingClientRect().top, 'the heading moved down with the second line').to.equal(before)\n })\n})\n\ndescribe('entity 360 section actions', () => {\n it('tells what sits in the actions slot to line up at the end', async () => {\n const section = (await fixture(html`<ox-entity360-section heading=\"papers\" state=\"ready\">\n <span slot=\"actions\">attach</span>\n </ox-entity360-section>`)) as OxEntity360Section\n\n const actions = section.querySelector('[slot=\"actions\"]') as HTMLElement\n expect(getComputedStyle(actions).getPropertyValue('--ox-actions-align').trim()).to.equal('end')\n })\n})\n"]}
@@ -1,7 +1,7 @@
1
1
  import { expect, fixture, elementUpdated } from '@open-wc/testing';
2
2
  import { html } from 'lit';
3
3
  import '../src/index.js';
4
- import { showEntity360, hideEntity360, navigateEntity360, canGoBackEntity360 } from '../src/index.js';
4
+ import { showEntity360, hideEntity360, isEntity360Unkept, navigateEntity360, canGoBackEntity360, ENTITY360_UNKEPT } from '../src/index.js';
5
5
  const owner = {};
6
6
  const labels = { close: 'Close', expand: 'Expand', collapse: 'Collapse', resize: 'Resize', back: 'Back' };
7
7
  const settle = () => new Promise(resolve => setTimeout(resolve, 50));
@@ -33,20 +33,43 @@ describe('shared nonmodal entity 360 dock', () => {
33
33
  expect(original.view.context).to.equal('Approval after · Revision 2');
34
34
  expect(original.shadowRoot.textContent).to.contain('Approval after · Revision 2');
35
35
  });
36
- it('refreshes all content while keeping the dock and its read context', async () => {
37
- showEntity360(owner, view());
36
+ it('★ refresh reads again and keeps the contents - what is being written stays (ADR-0067 decision 8)', async () => {
37
+ let refreshed = 0;
38
+ showEntity360(owner, { ...view(), onRefresh: () => refreshed++ });
38
39
  await settle();
39
40
  const original = dock();
40
41
  original.expanded = true;
41
42
  const content = original.shadowRoot.querySelector('ox-entity360-content');
42
43
  const input = content.shadowRoot.querySelector('input');
44
+ input.value = 'typed, not saved';
43
45
  original.shadowRoot.querySelector('[data-action="refresh"]').click();
44
46
  await settle();
47
+ expect(refreshed).to.equal(1);
45
48
  expect(dock()).to.equal(original);
46
49
  expect(original.expanded).to.equal(true);
47
- expect(original.view.key).to.equal('Revision 1');
48
- expect(content.shadowRoot.querySelector('input')).not.to.equal(input);
49
- expect(content.shadowRoot.querySelector('input').value).to.equal('Revision 1');
50
+ expect(content.shadowRoot.querySelector('input')).to.equal(input);
51
+ expect(input.value).to.equal('typed, not saved');
52
+ });
53
+ it('a dock that cannot read again draws no refresh button', async () => {
54
+ showEntity360(owner, view());
55
+ await settle();
56
+ expect(dock().shadowRoot.querySelector('[data-action="refresh"]')).to.equal(null);
57
+ });
58
+ it('★ a section holding an entry no draft keeps makes the dock unkept, until it says otherwise', async () => {
59
+ showEntity360(owner, view());
60
+ await settle();
61
+ const content = dock().shadowRoot.querySelector('ox-entity360-content');
62
+ const input = content.shadowRoot.querySelector('input');
63
+ const tell = (unkept) => input.dispatchEvent(new CustomEvent(ENTITY360_UNKEPT, { bubbles: true, composed: true, detail: { unkept } }));
64
+ expect(isEntity360Unkept(owner)).to.equal(false);
65
+ tell(true);
66
+ expect(isEntity360Unkept(owner)).to.equal(true);
67
+ tell(false);
68
+ expect(isEntity360Unkept(owner)).to.equal(false);
69
+ tell(true);
70
+ showEntity360(owner, view('Revision 2'));
71
+ await settle();
72
+ expect(isEntity360Unkept(owner)).to.equal(false);
50
73
  });
51
74
  it('uses compact header controls and the shared scrollbar theme without local overrides', async () => {
52
75
  bar.style.setProperty('--scrollbar-thumb-color', 'rgb(57, 78, 100)');
@@ -1 +1 @@
1
- {"version":3,"file":"entity360.test.js","sourceRoot":"","sources":["../../test/entity360.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture, elementUpdated } from '@open-wc/testing'\nimport { html } from 'lit'\nimport '../src/index.js'\nimport { showEntity360, hideEntity360, navigateEntity360, canGoBackEntity360, type OxEntity360Dock, type Entity360View } from '../src/index.js'\n\nconst owner = {}\nconst labels = { close: 'Close', expand: 'Expand', collapse: 'Collapse', resize: 'Resize', back: 'Back' }\nconst settle = () => new Promise(resolve => setTimeout(resolve, 50))\nlet bar: HTMLElement\nconst dock = () => bar.shadowRoot!.querySelector('ox-entity360-dock') as OxEntity360Dock\nfunction view(name = 'Revision 1'): Entity360View {\n return { key: name, title: 'Test specification', context: name, labels, content: html`<input value=${name}>`, onClose: () => hideEntity360(owner) }\n}\n\ndescribe('shared nonmodal entity 360 dock', () => {\n beforeEach(async () => { bar = await fixture(html`<ox-aside-bar></ox-aside-bar>`) })\n afterEach(() => hideEntity360(owner))\n\n it('uses the aside layout without a modal backdrop or duplicate close action', async () => {\n showEntity360(owner, view())\n await settle()\n expect(dock()).to.exist\n expect(bar.shadowRoot!.querySelector('ox-floating-overlay')).to.equal(null)\n expect(!!dock().shadowRoot!.querySelector('[aria-modal]')).to.equal(matchMedia('(max-width: 900px)').matches)\n expect(dock().shadowRoot!.querySelectorAll('[data-action=\"close\"]').length).to.equal(1)\n })\n\n it('switches the contents in one dock and retains expanded state', async () => {\n showEntity360(owner, view())\n await settle()\n const original = dock()\n original.expanded = true\n showEntity360(owner, view('Approval after · Revision 2'))\n await elementUpdated(original)\n expect(dock()).to.equal(original)\n expect(original.expanded).to.equal(true)\n expect(original.view!.context).to.equal('Approval after · Revision 2')\n expect(original.shadowRoot!.textContent).to.contain('Approval after · Revision 2')\n })\n\n it('refreshes all content while keeping the dock and its read context', async () => {\n showEntity360(owner, view())\n await settle()\n const original = dock()\n original.expanded = true\n const content = original.shadowRoot!.querySelector('ox-entity360-content') as HTMLElement\n const input = content.shadowRoot!.querySelector('input')!\n ;(original.shadowRoot!.querySelector('[data-action=\"refresh\"]') as HTMLElement).click()\n await settle()\n expect(dock()).to.equal(original)\n expect(original.expanded).to.equal(true)\n expect(original.view!.key).to.equal('Revision 1')\n expect(content.shadowRoot!.querySelector('input')).not.to.equal(input)\n expect(content.shadowRoot!.querySelector('input')!.value).to.equal('Revision 1')\n })\n\n it('uses compact header controls and the shared scrollbar theme without local overrides', async () => {\n bar.style.setProperty('--scrollbar-thumb-color', 'rgb(57, 78, 100)')\n showEntity360(owner, { ...view(), content: html`<div style=\"height:3000px\">Long detail</div>` })\n await settle()\n const el = dock()\n const close = el.shadowRoot!.querySelector('[data-action=\"close\"]') as HTMLElement\n expect(close.getBoundingClientRect().width).to.equal(matchMedia('(pointer: coarse)').matches ? 40 : 28)\n const body = el.shadowRoot!.querySelector('.body') as HTMLElement\n expect(getComputedStyle(body).scrollbarGutter).to.equal('stable')\n expect(getComputedStyle(body, '::-webkit-scrollbar').width).to.equal('5px')\n expect(getComputedStyle(body, '::-webkit-scrollbar-track').backgroundColor).to.equal('rgba(0, 0, 0, 0)')\n expect(getComputedStyle(body, '::-webkit-scrollbar-thumb').backgroundColor).to.equal('rgb(57, 78, 100)')\n bar.style.setProperty('--scrollbar-width', '7px')\n bar.style.setProperty('--scrollbar-thumb-border-radius', '2px')\n expect(getComputedStyle(body, '::-webkit-scrollbar').width).to.equal('7px')\n expect(getComputedStyle(body, '::-webkit-scrollbar-thumb').borderRadius).to.equal('2px')\n })\n\n it('closes through the common button and restores the invoking control', async () => {\n let restored = false\n showEntity360(owner, view(), () => { restored = true })\n await settle()\n ;(dock().shadowRoot!.querySelector('[data-action=\"close\"]') as HTMLElement).click()\n await settle()\n expect(dock()).to.equal(null)\n expect(restored).to.equal(true)\n })\n\n it('Escape does not close the dock underneath a modal', async () => {\n showEntity360(owner, view())\n await settle()\n const state = history.state\n history.replaceState({ ...state, overlay: { name: 'confirmation' } }, '')\n document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }))\n expect(dock()).to.exist\n history.replaceState(state, '')\n document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }))\n await settle()\n expect(dock()).to.equal(null)\n })\n\n it('resizes using the keyboard without changing the read context', async () => {\n showEntity360(owner, view())\n await settle()\n const el = dock()\n el.shadowRoot!.querySelector('[role=\"separator\"]')!.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))\n await elementUpdated(el)\n expect(el.style.getPropertyValue('--entity360-width')).to.equal('448px')\n expect(el.view!.context).to.equal('Revision 1')\n })\n\n it('also mounts in fullbleed layouts', async () => {\n bar.setAttribute('fullbleed', '')\n showEntity360(owner, view())\n await settle()\n expect(dock()).to.exist\n })\n\n it('records distinct targets and preserves unrelated address state', async () => {\n const initial = location.href\n history.replaceState({ userState: 42 }, '', initial)\n const first = new URL(initial)\n first.searchParams.set('f', 'testSpecifications:one')\n first.searchParams.set('revision', 'r1')\n expect(await navigateEntity360(first.href)).to.equal(true)\n expect(canGoBackEntity360()).to.equal(false)\n const second = new URL(first)\n second.searchParams.set('revision', 'r2')\n expect(await navigateEntity360(second.href)).to.equal(true)\n expect(canGoBackEntity360()).to.equal(true)\n expect(history.state.userState).to.equal(42)\n expect(history.state.entity360Previous).to.equal(first.href)\n history.replaceState({}, '', initial)\n })\n})\n"]}
1
+ {"version":3,"file":"entity360.test.js","sourceRoot":"","sources":["../../test/entity360.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture, elementUpdated } from '@open-wc/testing'\nimport { html } from 'lit'\nimport '../src/index.js'\nimport { showEntity360, hideEntity360, isEntity360Unkept, navigateEntity360, canGoBackEntity360, ENTITY360_UNKEPT, type OxEntity360Dock, type Entity360View } from '../src/index.js'\n\nconst owner = {}\nconst labels = { close: 'Close', expand: 'Expand', collapse: 'Collapse', resize: 'Resize', back: 'Back' }\nconst settle = () => new Promise(resolve => setTimeout(resolve, 50))\nlet bar: HTMLElement\nconst dock = () => bar.shadowRoot!.querySelector('ox-entity360-dock') as OxEntity360Dock\nfunction view(name = 'Revision 1'): Entity360View {\n return { key: name, title: 'Test specification', context: name, labels, content: html`<input value=${name}>`, onClose: () => hideEntity360(owner) }\n}\n\ndescribe('shared nonmodal entity 360 dock', () => {\n beforeEach(async () => { bar = await fixture(html`<ox-aside-bar></ox-aside-bar>`) })\n afterEach(() => hideEntity360(owner))\n\n it('uses the aside layout without a modal backdrop or duplicate close action', async () => {\n showEntity360(owner, view())\n await settle()\n expect(dock()).to.exist\n expect(bar.shadowRoot!.querySelector('ox-floating-overlay')).to.equal(null)\n expect(!!dock().shadowRoot!.querySelector('[aria-modal]')).to.equal(matchMedia('(max-width: 900px)').matches)\n expect(dock().shadowRoot!.querySelectorAll('[data-action=\"close\"]').length).to.equal(1)\n })\n\n it('switches the contents in one dock and retains expanded state', async () => {\n showEntity360(owner, view())\n await settle()\n const original = dock()\n original.expanded = true\n showEntity360(owner, view('Approval after · Revision 2'))\n await elementUpdated(original)\n expect(dock()).to.equal(original)\n expect(original.expanded).to.equal(true)\n expect(original.view!.context).to.equal('Approval after · Revision 2')\n expect(original.shadowRoot!.textContent).to.contain('Approval after · Revision 2')\n })\n\n it('★ refresh reads again and keeps the contents - what is being written stays (ADR-0067 decision 8)', async () => {\n let refreshed = 0\n showEntity360(owner, { ...view(), onRefresh: () => refreshed++ })\n await settle()\n const original = dock()\n original.expanded = true\n const content = original.shadowRoot!.querySelector('ox-entity360-content') as HTMLElement\n const input = content.shadowRoot!.querySelector('input')!\n input.value = 'typed, not saved'\n ;(original.shadowRoot!.querySelector('[data-action=\"refresh\"]') as HTMLElement).click()\n await settle()\n expect(refreshed).to.equal(1)\n expect(dock()).to.equal(original)\n expect(original.expanded).to.equal(true)\n expect(content.shadowRoot!.querySelector('input')).to.equal(input)\n expect(input.value).to.equal('typed, not saved')\n })\n\n it('a dock that cannot read again draws no refresh button', async () => {\n showEntity360(owner, view())\n await settle()\n expect(dock().shadowRoot!.querySelector('[data-action=\"refresh\"]')).to.equal(null)\n })\n\n it('★ a section holding an entry no draft keeps makes the dock unkept, until it says otherwise', async () => {\n showEntity360(owner, view())\n await settle()\n const content = dock().shadowRoot!.querySelector('ox-entity360-content') as HTMLElement\n const input = content.shadowRoot!.querySelector('input')!\n const tell = (unkept: boolean) => input.dispatchEvent(new CustomEvent(ENTITY360_UNKEPT, { bubbles: true, composed: true, detail: { unkept } }))\n expect(isEntity360Unkept(owner)).to.equal(false)\n tell(true)\n expect(isEntity360Unkept(owner)).to.equal(true)\n tell(false)\n expect(isEntity360Unkept(owner)).to.equal(false)\n tell(true)\n showEntity360(owner, view('Revision 2'))\n await settle()\n expect(isEntity360Unkept(owner)).to.equal(false)\n })\n\n it('uses compact header controls and the shared scrollbar theme without local overrides', async () => {\n bar.style.setProperty('--scrollbar-thumb-color', 'rgb(57, 78, 100)')\n showEntity360(owner, { ...view(), content: html`<div style=\"height:3000px\">Long detail</div>` })\n await settle()\n const el = dock()\n const close = el.shadowRoot!.querySelector('[data-action=\"close\"]') as HTMLElement\n expect(close.getBoundingClientRect().width).to.equal(matchMedia('(pointer: coarse)').matches ? 40 : 28)\n const body = el.shadowRoot!.querySelector('.body') as HTMLElement\n expect(getComputedStyle(body).scrollbarGutter).to.equal('stable')\n expect(getComputedStyle(body, '::-webkit-scrollbar').width).to.equal('5px')\n expect(getComputedStyle(body, '::-webkit-scrollbar-track').backgroundColor).to.equal('rgba(0, 0, 0, 0)')\n expect(getComputedStyle(body, '::-webkit-scrollbar-thumb').backgroundColor).to.equal('rgb(57, 78, 100)')\n bar.style.setProperty('--scrollbar-width', '7px')\n bar.style.setProperty('--scrollbar-thumb-border-radius', '2px')\n expect(getComputedStyle(body, '::-webkit-scrollbar').width).to.equal('7px')\n expect(getComputedStyle(body, '::-webkit-scrollbar-thumb').borderRadius).to.equal('2px')\n })\n\n it('closes through the common button and restores the invoking control', async () => {\n let restored = false\n showEntity360(owner, view(), () => { restored = true })\n await settle()\n ;(dock().shadowRoot!.querySelector('[data-action=\"close\"]') as HTMLElement).click()\n await settle()\n expect(dock()).to.equal(null)\n expect(restored).to.equal(true)\n })\n\n it('Escape does not close the dock underneath a modal', async () => {\n showEntity360(owner, view())\n await settle()\n const state = history.state\n history.replaceState({ ...state, overlay: { name: 'confirmation' } }, '')\n document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }))\n expect(dock()).to.exist\n history.replaceState(state, '')\n document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }))\n await settle()\n expect(dock()).to.equal(null)\n })\n\n it('resizes using the keyboard without changing the read context', async () => {\n showEntity360(owner, view())\n await settle()\n const el = dock()\n el.shadowRoot!.querySelector('[role=\"separator\"]')!.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))\n await elementUpdated(el)\n expect(el.style.getPropertyValue('--entity360-width')).to.equal('448px')\n expect(el.view!.context).to.equal('Revision 1')\n })\n\n it('also mounts in fullbleed layouts', async () => {\n bar.setAttribute('fullbleed', '')\n showEntity360(owner, view())\n await settle()\n expect(dock()).to.exist\n })\n\n it('records distinct targets and preserves unrelated address state', async () => {\n const initial = location.href\n history.replaceState({ userState: 42 }, '', initial)\n const first = new URL(initial)\n first.searchParams.set('f', 'testSpecifications:one')\n first.searchParams.set('revision', 'r1')\n expect(await navigateEntity360(first.href)).to.equal(true)\n expect(canGoBackEntity360()).to.equal(false)\n const second = new URL(first)\n second.searchParams.set('revision', 'r2')\n expect(await navigateEntity360(second.href)).to.equal(true)\n expect(canGoBackEntity360()).to.equal(true)\n expect(history.state.userState).to.equal(42)\n expect(history.state.entity360Previous).to.equal(first.href)\n history.replaceState({}, '', initial)\n })\n})\n"]}
@@ -0,0 +1,2 @@
1
+ import '../src/index.js';
2
+ import '../src/components/ox-id-lens.js';
@@ -0,0 +1,162 @@
1
+ import { expect, fixture } from '@open-wc/testing';
2
+ import { html } from 'lit';
3
+ import '../src/index.js';
4
+ import '../src/components/ox-id-lens.js';
5
+ import { askIdLensDoors, foldIdLensAnswers, idLensAnswerOf, idLensHitToOpen, lookupText, registerEntity360Kind } from '../src/index.js';
6
+ /**
7
+ * The ID Lens (ADR-0133): the products give the doors, the lens asks, folds and opens. These are the rules every
8
+ * product's lens shares, and the guard that keeps any product's words out of the shared code.
9
+ */
10
+ const a = { kind: 'idlens-test-a', id: 'X-1', name: 'X-1' };
11
+ const b = { kind: 'idlens-test-b', id: 'X-1', name: 'X-1', status: 'open' };
12
+ const registered = (kind) => kind === a.kind || kind === b.kind;
13
+ const door = (kind, ask, label = kind.toUpperCase()) => ({ kind, label: () => label, ask });
14
+ describe('ID Lens rules', () => {
15
+ it('only the ends are trimmed - case, prefixes and digits stay as typed', () => {
16
+ expect(lookupText(' wo-2609-041 \n')).to.equal('wo-2609-041');
17
+ expect(lookupText('(01)08801234567890(10)A1')).to.equal('(01)08801234567890(10)A1');
18
+ expect(lookupText(undefined)).to.equal('');
19
+ });
20
+ it('one hit of a registered kind, every door answered - its 360 opens', () => {
21
+ const outcome = foldIdLensAnswers('X-1', [
22
+ { kind: a.kind, state: 'ready', hit: a },
23
+ { kind: b.kind, state: 'none' }
24
+ ]);
25
+ expect(idLensHitToOpen(outcome, registered)).to.deep.equal(a);
26
+ });
27
+ it('the same identifier in two kinds is a choice for the person - the first is never picked', () => {
28
+ const outcome = foldIdLensAnswers('X-1', [
29
+ { kind: a.kind, state: 'ready', hit: a },
30
+ { kind: b.kind, state: 'ready', hit: b }
31
+ ]);
32
+ expect(outcome.hits).to.have.length(2);
33
+ expect(idLensHitToOpen(outcome, registered)).to.equal(undefined);
34
+ });
35
+ it('a door that failed might have held another hit - the one hit is shown, not opened', () => {
36
+ const outcome = foldIdLensAnswers('X-1', [
37
+ { kind: a.kind, state: 'ready', hit: a },
38
+ { kind: b.kind, state: 'failed', message: 'timeout' }
39
+ ]);
40
+ expect(idLensHitToOpen(outcome, registered)).to.equal(undefined);
41
+ expect(outcome.failed).to.deep.equal([{ kind: b.kind, message: 'timeout' }]);
42
+ });
43
+ it('a kind this person may not read is named by kind only and does not stop the open', () => {
44
+ const outcome = foldIdLensAnswers('X-1', [
45
+ { kind: a.kind, state: 'forbidden' },
46
+ { kind: b.kind, state: 'ready', hit: b }
47
+ ]);
48
+ expect(outcome.forbidden).to.deep.equal([a.kind]);
49
+ expect(idLensHitToOpen(outcome, registered)).to.deep.equal(b);
50
+ });
51
+ it('a hit whose kind has no 360 is listed, never opened', () => {
52
+ const outcome = foldIdLensAnswers('X-1', [{ kind: 'idlens-test-none', state: 'ready', hit: { kind: 'idlens-test-none', id: 'X-1', name: 'X-1' } }]);
53
+ expect(idLensHitToOpen(outcome, registered)).to.equal(undefined);
54
+ });
55
+ it('a door that threw did not answer - it is failed, not none, and the other doors still count', async () => {
56
+ const outcome = await askIdLensDoors([
57
+ door(a.kind, async () => ({ state: 'ready', hit: a })),
58
+ door(b.kind, async () => {
59
+ throw new Error('offline');
60
+ })
61
+ ], 'X-1');
62
+ expect(outcome.hits).to.deep.equal([a]);
63
+ expect(outcome.failed).to.deep.equal([{ kind: b.kind, message: 'offline' }]);
64
+ });
65
+ it("a door's response reads as the 360 doors do: refused is forbidden, nothing is none", () => {
66
+ const hitOf = (row) => ({ kind: a.kind, id: row.name, name: row.name });
67
+ expect(idLensAnswerOf({ data: { row: { name: 'X-1' } } }, data => data.row, hitOf)).to.deep.equal({ state: 'ready', hit: a });
68
+ expect(idLensAnswerOf({ data: { row: null } }, data => data.row, hitOf).state).to.equal('none');
69
+ expect(idLensAnswerOf({ errors: [{ extensions: { code: 'FORBIDDEN' } }] }, data => data.row, hitOf).state).to.equal('forbidden');
70
+ /* A product that finds the row but does not count it as a hit says so with undefined. */
71
+ expect(idLensAnswerOf({ data: { row: { name: 'X-1' } } }, data => data.row, () => undefined).state).to.equal('none');
72
+ });
73
+ });
74
+ describe('ID Lens results', () => {
75
+ before(() => registerEntity360Kind({ kind: a.kind, typenames: [], title: subject => subject.id }));
76
+ it('kinds are said in the words the product gave its doors', async () => {
77
+ const doors = [door(a.kind, async () => ({ state: 'none' }), 'Kind A'), door(b.kind, async () => ({ state: 'none' }), 'Kind B')];
78
+ const outcome = foldIdLensAnswers('X-1', [
79
+ { kind: a.kind, state: 'forbidden' },
80
+ { kind: b.kind, state: 'failed' }
81
+ ]);
82
+ const results = await fixture(html `<ox-id-lens-results .outcome=${outcome} .doors=${doors}></ox-id-lens-results>`);
83
+ const text = results.shadowRoot.textContent;
84
+ expect(text).to.contain('Kind A');
85
+ expect(text).to.contain('Kind B');
86
+ });
87
+ it('a hit with a 360 or a work screen is a button; one with neither stays text and says so', async () => {
88
+ let opened = '';
89
+ const screen = { kind: 'idlens-test-screen', id: 'S-1', name: 'S-1', open: () => (opened = 'S-1') };
90
+ const bare = { kind: 'idlens-test-bare', id: 'B-1', name: 'B-1' };
91
+ const outcome = foldIdLensAnswers('X', [
92
+ { kind: a.kind, state: 'ready', hit: a },
93
+ { kind: screen.kind, state: 'ready', hit: screen },
94
+ { kind: bare.kind, state: 'ready', hit: bare }
95
+ ]);
96
+ const picked = [];
97
+ const results = await fixture(html `<ox-id-lens-results .outcome=${outcome} .onPick=${(hit) => { var _a; return (picked.push(hit.id), (_a = hit.open) === null || _a === void 0 ? void 0 : _a.call(hit)); }}></ox-id-lens-results>`);
98
+ const buttons = Array.from(results.shadowRoot.querySelectorAll('button.hit'));
99
+ expect(buttons).to.have.length(2);
100
+ buttons.forEach(button => button.click());
101
+ expect(picked).to.deep.equal(['X-1', 'S-1']);
102
+ expect(opened).to.equal('S-1');
103
+ expect(results.shadowRoot.querySelector('div.hit').textContent).to.contain('B-1');
104
+ });
105
+ });
106
+ describe('ID Lens field', () => {
107
+ it('a placeholder given as a function is read at render - a band registered once follows the language', async () => {
108
+ let word = 'first';
109
+ const lens = await fixture(html `<ox-id-lens .placeholder=${() => word}></ox-id-lens>`);
110
+ const field = () => lens.shadowRoot.querySelector('ox-input-barcode').getAttribute('placeholder');
111
+ expect(field()).to.equal('first');
112
+ word = 'second';
113
+ lens.requestUpdate();
114
+ await lens.updateComplete;
115
+ expect(field()).to.equal('second');
116
+ });
117
+ });
118
+ describe('ID Lens element source', () => {
119
+ /* What the lens does is read from its source, as it was in operato-plant before the lens moved here. */
120
+ const lensSource = async () => (await (await fetch('/src/components/ox-id-lens.ts')).text()).replace(/\/\*[\s\S]*?\*\//g, '');
121
+ it('asks the 360 registry what opens - the doors say nothing about 360s', async () => {
122
+ const lens = await lensSource();
123
+ expect(lens).to.match(/idLensHitToOpen\(outcome, entity360KindRegistered\)/);
124
+ expect(lens).to.match(/openEntity360Kind\(/);
125
+ });
126
+ it('reuses ox-input-barcode and listens to no page-wide keys; a page scanner is not the lens', async () => {
127
+ const lens = await lensSource();
128
+ expect(lens).to.match(/<ox-input-barcode /);
129
+ expect(lens).not.to.match(/window\.addEventListener|document\.addEventListener|key === 'Enter'|@keydown/);
130
+ for (const scanRule of ['listenForScans', 'classifyScan', 'parseGs1'])
131
+ expect(lens.includes(scanRule), scanRule).to.equal(false);
132
+ });
133
+ it('leaving the field is not a request to look - only Enter or a scan, which keep focus in the lens', async () => {
134
+ const lens = await lensSource();
135
+ expect(lens).to.match(/@change=\$\{this\.committed\}/);
136
+ expect(lens).to.match(/if \(this\.matches\(':focus-within'\)\) this\.find\(\)/);
137
+ });
138
+ it('the front mark follows the camera: with one, the magnifier finds; without, the QR mark', async () => {
139
+ const lens = await lensSource();
140
+ expect(lens).to.match(/class="find"[^>]*@click=\$\{\(\) => this\.find\(\)\}>\s*<md-icon aria-hidden="true">search<\/md-icon>/);
141
+ expect(lens).to.match(/class="scan"[^>]*@click=\$\{\(\) => this\.field\?\.input\?\.focus\(\)\}>\s*<md-icon aria-hidden="true">qr_code_scanner<\/md-icon>/);
142
+ expect(lens).to.match(/\.lens:has\(> ox-input-barcode\[scannable\]\) \.scan,\s*\.lens:not\(:has\(> ox-input-barcode\[scannable\]\)\) \.find \{\s*display: none;/);
143
+ expect(lens).not.to.match(/without-scan-button/);
144
+ expect(lens).to.match(/--barcodescan-input-button-icon-size: auto 15px;/);
145
+ });
146
+ });
147
+ describe('ID Lens holds no product', () => {
148
+ /*
149
+ * ADR-0133 2-1: the shared lens owns no kind's name, rule or privilege. A product word here means a product's
150
+ * knowledge moved into the shared code - the doors are where it belongs (architect ruling 2026-10-23).
151
+ */
152
+ const words = /\b(plant|warehouse|lots?|job-?orders?|sscc|sgln|gtin|locations?|pallets?|orders?|tasks?)\b|로트|작업지시|창고|공장/i;
153
+ for (const file of ['/src/actions/id-lens.ts', '/src/components/ox-id-lens.ts']) {
154
+ it(`${file} names no product's kinds`, async () => {
155
+ const source = await (await fetch(file)).text();
156
+ expect(source.length, `${file} was not read`).to.be.greaterThan(1000);
157
+ const found = source.match(words);
158
+ expect(found === null || found === void 0 ? void 0 : found[0], `${file} says "${found === null || found === void 0 ? void 0 : found[0]}"`).to.equal(undefined);
159
+ });
160
+ }
161
+ });
162
+ //# sourceMappingURL=id-lens.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-lens.test.js","sourceRoot":"","sources":["../../test/id-lens.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture } from '@open-wc/testing'\nimport { html } from 'lit'\nimport '../src/index.js'\nimport '../src/components/ox-id-lens.js'\nimport {\n askIdLensDoors,\n foldIdLensAnswers,\n idLensAnswerOf,\n idLensHitToOpen,\n lookupText,\n registerEntity360Kind,\n type IdLensDoor\n} from '../src/index.js'\nimport type { OxIdLensResults } from '../src/components/ox-id-lens.js'\n\n/**\n * The ID Lens (ADR-0133): the products give the doors, the lens asks, folds and opens. These are the rules every\n * product's lens shares, and the guard that keeps any product's words out of the shared code.\n */\n\nconst a = { kind: 'idlens-test-a', id: 'X-1', name: 'X-1' }\nconst b = { kind: 'idlens-test-b', id: 'X-1', name: 'X-1', status: 'open' }\nconst registered = (kind: string) => kind === a.kind || kind === b.kind\n\nconst door = (kind: string, ask: IdLensDoor['ask'], label = kind.toUpperCase()): IdLensDoor => ({ kind, label: () => label, ask })\n\ndescribe('ID Lens rules', () => {\n it('only the ends are trimmed - case, prefixes and digits stay as typed', () => {\n expect(lookupText(' wo-2609-041 \\n')).to.equal('wo-2609-041')\n expect(lookupText('(01)08801234567890(10)A1')).to.equal('(01)08801234567890(10)A1')\n expect(lookupText(undefined)).to.equal('')\n })\n\n it('one hit of a registered kind, every door answered - its 360 opens', () => {\n const outcome = foldIdLensAnswers('X-1', [\n { kind: a.kind, state: 'ready', hit: a },\n { kind: b.kind, state: 'none' }\n ])\n expect(idLensHitToOpen(outcome, registered)).to.deep.equal(a)\n })\n\n it('the same identifier in two kinds is a choice for the person - the first is never picked', () => {\n const outcome = foldIdLensAnswers('X-1', [\n { kind: a.kind, state: 'ready', hit: a },\n { kind: b.kind, state: 'ready', hit: b }\n ])\n expect(outcome.hits).to.have.length(2)\n expect(idLensHitToOpen(outcome, registered)).to.equal(undefined)\n })\n\n it('a door that failed might have held another hit - the one hit is shown, not opened', () => {\n const outcome = foldIdLensAnswers('X-1', [\n { kind: a.kind, state: 'ready', hit: a },\n { kind: b.kind, state: 'failed', message: 'timeout' }\n ])\n expect(idLensHitToOpen(outcome, registered)).to.equal(undefined)\n expect(outcome.failed).to.deep.equal([{ kind: b.kind, message: 'timeout' }])\n })\n\n it('a kind this person may not read is named by kind only and does not stop the open', () => {\n const outcome = foldIdLensAnswers('X-1', [\n { kind: a.kind, state: 'forbidden' },\n { kind: b.kind, state: 'ready', hit: b }\n ])\n expect(outcome.forbidden).to.deep.equal([a.kind])\n expect(idLensHitToOpen(outcome, registered)).to.deep.equal(b)\n })\n\n it('a hit whose kind has no 360 is listed, never opened', () => {\n const outcome = foldIdLensAnswers('X-1', [{ kind: 'idlens-test-none', state: 'ready', hit: { kind: 'idlens-test-none', id: 'X-1', name: 'X-1' } }])\n expect(idLensHitToOpen(outcome, registered)).to.equal(undefined)\n })\n\n it('a door that threw did not answer - it is failed, not none, and the other doors still count', async () => {\n const outcome = await askIdLensDoors(\n [\n door(a.kind, async () => ({ state: 'ready', hit: a })),\n door(b.kind, async () => {\n throw new Error('offline')\n })\n ],\n 'X-1'\n )\n expect(outcome.hits).to.deep.equal([a])\n expect(outcome.failed).to.deep.equal([{ kind: b.kind, message: 'offline' }])\n })\n\n it(\"a door's response reads as the 360 doors do: refused is forbidden, nothing is none\", () => {\n const hitOf = (row: { name: string }) => ({ kind: a.kind, id: row.name, name: row.name })\n expect(idLensAnswerOf({ data: { row: { name: 'X-1' } } }, data => data.row, hitOf)).to.deep.equal({ state: 'ready', hit: a })\n expect(idLensAnswerOf({ data: { row: null } }, data => data.row, hitOf).state).to.equal('none')\n expect(idLensAnswerOf({ errors: [{ extensions: { code: 'FORBIDDEN' } }] }, data => data.row, hitOf).state).to.equal('forbidden')\n /* A product that finds the row but does not count it as a hit says so with undefined. */\n expect(idLensAnswerOf({ data: { row: { name: 'X-1' } } }, data => data.row, () => undefined).state).to.equal('none')\n })\n})\n\ndescribe('ID Lens results', () => {\n before(() => registerEntity360Kind({ kind: a.kind, typenames: [], title: subject => subject.id }))\n\n it('kinds are said in the words the product gave its doors', async () => {\n const doors = [door(a.kind, async () => ({ state: 'none' }), 'Kind A'), door(b.kind, async () => ({ state: 'none' }), 'Kind B')]\n const outcome = foldIdLensAnswers('X-1', [\n { kind: a.kind, state: 'forbidden' },\n { kind: b.kind, state: 'failed' }\n ])\n const results = await fixture<OxIdLensResults>(html`<ox-id-lens-results .outcome=${outcome} .doors=${doors}></ox-id-lens-results>`)\n const text = results.shadowRoot!.textContent!\n expect(text).to.contain('Kind A')\n expect(text).to.contain('Kind B')\n })\n\n it('a hit with a 360 or a work screen is a button; one with neither stays text and says so', async () => {\n let opened = ''\n const screen = { kind: 'idlens-test-screen', id: 'S-1', name: 'S-1', open: () => (opened = 'S-1') }\n const bare = { kind: 'idlens-test-bare', id: 'B-1', name: 'B-1' }\n const outcome = foldIdLensAnswers('X', [\n { kind: a.kind, state: 'ready', hit: a },\n { kind: screen.kind, state: 'ready', hit: screen },\n { kind: bare.kind, state: 'ready', hit: bare }\n ])\n const picked: string[] = []\n const results = await fixture<OxIdLensResults>(\n html`<ox-id-lens-results .outcome=${outcome} .onPick=${(hit: any) => (picked.push(hit.id), hit.open?.())}></ox-id-lens-results>`\n )\n const buttons = Array.from(results.shadowRoot!.querySelectorAll('button.hit')) as HTMLButtonElement[]\n expect(buttons).to.have.length(2)\n buttons.forEach(button => button.click())\n expect(picked).to.deep.equal(['X-1', 'S-1'])\n expect(opened).to.equal('S-1')\n expect(results.shadowRoot!.querySelector('div.hit')!.textContent).to.contain('B-1')\n })\n})\n\ndescribe('ID Lens field', () => {\n it('a placeholder given as a function is read at render - a band registered once follows the language', async () => {\n let word = 'first'\n const lens = await fixture<HTMLElement & { requestUpdate(): void; updateComplete: Promise<boolean> }>(\n html`<ox-id-lens .placeholder=${() => word}></ox-id-lens>`\n )\n const field = () => lens.shadowRoot!.querySelector('ox-input-barcode')!.getAttribute('placeholder')\n expect(field()).to.equal('first')\n word = 'second'\n lens.requestUpdate()\n await lens.updateComplete\n expect(field()).to.equal('second')\n })\n})\n\ndescribe('ID Lens element source', () => {\n /* What the lens does is read from its source, as it was in operato-plant before the lens moved here. */\n const lensSource = async () => (await (await fetch('/src/components/ox-id-lens.ts')).text()).replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n\n it('asks the 360 registry what opens - the doors say nothing about 360s', async () => {\n const lens = await lensSource()\n expect(lens).to.match(/idLensHitToOpen\\(outcome, entity360KindRegistered\\)/)\n expect(lens).to.match(/openEntity360Kind\\(/)\n })\n\n it('reuses ox-input-barcode and listens to no page-wide keys; a page scanner is not the lens', async () => {\n const lens = await lensSource()\n expect(lens).to.match(/<ox-input-barcode /)\n expect(lens).not.to.match(/window\\.addEventListener|document\\.addEventListener|key === 'Enter'|@keydown/)\n for (const scanRule of ['listenForScans', 'classifyScan', 'parseGs1']) expect(lens.includes(scanRule), scanRule).to.equal(false)\n })\n\n it('leaving the field is not a request to look - only Enter or a scan, which keep focus in the lens', async () => {\n const lens = await lensSource()\n expect(lens).to.match(/@change=\\$\\{this\\.committed\\}/)\n expect(lens).to.match(/if \\(this\\.matches\\(':focus-within'\\)\\) this\\.find\\(\\)/)\n })\n\n it('the front mark follows the camera: with one, the magnifier finds; without, the QR mark', async () => {\n const lens = await lensSource()\n expect(lens).to.match(/class=\"find\"[^>]*@click=\\$\\{\\(\\) => this\\.find\\(\\)\\}>\\s*<md-icon aria-hidden=\"true\">search<\\/md-icon>/)\n expect(lens).to.match(/class=\"scan\"[^>]*@click=\\$\\{\\(\\) => this\\.field\\?\\.input\\?\\.focus\\(\\)\\}>\\s*<md-icon aria-hidden=\"true\">qr_code_scanner<\\/md-icon>/)\n expect(lens).to.match(/\\.lens:has\\(> ox-input-barcode\\[scannable\\]\\) \\.scan,\\s*\\.lens:not\\(:has\\(> ox-input-barcode\\[scannable\\]\\)\\) \\.find \\{\\s*display: none;/)\n expect(lens).not.to.match(/without-scan-button/)\n expect(lens).to.match(/--barcodescan-input-button-icon-size: auto 15px;/)\n })\n})\n\ndescribe('ID Lens holds no product', () => {\n /*\n * ADR-0133 2-1: the shared lens owns no kind's name, rule or privilege. A product word here means a product's\n * knowledge moved into the shared code - the doors are where it belongs (architect ruling 2026-10-23).\n */\n const words = /\\b(plant|warehouse|lots?|job-?orders?|sscc|sgln|gtin|locations?|pallets?|orders?|tasks?)\\b|로트|작업지시|창고|공장/i\n\n for (const file of ['/src/actions/id-lens.ts', '/src/components/ox-id-lens.ts']) {\n it(`${file} names no product's kinds`, async () => {\n const source = await (await fetch(file)).text()\n expect(source.length, `${file} was not read`).to.be.greaterThan(1000)\n const found = source.match(words)\n expect(found?.[0], `${file} says \"${found?.[0]}\"`).to.equal(undefined)\n })\n }\n})\n"]}