@fmidev/smartmet-alert-client 4.4.19 → 4.7.0-alpha.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 (105) hide show
  1. package/.eslintignore +2 -14
  2. package/.github/workflows/test.yaml +26 -0
  3. package/.nvmrc +1 -0
  4. package/dist/index.html +5 -0
  5. package/dist/index.js +105 -135
  6. package/dist/index.mjs +112 -135
  7. package/dist/locale-en-DCEKDw5G.js +8 -0
  8. package/dist/locale-fi-DPiOM1rB.js +8 -0
  9. package/dist/locale-sv-B0FlbgEF.js +8 -0
  10. package/dist/vendor-Cfkkvdz7.js +21 -0
  11. package/dist/vue/index.mjs +15245 -0
  12. package/dist/vue/style.css +1 -0
  13. package/dist/xml-parser-BiNO9kc-.js +13 -0
  14. package/package.json +60 -24
  15. package/src/AlertClientVue.vue +170 -0
  16. package/src/App.vue +55 -205
  17. package/src/assets/img/ui/arrow-down.svg +4 -11
  18. package/src/assets/img/ui/arrow-up.svg +4 -11
  19. package/src/assets/img/ui/clear.svg +7 -21
  20. package/src/assets/img/ui/close.svg +4 -15
  21. package/src/assets/img/ui/toggle-selected.svg +5 -6
  22. package/src/assets/img/ui/toggle-unselected.svg +5 -6
  23. package/src/assets/img/warning/cold-weather.svg +3 -6
  24. package/src/assets/img/warning/flood-level-3.svg +4 -7
  25. package/src/assets/img/warning/forest-fire-weather.svg +2 -6
  26. package/src/assets/img/warning/grass-fire-weather.svg +2 -6
  27. package/src/assets/img/warning/hot-weather.svg +3 -6
  28. package/src/assets/img/warning/pedestrian-safety.svg +3 -7
  29. package/src/assets/img/warning/rain.svg +2 -7
  30. package/src/assets/img/warning/sea-icing.svg +2 -6
  31. package/src/assets/img/warning/sea-thunder-storm.svg +2 -5
  32. package/src/assets/img/warning/sea-water-height-high-water.svg +3 -8
  33. package/src/assets/img/warning/sea-water-height-shallow-water.svg +3 -7
  34. package/src/assets/img/warning/sea-wave-height.svg +4 -7
  35. package/src/assets/img/warning/sea-wind-legend.svg +2 -5
  36. package/src/assets/img/warning/sea-wind.svg +2 -5
  37. package/src/assets/img/warning/several.svg +2 -5
  38. package/src/assets/img/warning/thunder-storm.svg +2 -5
  39. package/src/assets/img/warning/traffic-weather.svg +2 -6
  40. package/src/assets/img/warning/uv-note.svg +2 -6
  41. package/src/assets/img/warning/wind.svg +2 -5
  42. package/src/components/AlertClient.vue +41 -19
  43. package/src/components/CollapsiblePanel.vue +284 -0
  44. package/src/components/DayLarge.vue +12 -7
  45. package/src/components/DaySmall.vue +16 -6
  46. package/src/components/Days.vue +76 -51
  47. package/src/components/DescriptionWarning.vue +15 -8
  48. package/src/components/GrayScaleToggle.vue +11 -6
  49. package/src/components/Legend.vue +36 -248
  50. package/src/components/MapLarge.vue +41 -42
  51. package/src/components/MapSmall.vue +44 -28
  52. package/src/components/PopupRow.vue +6 -3
  53. package/src/components/Region.vue +30 -15
  54. package/src/components/RegionWarning.vue +6 -5
  55. package/src/components/Regions.vue +50 -19
  56. package/src/components/Warning.vue +18 -10
  57. package/src/components/Warnings.vue +36 -21
  58. package/src/main.js +1 -0
  59. package/src/mixins/alertClientCore.js +210 -0
  60. package/src/mixins/config.js +262 -256
  61. package/src/mixins/utils.js +40 -26
  62. package/src/plugins/index.js +1 -1
  63. package/src/scss/_utilities.scss +193 -0
  64. package/src/scss/constants.scss +2 -1
  65. package/src/scss/warningImages.scss +8 -3
  66. package/src/vue.js +41 -0
  67. package/svgo.config.js +45 -0
  68. package/tests/README.md +430 -0
  69. package/tests/fixtures/mockWarningData.js +135 -0
  70. package/tests/integration/warning-flow.spec.js +452 -0
  71. package/tests/setup.js +41 -0
  72. package/tests/unit/components/AlertClient.spec.js +734 -0
  73. package/tests/unit/components/DayLarge.spec.js +281 -0
  74. package/tests/unit/components/DaySmall.spec.js +278 -0
  75. package/tests/unit/components/Days.spec.js +565 -0
  76. package/tests/unit/components/DescriptionWarning.spec.js +432 -0
  77. package/tests/unit/components/GrayScaleToggle.spec.js +311 -0
  78. package/tests/unit/components/Legend.spec.js +223 -0
  79. package/tests/unit/components/MapLarge.spec.js +276 -0
  80. package/tests/unit/components/MapSmall.spec.js +226 -0
  81. package/tests/unit/components/PopupRow.spec.js +261 -0
  82. package/tests/unit/components/Region.spec.js +430 -0
  83. package/tests/unit/components/RegionWarning.snapshot.spec.js +73 -0
  84. package/tests/unit/components/RegionWarning.spec.js +408 -0
  85. package/tests/unit/components/Regions.spec.js +335 -0
  86. package/tests/unit/components/Warning.snapshot.spec.js +107 -0
  87. package/tests/unit/components/Warning.spec.js +472 -0
  88. package/tests/unit/components/Warnings.spec.js +329 -0
  89. package/tests/unit/components/__snapshots__/RegionWarning.snapshot.spec.js.snap +21 -0
  90. package/tests/unit/components/__snapshots__/Warning.snapshot.spec.js.snap +199 -0
  91. package/tests/unit/mixins/config.spec.js +269 -0
  92. package/tests/unit/mixins/i18n.spec.js +115 -0
  93. package/tests/unit/mixins/keycodes.spec.js +37 -0
  94. package/tests/unit/mixins/utils.spec.js +624 -0
  95. package/vite.config.js +96 -26
  96. package/vitest.config.js +40 -0
  97. package/dist/index.mjs.map +0 -1
  98. package/dist/index.relative.html +0 -19
  99. package/dist/index.start.html +0 -20
  100. package/playwright.config.ts +0 -18
  101. package/public/index.relative.html +0 -19
  102. package/public/index.start.html +0 -20
  103. package/src/mixins/panzoom.js +0 -900
  104. package/test/snapshot.test.ts +0 -126
  105. package/vitest.config.ts +0 -6
