@operato/graphql 10.29.76 → 10.29.79

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/graphql",
3
3
  "description": "Webcomponent graphql-client following open-wc recommendations",
4
4
  "author": "heartyoh@hatiolab.com",
5
- "version": "10.29.76",
5
+ "version": "10.29.79",
6
6
  "type": "module",
7
7
  "main": "dist/src/index.js",
8
8
  "module": "dist/src/index.js",
@@ -127,5 +127,5 @@
127
127
  "prettier --write"
128
128
  ]
129
129
  },
130
- "gitHead": "08d33aec6fbe7c55cbb8e5018781a8500c792d4d"
130
+ "gitHead": "f86fbc40c2d343d7996573fe49f82829c1ac1ea4"
131
131
  }
@@ -0,0 +1,146 @@
1
+ import { expect, fixture } from '@open-wc/testing'
2
+ import gql from 'graphql-tag'
3
+ import { html, LitElement } from 'lit'
4
+
5
+ import { resetActiveRequestCounterCallback, setActiveRequestCounterCallback } from '../src/active-request-counter-link.js'
6
+ import { client } from '../src/graphql-client.js'
7
+ import { QueryController } from '../src/query-controller.js'
8
+
9
+ /**
10
+ * The shell shows its progress bar while the count is not zero (shell/actions/busy.ts). Every request that counts up
11
+ * counts down exactly once - answered, failed, refused, aborted, or left by the screen that asked.
12
+ */
13
+
14
+ const query = gql`
15
+ query ($id: String) {
16
+ ping(id: $id)
17
+ }
18
+ `
19
+
20
+ const respond = (body: unknown, status = 200) =>
21
+ new Response(JSON.stringify(body), { status, headers: { 'content-type': 'application/json' } })
22
+
23
+ const settle = () => new Promise(resolve => setTimeout(resolve, 20))
24
+
25
+ let count: number
26
+ let calls: number[]
27
+ let fetched: typeof window.fetch
28
+ const silence = (event: Event) => event.stopImmediatePropagation()
29
+
30
+ beforeEach(() => {
31
+ count = 0
32
+ calls = []
33
+ fetched = window.fetch
34
+ setActiveRequestCounterCallback(now => {
35
+ count = now
36
+ calls.push(now)
37
+ })
38
+ document.addEventListener('notify', silence)
39
+ document.addEventListener('auth-required', silence)
40
+ document.addEventListener('domain-required', silence)
41
+ })
42
+
43
+ afterEach(() => {
44
+ window.fetch = fetched
45
+ resetActiveRequestCounterCallback()
46
+ document.removeEventListener('notify', silence)
47
+ document.removeEventListener('auth-required', silence)
48
+ document.removeEventListener('domain-required', silence)
49
+ })
50
+
51
+ const read = () => client.query({ query, fetchPolicy: 'no-cache' }).catch(error => error)
52
+
53
+ describe('the active request count', () => {
54
+ it('goes back to zero after an answer', async () => {
55
+ window.fetch = async () => respond({ data: { ping: 'pong' } })
56
+ await read()
57
+ expect(calls).to.deep.equal([1, 0])
58
+ })
59
+
60
+ it('goes back to zero after an answer with errors', async () => {
61
+ window.fetch = async () => respond({ data: null, errors: [{ message: 'no' }] })
62
+ await read()
63
+ expect(calls).to.deep.equal([1, 0])
64
+ })
65
+
66
+ it('goes back to zero after a dropped connection', async () => {
67
+ window.fetch = () => Promise.reject(new TypeError('Failed to fetch'))
68
+ await read()
69
+ expect(calls).to.deep.equal([1, 0])
70
+ })
71
+
72
+ it('goes back to zero once after an error status that carries data and errors', async () => {
73
+ window.fetch = async () => respond({ data: { ping: null }, errors: [{ message: 'refused' }] }, 403)
74
+ await read()
75
+ await settle()
76
+ expect(calls).to.deep.equal([1, 0])
77
+ })
78
+
79
+ it('goes back to zero after a 401', async () => {
80
+ window.fetch = async () => respond({ errors: [{ message: 'sign in' }] }, 401)
81
+ await read()
82
+ expect(calls).to.deep.equal([1, 0])
83
+ })
84
+
85
+ it('goes back to zero after a read aborted with its signal', async () => {
86
+ window.fetch = (_input, init) =>
87
+ new Promise((_, reject) =>
88
+ init!.signal!.addEventListener('abort', () => reject(new DOMException('aborted', 'AbortError')))
89
+ )
90
+ const controller = new AbortController()
91
+ const reading = client
92
+ .query({ query, fetchPolicy: 'no-cache', context: { fetchOptions: { signal: controller.signal } } })
93
+ .catch(error => error)
94
+ controller.abort()
95
+ await reading
96
+ await settle()
97
+ expect(count).to.equal(0)
98
+ })
99
+
100
+ it('goes back to zero when the watcher stops before the answer', async () => {
101
+ let answer!: (response: Response) => void
102
+ window.fetch = () => new Promise(resolve => (answer = resolve))
103
+ const subscription = client.watchQuery({ query, fetchPolicy: 'no-cache' }).subscribe({ error: () => {} })
104
+ await settle()
105
+ expect(count).to.equal(1)
106
+ subscription.unsubscribe()
107
+ await settle()
108
+ expect(count).to.equal(0)
109
+ /* The answer that comes after is not counted again. */
110
+ answer(respond({ data: { ping: 'late' } }))
111
+ await settle()
112
+ expect(calls).to.deep.equal([1, 0])
113
+ })
114
+
115
+ it('goes back to zero when a screen asks for other variables, and when it leaves', async () => {
116
+ const pending: ((response: Response) => void)[] = []
117
+ window.fetch = () => new Promise(resolve => pending.push(resolve))
118
+
119
+ class PingView extends LitElement {
120
+ static properties = { pingId: {} }
121
+ pingId = 'a'
122
+ ping = new QueryController(this, query, { variables: () => ({ id: this.pingId }) })
123
+ render() {
124
+ return html``
125
+ }
126
+ }
127
+ customElements.define('active-request-ping-view', PingView)
128
+
129
+ const view = await fixture<PingView>(html`<active-request-ping-view></active-request-ping-view>`)
130
+ await settle()
131
+ expect(count).to.equal(1)
132
+
133
+ view.pingId = 'b'
134
+ await view.updateComplete
135
+ await settle()
136
+ expect(count).to.equal(1)
137
+
138
+ view.remove()
139
+ await settle()
140
+ expect(count).to.equal(0)
141
+
142
+ pending.forEach(resolve => resolve(respond({ data: { ping: 'late' } })))
143
+ await settle()
144
+ expect(count).to.equal(0)
145
+ })
146
+ })