@knowark/componarkjs 1.13.4 → 1.14.0

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 (35) hide show
  1. package/lib/base/component/component.js +17 -1
  2. package/lib/base/component/component.test.js +475 -389
  3. package/lib/base/utils/define.js +28 -6
  4. package/lib/base/utils/define.test.js +129 -42
  5. package/lib/base/utils/format.test.js +16 -16
  6. package/lib/base/utils/helpers.js +11 -4
  7. package/lib/base/utils/helpers.test.js +134 -115
  8. package/lib/base/utils/slots.test.js +38 -38
  9. package/lib/base/utils/uuid.test.js +13 -13
  10. package/lib/components/audio/components/audio.js +19 -1
  11. package/lib/components/audio/components/audio.test.js +120 -90
  12. package/lib/components/camera/components/camera.js +5 -0
  13. package/lib/components/camera/components/camera.test.js +96 -91
  14. package/lib/components/capture/components/capture.js +30 -2
  15. package/lib/components/capture/components/capture.test.js +165 -97
  16. package/lib/components/droparea/components/droparea-preview.js +58 -8
  17. package/lib/components/droparea/components/droparea-preview.test.js +262 -80
  18. package/lib/components/droparea/components/droparea.js +41 -4
  19. package/lib/components/droparea/components/droparea.test.js +309 -299
  20. package/lib/components/emit/components/emit.js +23 -3
  21. package/lib/components/emit/components/emit.test.js +192 -134
  22. package/lib/components/list/components/item.test.js +69 -68
  23. package/lib/components/list/components/list.js +33 -3
  24. package/lib/components/list/components/list.test.js +358 -227
  25. package/lib/components/paginator/components/paginator.test.js +146 -143
  26. package/lib/components/spinner/components/spinner.test.js +36 -41
  27. package/lib/components/splitview/components/splitview.detail.test.js +75 -73
  28. package/lib/components/splitview/components/splitview.js +36 -8
  29. package/lib/components/splitview/components/splitview.master.js +27 -2
  30. package/lib/components/splitview/components/splitview.master.test.js +52 -52
  31. package/lib/components/splitview/components/splitview.test.js +135 -31
  32. package/lib/components/translate/components/translate.js +28 -8
  33. package/lib/components/translate/components/translate.test.js +492 -133
  34. package/package.json +3 -27
  35. package/scripts/node-test-setup.js +94 -0
@@ -1,52 +1,52 @@
1
+ import { it } from 'node:test';
2
+ import assert from 'node:assert/strict';
1
3
  import { getSlots } from './slots.js'
2
4
 