@@ -0,0 +1,335 @@
1
+ import { describe, it, expect, afterEach } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import Regions from '@/components/Regions.vue'
4
+
5
+ const mockRegionsInput = [
6
+ {
7
+ land: [
8
+ {
9
+ key: 'county.1',
10
+ regionIndex: 0,
11
+ name: 'Uusimaa',
12
+ warnings: [
13
+ {
14
+ type: 'wind',
15
+ identifiers: ['warning-1'],
16
+ coverage: 100,
17
+ },
18
+ ],
19
+ },
20
+ {
21
+ key: 'county.2',
22
+ regionIndex: 1,
23
+ name: 'Varsinais-Suomi',
24
+ warnings: [
25
+ {
26
+ type: 'rain',
27
+ identifiers: ['warning-2'],
28
+ coverage: 75,
29
+ },
30
+ ],
31
+ },
32
+ ],
33
+ sea: [
34
+ {
35
+ key: 'sea_region.B1N',
36
+ regionIndex: 10,
37
+ name: 'Perämeri',
38
+ warnings: [
39
+ {
40
+ type: 'seaWind',
41
+ identifiers: ['warning-3'],
42
+ coverage: 100,
43
+ },
44
+ ],
45
+ },
46
+ ],
47
+ },
48
+ ]
49
+
50
+ const mockWarnings = {
51
+ 'warning-1': {
52
+ id: 'warning-1',
53
+ type: 'wind',
54
+ severity: 3,
55
+ },
56
+ 'warning-2': {
57
+ id: 'warning-2',
58
+ type: 'rain',
59
+ severity: 2,
60
+ },
61
+ 'warning-3': {
62
+ id: 'warning-3',
63
+ type: 'seaWind',
64
+ severity: 4,
65
+ },
66
+ }
67
+
68
+ describe('Regions.vue', () => {
69
+ let wrapper
70
+
71
+ const mountComponent = (props) => {
72
+ return mount(Regions, {
73
+ props,
74
+ global: {
75
+ stubs: {
76
+ Region: true,
77
+ },
78
+ },
79
+ })
80
+ }
81
+
82
+ afterEach(() => {
83
+ if (wrapper) {
84
+ wrapper.unmount()
85
+ }
86
+ })
87
+
88
+ describe('Component mounting', () => {
89
+ it('should mount with required props', () => {
90
+ wrapper = mountComponent({
91
+ input: mockRegionsInput,
92
+ selectedDay: 0,
93
+ warnings: mockWarnings,
94
+ parents: {},
95
+ geometryId: 2021,
96
+ theme: 'light-theme',
97
+ language: 'fi',
98
+ })
99
+
100
+ expect(wrapper.exists()).toBe(true)
101
+ })
102
+ })
103
+
104
+ describe('Computed properties', () => {
105
+ it('should compute landText', () => {
106
+ wrapper = mountComponent({
107
+ input: mockRegionsInput,
108
+ selectedDay: 0,
109
+ warnings: mockWarnings,
110
+ parents: {},
111
+ geometryId: 2021,
112
+ theme: 'light-theme',
113
+ language: 'fi',
114
+ })
115
+
116
+ expect(typeof wrapper.vm.landText).toBe('string')
117
+ })
118
+
119
+ it('should compute seaText', () => {
120
+ wrapper = mountComponent({
121
+ input: mockRegionsInput,
122
+ selectedDay: 0,
123
+ warnings: mockWarnings,
124
+ parents: {},
125
+ geometryId: 2021,
126
+ theme: 'light-theme',
127
+ language: 'fi',
128
+ })
129
+
130
+ expect(typeof wrapper.vm.seaText).toBe('string')
131
+ })
132
+
133
+ it('should filter regions with coverage criterion', () => {
134
+ wrapper = mountComponent({
135
+ input: mockRegionsInput,
136
+ selectedDay: 0,
137
+ warnings: mockWarnings,
138
+ parents: {},
139
+ geometryId: 2021,
140
+ theme: 'light-theme',
141
+ language: 'fi',
142
+ })
143
+
144
+ const regions = wrapper.vm.regions
145
+ expect(regions).toHaveProperty('land')
146
+ expect(regions).toHaveProperty('sea')
147
+ expect(Array.isArray(regions.land)).toBe(true)
148
+ expect(Array.isArray(regions.sea)).toBe(true)
149
+ })
150
+
151
+ it('should detect land warnings', () => {
152
+ wrapper = mountComponent({
153
+ input: mockRegionsInput,
154
+ selectedDay: 0,
155
+ warnings: mockWarnings,
156
+ parents: {},
157
+ geometryId: 2021,
158
+ theme: 'light-theme',
159
+ language: 'fi',
160
+ })
161
+
162
+ expect(wrapper.vm.anyLandWarnings).toBe(true)
163
+ })
164
+
165
+ it('should detect sea warnings', () => {
166
+ wrapper = mountComponent({
167
+ input: mockRegionsInput,
168
+ selectedDay: 0,
169
+ warnings: mockWarnings,
170
+ parents: {},
171
+ geometryId: 2021,
172
+ theme: 'light-theme',
173
+ language: 'fi',
174
+ })
175
+
176
+ expect(wrapper.vm.anySeaWarnings).toBe(true)
177
+ })
178
+
179
+ it('should return false for no land warnings', () => {
180
+ const noLandInput = [
181
+ {
182
+ land: [],
183
+ sea: [],
184
+ },
185
+ ]
186
+
187
+ wrapper = mountComponent({
188
+ input: noLandInput,
189
+ selectedDay: 0,
190
+ warnings: mockWarnings,
191
+ parents: {},
192
+ geometryId: 2021,
193
+ theme: 'light-theme',
194
+ language: 'fi',
195
+ })
196
+
197
+ expect(wrapper.vm.anyLandWarnings).toBe(false)
198
+ })
199
+
200
+ it('should compute fromLandToNextContentHref correctly with sea warnings', () => {
201
+ wrapper = mountComponent({
202
+ input: mockRegionsInput,
203
+ selectedDay: 0,
204
+ warnings: mockWarnings,
205
+ parents: {},
206
+ geometryId: 2021,
207
+ theme: 'light-theme',
208
+ language: 'fi',
209
+ })
210
+
211
+ expect(wrapper.vm.fromLandToNextContentHref).toBe(
212
+ '#fmi-warnings-from-sea-to-next-content'
213
+ )
214
+ })
215
+
216
+ it('should compute fromLandToNextContentHref correctly without sea warnings', () => {
217
+ const noSeaInput = [
218
+ {
219
+ land: mockRegionsInput[0].land,
220
+ sea: [],
221
+ },
222
+ ]
223
+
224
+ wrapper = mountComponent({
225
+ input: noSeaInput,
226
+ selectedDay: 0,
227
+ warnings: mockWarnings,
228
+ parents: {},
229
+ geometryId: 2021,
230
+ theme: 'light-theme',
231
+ language: 'fi',
232
+ })
233
+
234
+ expect(wrapper.vm.fromLandToNextContentHref).toBe(
235
+ '#fmi-warnings-end-of-regions'
236
+ )
237
+ })
238
+ })
239
+
240
+ describe('Content rendering', () => {
241
+ it('should render land region header when land warnings exist', () => {
242
+ wrapper = mountComponent({
243
+ input: mockRegionsInput,
244
+ selectedDay: 0,
245
+ warnings: mockWarnings,
246
+ parents: {},
247
+ geometryId: 2021,
248
+ theme: 'light-theme',
249
+ language: 'fi',
250
+ })
251
+
252
+ expect(wrapper.find('#header-land').exists()).toBe(true)
253
+ })
254
+
255
+ it('should render sea region header when sea warnings exist', () => {
256
+ wrapper = mountComponent({
257
+ input: mockRegionsInput,
258
+ selectedDay: 0,
259
+ warnings: mockWarnings,
260
+ parents: {},
261
+ geometryId: 2021,
262
+ theme: 'light-theme',
263
+ language: 'fi',
264
+ })
265
+
266
+ expect(wrapper.find('#header-sea').exists()).toBe(true)
267
+ })
268
+
269
+ it('should not render land header when no land warnings', () => {
270
+ const noLandInput = [
271
+ {
272
+ land: [],
273
+ sea: [],
274
+ },
275
+ ]
276
+
277
+ wrapper = mountComponent({
278
+ input: noLandInput,
279
+ selectedDay: 0,
280
+ warnings: mockWarnings,
281
+ parents: {},
282
+ geometryId: 2021,
283
+ theme: 'light-theme',
284
+ language: 'fi',
285
+ })
286
+
287
+ expect(wrapper.find('#header-land').exists()).toBe(false)
288
+ })
289
+
290
+ it('should render Region components', () => {
291
+ wrapper = mountComponent({
292
+ input: mockRegionsInput,
293
+ selectedDay: 0,
294
+ warnings: mockWarnings,
295
+ parents: {},
296
+ geometryId: 2021,
297
+ theme: 'light-theme',
298
+ language: 'fi',
299
+ })
300
+
301
+ const regionComponents = wrapper.findAllComponents({ name: 'Region' })
302
+ expect(regionComponents.length).toBeGreaterThan(0)
303
+ })
304
+ })
305
+
306
+ describe('Navigation methods', () => {
307
+ it('should have fromLandToNextContentClicked method', () => {
308
+ wrapper = mountComponent({
309
+ input: mockRegionsInput,
310
+ selectedDay: 0,
311
+ warnings: mockWarnings,
312
+ parents: {},
313
+ geometryId: 2021,
314
+ theme: 'light-theme',
315
+ language: 'fi',
316
+ })
317
+
318
+ expect(typeof wrapper.vm.fromLandToNextContentClicked).toBe('function')
319
+ })
320
+
321
+ it('should have fromSeaToNextContentClicked method', () => {
322
+ wrapper = mountComponent({
323
+ input: mockRegionsInput,
324
+ selectedDay: 0,
325
+ warnings: mockWarnings,
326
+ parents: {},
327
+ geometryId: 2021,
328
+ theme: 'light-theme',
329
+ language: 'fi',
330
+ })
331
+
332
+ expect(typeof wrapper.vm.fromSeaToNextContentClicked).toBe('function')
333
+ })
334
+ })
335
+ })
@@ -0,0 +1,107 @@
1
+ import { describe, it, expect, afterEach } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import Warning from '@/components/Warning.vue'
4
+
5
+ const mockWarning = {
6
+ type: 'wind',
7
+ severity: 3,
8
+ visible: true,
9
+ }
10
+
11
+ describe('Warning.vue snapshots', () => {
12
+ let wrapper
13
+
14
+ afterEach(() => {
15
+ if (wrapper) {
16
+ wrapper.unmount()
17
+ }
18
+ })
19
+
20
+ it('should match snapshot for default state', () => {
21
+ wrapper = mount(Warning, {
22
+ props: {
23
+ input: mockWarning,
24
+ hideable: true,
25
+ language: 'fi',
26
+ theme: 'light-theme',
27
+ },
28
+ })
29
+
30
+ expect(wrapper.html()).toMatchSnapshot()
31
+ })
32
+
33
+ it('should match snapshot for hidden warning', () => {
34
+ wrapper = mount(Warning, {
35
+ props: {
36
+ input: { ...mockWarning, visible: false },
37
+ hideable: true,
38
+ language: 'fi',
39
+ theme: 'light-theme',
40
+ },
41
+ })
42
+
43
+ expect(wrapper.html()).toMatchSnapshot()
44
+ })
45
+
46
+ it('should match snapshot for different severity levels', () => {
47
+ const severities = [1, 2, 3, 4]
48
+
49
+ severities.forEach((severity) => {
50
+ wrapper = mount(Warning, {
51
+ props: {
52
+ input: { ...mockWarning, severity },
53
+ hideable: true,
54
+ language: 'fi',
55
+ theme: 'light-theme',
56
+ },
57
+ })
58
+
59
+ expect(wrapper.html()).toMatchSnapshot(`severity-${severity}`)
60
+ wrapper.unmount()
61
+ })
62
+ })
63
+
64
+ it('should match snapshot for dark theme', () => {
65
+ wrapper = mount(Warning, {
66
+ props: {
67
+ input: mockWarning,
68
+ hideable: true,
69
+ language: 'fi',
70
+ theme: 'dark-theme',
71
+ },
72
+ })
73
+
74
+ expect(wrapper.html()).toMatchSnapshot()
75
+ })
76
+
77
+ it('should match snapshot for different languages', () => {
78
+ const languages = ['fi', 'sv', 'en']
79
+
80
+ languages.forEach((language) => {
81
+ wrapper = mount(Warning, {
82
+ props: {
83
+ input: mockWarning,
84
+ hideable: true,
85
+ language,
86
+ theme: 'light-theme',
87
+ },
88
+ })
89
+
90
+ expect(wrapper.html()).toMatchSnapshot(`language-${language}`)
91
+ wrapper.unmount()
92
+ })
93
+ })
94
+
95
+ it('should match snapshot when not hideable', () => {
96
+ wrapper = mount(Warning, {
97
+ props: {
98
+ input: mockWarning,
99
+ hideable: false,
100
+ language: 'fi',
101
+ theme: 'light-theme',
102
+ },
103
+ })
104
+
105
+ expect(wrapper.html()).toMatchSnapshot()
106
+ })
107
+ })