@operato/shell 10.29.40 → 10.29.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/coverage/lcov-report/index.html +83 -83
- package/coverage/lcov-report/test/fixtures/guarded-define.ts.html +1 -1
- package/coverage/lcov-report/test/fixtures/index.html +1 -1
- package/coverage/lcov-report/test/fixtures/no-registration.ts.html +1 -1
- package/coverage/lcov-report/test/fixtures/registers.ts.html +1 -1
- package/coverage/lcov-report/test/fixtures/unguarded-define.ts.html +1 -1
- package/coverage/lcov.info +49968 -49472
- package/dist/src/actions/route.d.ts +1 -1
- package/dist/src/actions/route.js +2 -2
- package/dist/src/actions/route.js.map +1 -1
- package/dist/src/app/app.js +7 -5
- package/dist/src/app/app.js.map +1 -1
- package/dist/src/app/pages/page-view.d.ts +30 -5
- package/dist/src/app/pages/page-view.js +52 -18
- package/dist/src/app/pages/page-view.js.map +1 -1
- package/dist/src/router.js +2 -2
- package/dist/src/router.js.map +1 -1
- package/dist/test/leaving-edits.test.d.ts +1 -0
- package/dist/test/leaving-edits.test.js +87 -0
- package/dist/test/leaving-edits.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/test/leaving-edits.test.ts +94 -0
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@operato/shell",
|
|
3
3
|
"description": "WebApplication architecturing shell following open-wc recommendations",
|
|
4
4
|
"author": "heartyoh",
|
|
5
|
-
"version": "10.29.
|
|
5
|
+
"version": "10.29.43",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/src/index.js",
|
|
8
8
|
"module": "dist/src/index.js",
|
|
@@ -60,11 +60,11 @@
|
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@material/web": "^2.0.0",
|
|
63
|
-
"@operato/graphql": "^10.29.
|
|
63
|
+
"@operato/graphql": "^10.29.43",
|
|
64
64
|
"@operato/i18n": "^10.29.27",
|
|
65
|
-
"@operato/popup": "^10.29.
|
|
65
|
+
"@operato/popup": "^10.29.43",
|
|
66
66
|
"@operato/styles": "^10.29.30",
|
|
67
|
-
"@operato/utils": "^10.29.
|
|
67
|
+
"@operato/utils": "^10.29.43",
|
|
68
68
|
"@webcomponents/scoped-custom-element-registry": "^0.0.9",
|
|
69
69
|
"lit": "^3.1.2",
|
|
70
70
|
"lodash-es": "^4.17.21",
|
|
@@ -103,5 +103,5 @@
|
|
|
103
103
|
"prettier --write"
|
|
104
104
|
]
|
|
105
105
|
},
|
|
106
|
-
"gitHead": "
|
|
106
|
+
"gitHead": "ccc06fed313fcc20a076a1cf7bc586fdacaba594"
|
|
107
107
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { expect, fixture } from '@open-wc/testing'
|
|
2
|
+
import { html } from 'lit'
|
|
3
|
+
|
|
4
|
+
import { PageView, staysOn } from '../src/app/pages/page-view.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* What leaving with unsaved edits asks (address-state-ownership §6.4, ruling 2026-10-19): only a change that would
|
|
8
|
+
* discard them. Grid edits stay in the cached page when another page is shown, as they did before 2026-10-17; a
|
|
9
|
+
* page's own unsaved state (a modeller's model) is asked about whenever it is left, as it was then.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
class ListPage extends PageView {
|
|
13
|
+
render() {
|
|
14
|
+
return html`<ox-grist id="bound"></ox-grist><ox-grist id="detail"></ox-grist>`
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
customElements.define('leaving-list-page', ListPage)
|
|
18
|
+
|
|
19
|
+
class ModellerPage extends PageView {
|
|
20
|
+
unsaved = false
|
|
21
|
+
get addressDirty() {
|
|
22
|
+
return this.unsaved
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
customElements.define('leaving-modeller-page', ModellerPage)
|
|
26
|
+
|
|
27
|
+
const query = { route: false, query: true }
|
|
28
|
+
const route = { route: true, query: false }
|
|
29
|
+
|
|
30
|
+
const listPage = async (bound: number, detail: number) => {
|
|
31
|
+
const page = await fixture<ListPage>(html`<leaving-list-page active></leaving-list-page>`)
|
|
32
|
+
Object.assign(page.renderRoot.querySelector('#bound')!, { urlParamsSensitive: true, dirtyRecords: new Array(bound) })
|
|
33
|
+
Object.assign(page.renderRoot.querySelector('#detail')!, { dirtyRecords: new Array(detail) })
|
|
34
|
+
return page
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe('leaving with unsaved edits', () => {
|
|
38
|
+
it('showing another page asks nothing: the grid edits stay in the cached page', async () => {
|
|
39
|
+
const page = await listPage(1, 1)
|
|
40
|
+
expect(page.discards(route, false)).to.equal(false)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('a new query for the url-bound grid that holds edits asks', async () => {
|
|
44
|
+
const page = await listPage(1, 0)
|
|
45
|
+
expect(page.discards(query, true)).to.equal(true)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('a new query asks nothing when only a grid not bound to the address holds edits', async () => {
|
|
49
|
+
const page = await listPage(0, 1)
|
|
50
|
+
expect(page.discards(query, true)).to.equal(false)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('new route arguments for the page on screen ask about every grid', async () => {
|
|
54
|
+
const page = await listPage(0, 1)
|
|
55
|
+
expect(page.discards(route, true)).to.equal(true)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it("a page's own unsaved state is asked about when the page is left", async () => {
|
|
59
|
+
const page = await fixture<ModellerPage>(html`<leaving-modeller-page></leaving-modeller-page>`)
|
|
60
|
+
page.unsaved = true
|
|
61
|
+
expect(page.discards(route, false)).to.equal(true)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('closing the instance asks first when it holds unsaved edits, and answers with the user', async () => {
|
|
65
|
+
class Asking extends ListPage {
|
|
66
|
+
answer = false
|
|
67
|
+
asked = 0
|
|
68
|
+
async canDeactivate() {
|
|
69
|
+
this.asked++
|
|
70
|
+
return this.answer
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
customElements.define('leaving-asking-page', Asking)
|
|
74
|
+
const page = await fixture<Asking>(html`<leaving-asking-page active></leaving-asking-page>`)
|
|
75
|
+
Object.assign(page.renderRoot.querySelector('#detail')!, { dirtyRecords: [{}], reset() {} })
|
|
76
|
+
expect(await page.confirmClose()).to.equal(false)
|
|
77
|
+
page.answer = true
|
|
78
|
+
expect(await page.confirmClose()).to.equal(true)
|
|
79
|
+
expect(page.asked).to.equal(2)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('closing a clean instance asks nothing', async () => {
|
|
83
|
+
const page = await listPage(0, 0)
|
|
84
|
+
expect(await page.confirmClose()).to.equal(true)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('a change stays on the page when the path is the same, or names the same page', async () => {
|
|
88
|
+
const page = await fixture<ListPage>(html`<leaving-list-page data-page="ledger"></leaving-list-page>`)
|
|
89
|
+
const at = (path: string) => new URL(path, location.origin)
|
|
90
|
+
expect(staysOn(page, at('/ledger?filters=x'), at('/ledger'))).to.equal(true)
|
|
91
|
+
expect(staysOn(page, at('/ledger/2'), at('/ledger/1'))).to.equal(true)
|
|
92
|
+
expect(staysOn(page, at('/employees'), at('/ledger'))).to.equal(false)
|
|
93
|
+
})
|
|
94
|
+
})
|