3
- describe('Slots', () => {
4
- it('can be rendered without content', () => {
5
- const item = document.createElement('div')
6
- const slots = getSlots(item)
7
- expect(!slots.general.length).toBeTruthy()
8
- })
5
+ it('can be rendered without content', () => {
6
+ const item = document.createElement('div')
7
+ const slots = getSlots(item)
8
+ assert.ok(!slots.general.length)
9
+ })
9
10
 
10
- it('can be rendered with content', () => {
11
- const item = document.createElement('div')
11
+ it('can be rendered with content', () => {
12
+ const item = document.createElement('div')
12
13
 
13
- const obj = document.createElement('div')
14
+ const obj = document.createElement('div')
14
15
 
15
- item.appendChild(obj)
16
- const slots = getSlots(item)
17
- expect(slots.general.length).toBeTruthy()
18
- })
16
+ item.appendChild(obj)
17
+ const slots = getSlots(item)
18
+ assert.ok(slots.general.length)
19
+ })
19
20
 
20
- it('can be rendered with value slot', () => {
21
- const item = document.createElement('div')
21
+ it('can be rendered with value slot', () => {
22
+ const item = document.createElement('div')
22
23
 
23
- const obj = document.createElement('div')
24
- const att = document.createAttribute('slot')
25
- att.value = 'mySlot'
26
- obj.setAttributeNode(att)
24
+ const obj = document.createElement('div')
25
+ const att = document.createAttribute('slot')
26
+ att.value = 'mySlot'
27
+ obj.setAttributeNode(att)
27
28
 
28
- item.appendChild(obj)
29
- const slots = getSlots(item)
30
- expect(slots.mySlot.length).toBeTruthy()
31
- })
29
+ item.appendChild(obj)
30
+ const slots = getSlots(item)
31
+ assert.ok(slots.mySlot.length)
32
+ })
32
33
 
33
- it('can be rendered with multiple values slot', () => {
34
- const item = document.createElement('div')
34
+ it('can be rendered with multiple values slot', () => {
35
+ const item = document.createElement('div')
35
36
 
36
- const obj = document.createElement('div')
37
- const att = document.createAttribute('slot')
38
- att.value = 'mySlot'
39
- obj.setAttributeNode(att)
37
+ const obj = document.createElement('div')
38
+ const att = document.createAttribute('slot')
39
+ att.value = 'mySlot'
40
+ obj.setAttributeNode(att)
40
41
 
41
- item.appendChild(obj)
42
+ item.appendChild(obj)
42
43
 
43
- const obj2 = document.createElement('div')
44
- const att2 = document.createAttribute('slot')
45
- att2.value = 'mySlot'
46
- obj2.setAttributeNode(att2)
44
+ const obj2 = document.createElement('div')
45
+ const att2 = document.createAttribute('slot')
46
+ att2.value = 'mySlot'
47
+ obj2.setAttributeNode(att2)
47
48
 
48
- item.appendChild(obj2)
49
- const slots = getSlots(item)
50
- expect(slots.mySlot.length).toBeTruthy()
51
- })
49
+ item.appendChild(obj2)
50
+ const slots = getSlots(item)
51
+ assert.ok(slots.mySlot.length)
52
52
  })
@@ -1,19 +1,19 @@
1
+ import { it } from 'node:test';
2
+ import assert from 'node:assert/strict';
1
3
  import { uuid } from './uuid.js'
2
4
 
3
- describe('Slots', () => {
4
- it('groups separated by dashes', () => {
5
- const id = uuid()
6
- expect(id.split('-').length === 5).toBeTruthy()
7
- })
8
-
9
- it('total digits == 32', () => {
10
- const id = uuid()
5
+ it('groups separated by dashes', () => {
6
+ const id = uuid()
7
+ assert.ok(id.split('-').length === 5)
8
+ })
11
9
 
12
- let digits = ''
13
- id.split('-').forEach(element => {
14
- digits += element
15
- })
10
+ it('total digits == 32', () => {
11
+ const id = uuid()
16
12
 
17
- expect(digits.length === 32).toBeTruthy()
13
+ let digits = ''
14
+ id.split('-').forEach(element => {
15
+ digits += element
18
16
  })
17
+
18
+ assert.ok(digits.length === 32)
19
19
  })
@@ -8,6 +8,7 @@ export class Audio extends Component {
8
8
  this.dataURL = null
9
9
  this.timerId = null
10
10
  this.recorder = null
11
+ this.objectURL = null
11
12
  this.global = context.global || window
12
13
 
13
14
  return super.init()
@@ -70,6 +71,8 @@ export class Audio extends Component {
70
71
  }
71
72
 
72
73
  reset () {
74
+ clearInterval(this.timerId)
75
+ this._revokeObjectURL()
73
76
  this.status = 'idle'
74
77
  this.render()
75
78
  this.dataURL = null
@@ -77,6 +80,13 @@ export class Audio extends Component {
77
80
  this.recorder = null
78
81
  }
79
82
 
83
+ disconnectedCallback () {
84
+ clearInterval(this.timerId)
85
+ this.recorder?.stream?.getTracks?.().forEach(track => track.stop())
86
+ this._revokeObjectURL()
87
+ super.disconnectedCallback()
88
+ }
89
+
80
90
  _time () {
81
91
  let count = 0
82
92
  return setInterval(() => {
@@ -95,10 +105,18 @@ export class Audio extends Component {
95
105
  _onData (event) {
96
106
  const audio = /** @type {HTMLAudioElement} */ (
97
107
  this.querySelector('.ark-audio__audio'))
98
- audio.src = this.global.URL.createObjectURL(event.data)
108
+ this._revokeObjectURL()
109
+ this.objectURL = this.global.URL.createObjectURL(event.data)
110
+ audio.src = this.objectURL
99
111
  const reader = new this.global.FileReader()
100
112
  reader.readAsDataURL(event.data)
101
113
  reader.onloadend = () => { this.dataURL = reader.result }
102
114
  }
115
+
116
+ _revokeObjectURL () {
117
+ if (!this.objectURL) return
118
+ this.global.URL.revokeObjectURL?.(this.objectURL)
119
+ this.objectURL = null
120
+ }
103
121
  }
104
122
  Component.define(tag, Audio, styles)
@@ -1,8 +1,7 @@
1
- import { jest } from '@jest/globals'
1
+ import { it, mock } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
  import './audio.js'
3
4
 
4
- jest.useFakeTimers()
5
-
6
5
  const mockGlobal = {
7
6
  navigator: {
8
7
  mediaDevices: {
@@ -25,104 +24,135 @@ const mockGlobal = {
25
24
  URL: { createObjectURL: (data) => 'mock://data/url' }
26
25
  }
27
26
 
28
- describe('Audio', () => {
29
- let container = null
30
- beforeEach(() => {
31
- container = document.createElement('div')
32
- document.body.appendChild(container)
33
- })
27
+ const mockGlobalWithRevoke = {
28
+ ...mockGlobal,
29
+ URL: {
30
+ createObjectURL: (data) => 'mock://data/url',
31
+ revokeObjectURL: mock.fn()
32
+ }
33
+ }
34
34
 
35
- afterEach(() => {
36
- container.remove()
37
- container = null
38
- })
35
+ let container = null
39
36
 
40
- it('can be instantiated', () => {
41
- container.innerHTML = `
42
- <ark-audio></ark-audio>
43
- `
44
- const audio = container.querySelector('ark-audio')
45
- audio.init()
46
- expect(audio).toBeTruthy()
37
+ const setup = () => {
38
+ document.body.innerHTML = ''
39
+ mock.timers.reset()
40
+ mock.timers.enable({
41
+ apis: ['setInterval', 'setTimeout']
47
42
  })
43
+ container = document.createElement('div')
44
+ document.body.appendChild(container)
45
+ }
48
46
 
49
- it('can start recording', async () => {
50
- container.innerHTML = `
51
- <ark-audio></ark-audio>
52
- `
53
- const audio = container.querySelector('ark-audio')
54
- audio.init({ global: mockGlobal })
55
-
56
- expect(audio.status).toEqual('idle')
57
- await audio.start(new Event('click'))
58
- expect(audio.status).toEqual('recording')
59
- expect(audio.recorder).toBeTruthy()
60
- })
47
+ it('can be instantiated', () => {
48
+ setup()
49
+ container.innerHTML = `
50
+ <ark-audio></ark-audio>
51
+ `
52
+ const audio = container.querySelector('ark-audio')
53
+ audio.init()
54
+ assert.ok(audio)
55
+ })
61
56
 
62
- it('can stop recording', async () => {
63
- container.innerHTML = `
64
- <ark-audio></ark-audio>
65
- `
66
- const audio = container.querySelector('ark-audio')
67
- audio.init({ global: mockGlobal })
68
-
69
- expect(audio.status).toEqual('idle')
70
- await audio.start(new Event('click'))
71
- expect(audio.status).toEqual('recording')
72
- audio.stop(new Event('click'))
73
- expect(audio.status).toEqual('done')
74
- })
57
+ it('can start recording', async () => {
58
+ setup()
59
+ container.innerHTML = `
60
+ <ark-audio></ark-audio>
61
+ `
62
+ const audio = container.querySelector('ark-audio')
63
+ audio.init({ global: mockGlobal })
64
+
65
+ assert.deepStrictEqual(audio.status, 'idle')
66
+ await audio.start(new Event('click'))
67
+ assert.deepStrictEqual(audio.status, 'recording')
68
+ assert.ok(audio.recorder)
69
+ })
75
70
 
76
- it('can reset recording', async () => {
77
- container.innerHTML = `
78
- <ark-audio></ark-audio>
79
- `
80
- const audio = container.querySelector('ark-audio')
81
- audio.init({ global: mockGlobal })
82
-
83
- expect(audio.status).toEqual('idle')
84
- await audio.start(new Event('click'))
85
- expect(audio.status).toEqual('recording')
86
- audio.stop(new Event('click'))
87
- expect(audio.status).toEqual('done')
88
- audio.reset(new Event('click'))
89
- expect(audio.status).toEqual('idle')
90
- expect(audio.recorder).toBeNull()
91
- })
71
+ it('can stop recording', async () => {
72
+ setup()
73
+ container.innerHTML = `
74
+ <ark-audio></ark-audio>
75
+ `
76
+ const audio = container.querySelector('ark-audio')
77
+ audio.init({ global: mockGlobal })
78
+
79
+ assert.deepStrictEqual(audio.status, 'idle')
80
+ await audio.start(new Event('click'))
81
+ assert.deepStrictEqual(audio.status, 'recording')
82
+ audio.stop(new Event('click'))
83
+ assert.deepStrictEqual(audio.status, 'done')
84
+ })
92
85
 
93
- it('counts the ellapsed time of the recording', async () => {
94
- container.innerHTML = `
95
- <ark-audio></ark-audio>
96
- `
97
- const audio = container.querySelector('ark-audio')
98
- audio.init({ global: mockGlobal })
86
+ it('can reset recording', async () => {
87
+ setup()
88
+ container.innerHTML = `
89
+ <ark-audio></ark-audio>
90
+ `
91
+ const audio = container.querySelector('ark-audio')
92
+ audio.init({ global: mockGlobal })
93
+
94
+ assert.deepStrictEqual(audio.status, 'idle')
95
+ await audio.start(new Event('click'))
96
+ assert.deepStrictEqual(audio.status, 'recording')
97
+ audio.stop(new Event('click'))
98
+ assert.deepStrictEqual(audio.status, 'done')
99
+ audio.reset(new Event('click'))
100
+ assert.deepStrictEqual(audio.status, 'idle')
101
+ assert.strictEqual(audio.recorder, null)
102
+ })
99
103
 
100
- await audio.start(new Event('click'))
101
- jest.runOnlyPendingTimers()
104
+ it('counts the ellapsed time of the recording', async () => {
105
+ setup()
106
+ container.innerHTML = `
107
+ <ark-audio></ark-audio>
108
+ `
109
+ const audio = container.querySelector('ark-audio')
110
+ audio.init({ global: mockGlobal })
111
+
112
+ await audio.start(new Event('click'))
113
+ mock.timers.tick(1000)
114
+
115
+ const timer = audio.select('.ark-audio__timer')
116
+ assert.deepStrictEqual(timer.textContent, '00:01')
117
+ mock.timers.tick(623000)
118
+ assert.deepStrictEqual(timer.textContent, '10:24')
119
+ })
102
120
 
103
- const timer = audio.select('.ark-audio__timer')
104
- expect(timer.textContent).toEqual('00:01')
105
- jest.advanceTimersByTime(623000)
106
- expect(timer.textContent).toEqual('10:24')
107
- })
121
+ it('sets the dataURL (base64) property when stopped', async () => {
122
+ setup()
123
+ container.innerHTML = `
124
+ <ark-audio></ark-audio>
125
+ `
126
+ const audio = container.querySelector('ark-audio')
127
+ audio.init({ global: mockGlobal })
108
128
 
109
- it('sets the dataURL (base64) property when stopped', async () => {
110
- container.innerHTML = `
111
- <ark-audio></ark-audio>
112
- `
113
- const audio = container.querySelector('ark-audio')
114
- audio.init({ global: mockGlobal })
129
+ await audio.start(new Event('click'))
130
+ audio.stop(new Event('click'))
115
131
 
116
- await audio.start(new Event('click'))
117
- audio.stop(new Event('click'))
132
+ audio._onData({
133
+ data: new globalThis.Blob(['Hello'], { type: 'text/plain' })
134
+ })
135
+ mock.timers.tick(1000)
118
136
 
119
- audio._onData({
120
- data: new globalThis.Blob(['Hello'], { type: 'text/plain' })
121
- })
122
- jest.runOnlyPendingTimers()
137
+ assert.deepStrictEqual(audio.dataURL, 'base64::data::result')
138
+ assert.deepStrictEqual(audio.querySelector('.ark-audio__audio').src, 'mock://data/url')
139
+ })
123
140
 
124
- expect(audio.dataURL).toEqual('base64::data::result')
125
- expect(audio.querySelector('.ark-audio__audio').src).toEqual(
126
- 'mock://data/url')
127
- })
141
+ it('revokes the previously created object URL', () => {
142
+ setup()
143
+ container.innerHTML = `
144
+ <ark-audio></ark-audio>
145
+ `
146
+ const audio = container.querySelector('ark-audio')
147
+ mockGlobalWithRevoke.URL.revokeObjectURL.mock.resetCalls()
148
+ audio.init({ global: mockGlobalWithRevoke })
149
+ audio.objectURL = 'mock://data/url'
150
+
151
+ audio._revokeObjectURL()
152
+
153
+ assert.deepStrictEqual(
154
+ mockGlobalWithRevoke.URL.revokeObjectURL.mock.calls[0].arguments[0],
155
+ 'mock://data/url'
156
+ )
157
+ assert.strictEqual(audio.objectURL, null)
128
158
  })
@@ -72,6 +72,11 @@ export class Camera extends Component {
72
72
  await this.start()
73
73
  }
74
74
 
75
+ disconnectedCallback () {
76
+ this.stop()
77
+ super.disconnectedCallback()
78
+ }
79
+
75
80
  /** @returns {HTMLVideoElement} */
76
81
  get video () {
77
82
  return this.querySelector('.ark-camera__video')
@@ -1,3 +1,5 @@
1
+ import { it } from 'node:test'
2
+ import assert from 'node:assert/strict'
1
3
  import './camera.js'
2
4
 
3
5
  const mockGlobal = () => ({
@@ -5,100 +7,103 @@ const mockGlobal = () => ({
5
7
  mediaDevices: {
6
8
  __stops: 0,
7
9
  async getUserMedia (_options) {
8
- return { getTracks: () => [{ stop: () => { this.__stops += 1 } }] }
10
+ const stream = {}
11
+ stream.getTracks = () => [{ stop: () => { this.__stops += 1 } }]
12
+ return stream
9
13
  }
10
14
  }
11
15
  }
12
16
  })
13
17
 
14
- describe('Camera', () => {
15
- let container = null
16
- beforeEach(() => {
17
- container = document.createElement('div')
18
- document.body.appendChild(container)
19
- })
20
-
21
- afterEach(() => {
22
- container.remove()
23
- container = null
24
- })
25
-
26
- it('can be instantiated', () => {
27
- container.innerHTML = `
28
- <ark-camera></ark-camera>
29
- `
30
- const camera = container.querySelector('ark-camera')
31
- expect(camera).toBeTruthy()
32
-
33
- expect(camera).toBe(camera.init())
34
- })
35
-
36
- it('sets its dimensions on canplay event', async () => {
37
- container.innerHTML = `
38
- <ark-camera width="50" height="80"></ark-camera>
39
- `
40
- const camera = container.querySelector('ark-camera')
41
- const video = camera.select('video')
42
- const canvas = camera.select('canvas')
43
-
44
- video.dispatchEvent(new Event('canplay'))
45
-
46
- expect(video.width).toEqual(50)
47
- expect(video.height).toEqual(80)
48
-
49
- expect(canvas.width).toEqual(50)
50
- expect(canvas.height).toEqual(80)
51
- })
52
-
53
- it('can start video recording', async () => {
54
- container.innerHTML = `
55
- <ark-camera></ark-camera>
56
- `
57
- const camera = container.querySelector('ark-camera')
58
- camera.init({ global: mockGlobal() })
59
-
60
- await camera.start()
61
-
62
- expect(camera.video.srcObject.getTracks()).toBeTruthy()
63
- })
64
-
65
- it('can stop video recording', async () => {
66
- container.innerHTML = `
67
- <ark-camera></ark-camera>
68
- `
69
- const camera = container.querySelector('ark-camera')
70
- const global = mockGlobal()
71
- camera.init({ global })
72
-
73
- await camera.start()
74
-
75
- camera.stop()
76
-
77
- expect(global.navigator.mediaDevices.__stops).toEqual(1)
78
- })
79
-
80
- it('can set the camera orientation', async () => {
81
- container.innerHTML = `
82
- <ark-camera></ark-camera>
83
- `
84
- const camera = container.querySelector('ark-camera')
85
- const global = mockGlobal()
86
- camera.init({ global })
87
-
88
- await camera.setCameraOrientation('environment')
89
-
90
- expect(camera.facingMode).toEqual('environment')
91
- })
92
-
93
- it('gets the dataURL (base64) of its containing canvas', async () => {
94
- container.innerHTML = `
95
- <ark-camera></ark-camera>
96
- `
97
- const camera = container.querySelector('ark-camera')
98
- camera.init({ global: mockGlobal() })
99
-
100
- const data = camera.dataURL()
101
-
102
- expect(data).toBeTruthy()
103
- })
18
+ let container = null
19
+
20
+ const setup = () => {
21
+ document.body.innerHTML = ''
22
+ container = document.createElement('div')
23
+ document.body.appendChild(container)
24
+ }
25
+
26
+ it('can be instantiated', () => {
27
+ setup()
28
+ container.innerHTML = `
29
+ <ark-camera></ark-camera>
30
+ `
31
+ const camera = container.querySelector('ark-camera')
32
+ assert.ok(camera)
33
+
34
+ assert.strictEqual(camera, camera.init())
35
+ })
36
+
37
+ it('sets its dimensions on canplay event', async () => {
38
+ setup()
39
+ container.innerHTML = `
40
+ <ark-camera width="50" height="80"></ark-camera>
41
+ `
42
+ const camera = container.querySelector('ark-camera')
43
+ const video = camera.select('video')
44
+ const canvas = camera.select('canvas')
45
+
46
+ video.dispatchEvent(new Event('canplay'))
47
+
48
+ assert.deepStrictEqual(video.getAttribute('width'), '50px')
49
+ assert.deepStrictEqual(video.getAttribute('height'), '80px')
50
+
51
+ assert.deepStrictEqual(canvas.getAttribute('width'), '50px')
52
+ assert.deepStrictEqual(canvas.getAttribute('height'), '80px')
53
+ })
54
+
55
+ it('can start video recording', async () => {
56
+ setup()
57
+ container.innerHTML = `
58
+ <ark-camera></ark-camera>
59
+ `
60
+ const camera = container.querySelector('ark-camera')
61
+ camera.init({ global: mockGlobal() })
62
+
63
+ await camera.start()
64
+
65
+ assert.ok(camera.video.srcObject.getTracks())
66
+ })
67
+
68
+ it('can stop video recording', async () => {
69
+ setup()
70
+ container.innerHTML = `
71
+ <ark-camera></ark-camera>
72
+ `
73
+ const camera = container.querySelector('ark-camera')
74
+ const global = mockGlobal()
75
+ camera.init({ global })
76
+
77
+ await camera.start()
78
+
79
+ camera.stop()
80
+
81
+ assert.deepStrictEqual(global.navigator.mediaDevices.__stops, 1)
82
+ })
83
+
84
+ it('can set the camera orientation', async () => {
85
+ setup()
86
+ container.innerHTML = `
87
+ <ark-camera></ark-camera>
88
+ `
89
+ const camera = container.querySelector('ark-camera')
90
+ const global = mockGlobal()
91
+ camera.init({ global })
92
+
93
+ await camera.setCameraOrientation('environment')
94
+
95
+ assert.deepStrictEqual(camera.facingMode, 'environment')
96
+ })
97
+
98
+ it('gets the dataURL (base64) of its containing canvas', async () => {
99
+ setup()
100
+ container.innerHTML = `
101
+ <ark-camera></ark-camera>
102
+ `
103
+ const camera = container.querySelector('ark-camera')
104
+ camera.init({ global: mockGlobal() })
105
+
106
+ const data = camera.dataURL()
107
+
108
+ assert.ok(data)
104
109
  })