@operato/shell 10.29.37 → 10.29.39

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/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.37",
5
+ "version": "10.29.39",
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.37",
63
+ "@operato/graphql": "^10.29.39",
64
64
  "@operato/i18n": "^10.29.27",
65
- "@operato/popup": "^10.29.37",
65
+ "@operato/popup": "^10.29.39",
66
66
  "@operato/styles": "^10.29.30",
67
- "@operato/utils": "^10.29.37",
67
+ "@operato/utils": "^10.29.39",
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": "38361a65226ee9f23814747b4f0520edf42c3184"
106
+ "gitHead": "f48742480ad2b9ce87f0b3b4c3ac5923f4866ad6"
107
107
  }
@@ -52,7 +52,7 @@ describe('draft decision', () => {
52
52
  expect(draftDecision({ at: now - DRAFT_LIFETIME_MS - 1, base: 7 }, 7, now)).to.equal('drop')
53
53
  })
54
54
 
55
- it('a key never lets one user read another\'s draft, and survives odd names', () => {
55
+ it("a key never lets one user read another's draft, and survives odd names", () => {
56
56
  expect(draftKey(at('x', 'u1'))).to.not.equal(draftKey(at('x', 'u2')))
57
57
  expect(draftKey({ user: 'a/b', domain: 'd', screen: 's', target: 't' })).to.not.equal(
58
58
  draftKey({ user: 'a', domain: 'b/d', screen: 's', target: 't' })
@@ -69,7 +69,7 @@ describe('draft store', () => {
69
69
  expect(read?.base).to.equal(7)
70
70
  })
71
71
 
72
- it('★ sign-out takes one user\'s drafts, and only theirs', async () => {
72
+ it("★ sign-out takes one user's drafts, and only theirs", async () => {
73
73
  await writeDraft({ key: draftKey(at('a', 'leaving')), value: 1, base: null, at: 1 })
74
74
  await writeDraft({ key: draftKey(at('b', 'leaving')), value: 2, base: null, at: 1 })
75
75
  await writeDraft({ key: draftKey(at('a', 'staying')), value: 3, base: null, at: 1 })
@@ -84,10 +84,15 @@ describe('draft store', () => {
84
84
 
85
85
  describe('UnsavedDraftController', () => {
86
86
  const originalOpen = OxPrompt.open
87
- afterEach(() => ((OxPrompt as any).open = originalOpen))
87
+ const hosts: Host[] = []
88
+ afterEach(() => {
89
+ ;(OxPrompt as any).open = originalOpen
90
+ hosts.splice(0).forEach(host => host.disconnect())
91
+ })
88
92
 
89
93
  function screen(target: string, state: { value?: number; base: number | null; saved: number | null }) {
90
94
  const host = new Host()
95
+ hosts.push(host)
91
96
  const restored: any[] = []
92
97
  const controller = new UnsavedDraftController<number>(host as any, {
93
98
  address: () => at(target),
@@ -138,8 +143,9 @@ describe('UnsavedDraftController', () => {
138
143
  expect(await readDraft(draftKey(at('saved')))).to.equal(undefined)
139
144
  })
140
145
 
141
- it('★ where drafts cannot be kept, the browser\'s own question comes back while something is unsaved', async () => {
146
+ it("★ where drafts cannot be kept, the browser's own question comes back while something is unsaved", async () => {
142
147
  const { controller } = screen('fallback', { value: 1, base: null, saved: null })
148
+ await controller.flush()
143
149
  ;(controller as any).cannotKeep = true
144
150
  const event = new Event('beforeunload', { cancelable: true })
145
151
  window.dispatchEvent(event)
@@ -150,4 +156,84 @@ describe('UnsavedDraftController', () => {
150
156
  window.dispatchEvent(kept)
151
157
  expect(kept.defaultPrevented).to.equal(false)
152
158
  })
159
+ it('a changed edit is not reported durable before its transaction has committed', async () => {
160
+ const state = { value: 1, base: 7, saved: 7 }
161
+ const { controller, host } = screen('durable', state)
162
+ expect(controller.keeps).to.equal(false)
163
+ await controller.flush()
164
+ expect(controller.keeps).to.equal(true)
165
+ state.value = 2
166
+ expect(controller.keeps).to.equal(false)
167
+ await controller.flush()
168
+ expect(controller.keeps).to.equal(true)
169
+ host.disconnect()
170
+ })
171
+
172
+ it('an edit captured before changing queries keeps its original key and value', async () => {
173
+ const host = new Host()
174
+ hosts.push(host)
175
+ let target = 'october'
176
+ let value = 10
177
+ const controller = new UnsavedDraftController(host as any, {
178
+ address: () => at(target),
179
+ snapshot: () => ({ value, base: 1 }),
180
+ savedRevision: () => 1,
181
+ restore() {}
182
+ })
183
+ host.connect()
184
+ const storing = controller.flush()
185
+ target = 'november'
186
+ value = 11
187
+ await storing
188
+ expect((await readDraft<number>(draftKey(at('october'))))?.value).to.equal(10)
189
+ expect(await readDraft(draftKey(at('november')))).to.equal(undefined)
190
+ expect(controller.keeps).to.equal(false)
191
+ host.disconnect()
192
+ })
193
+
194
+ it('disconnecting an owner cancels restoration even if its old question later accepts', async () => {
195
+ const first = screen('stale-offer', { value: 42, base: 5, saved: 5 })
196
+ await first.controller.flush()
197
+ let answer!: (accepted: boolean) => void
198
+ ;(OxPrompt as any).open = () =>
199
+ new Promise(resolve => {
200
+ answer = resolve
201
+ })
202
+ const second = screen('stale-offer', { base: 5, saved: 5 })
203
+ const offered = second.controller.offer()
204
+ while (!answer) await new Promise(resolve => setTimeout(resolve, 0))
205
+ second.host.disconnect()
206
+ answer(true)
207
+ expect(await offered).to.equal(false)
208
+ expect(second.restored).to.deep.equal([])
209
+ expect(await readDraft(draftKey(at('stale-offer')))).not.to.equal(undefined)
210
+ first.host.disconnect()
211
+ })
212
+
213
+ it('a signed-out owner cannot restore or delete its old draft from a late answer', async () => {
214
+ const host = new Host()
215
+ hosts.push(host)
216
+ let signedIn = true
217
+ const restored: number[] = []
218
+ const controller = new UnsavedDraftController(host as any, {
219
+ address: () => (signedIn ? at('signed-out') : undefined),
220
+ snapshot: () => ({ value: 42, base: 5 }),
221
+ savedRevision: () => 5,
222
+ restore: value => restored.push(value)
223
+ })
224
+ host.connect()
225
+ await controller.flush()
226
+ let answer!: (accepted: boolean) => void
227
+ ;(OxPrompt as any).open = () =>
228
+ new Promise(resolve => {
229
+ answer = resolve
230
+ })
231
+ const offered = controller.offer()
232
+ while (!answer) await new Promise(resolve => setTimeout(resolve, 0))
233
+ signedIn = false
234
+ answer(true)
235
+ expect(await offered).to.equal(false)
236
+ expect(restored).to.deep.equal([])
237
+ host.disconnect()
238
+ })
153
239
  })