TargetSetSelector.spec.js (14476B)
1 import { test, expect, vi } from 'vitest'; 2 import { shallowMount } from '@vue/test-utils'; 3 import TargetSetSelector from '@/components/TargetSetSelector.vue'; 4 5 test('should correctly render target sets options', async () => { 6 // Initialize component 7 const wrapper = shallowMount(TargetSetSelector, { 8 propsData: { 9 selectedTargetSet: 'B', 10 targetSets: { 11 'A': { 12 name: '1st target set', 13 targets: [ 14 { type: 'distance', distanceValue: 1, distanceUnit: 'miles' }, 15 { type: 'distance', distanceValue: 2, distanceUnit: 'miles' }, 16 { type: 'distance', distanceValue: 3, distanceUnit: 'miles' }, 17 ], 18 }, 19 'B': { 20 name: '2nd target set', 21 targets: [ 22 { type: 'distance', distanceValue: 1, distanceUnit: 'kilometers' }, 23 { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, 24 { type: 'distance', distanceValue: 10, distanceUnit: 'kilometers' }, 25 ], 26 }, 27 }, 28 } 29 }); 30 31 // Assert select element populated with target sets 32 const options = wrapper.findAll('option'); 33 expect(options[0].element.text).to.equal('1st target set'); 34 expect(options[0].element.value).to.equal('A'); 35 expect(options[1].element.text).to.equal('2nd target set'); 36 expect(options[1].element.value).to.equal('B'); 37 expect(options[2].element.text).to.equal('[ Create New Target Set ]'); 38 expect(options[2].element.value).to.equal('_new'); 39 expect(options.length).to.equal(3); 40 41 // Assert correct target set is selected 42 expect(wrapper.find('select').element.value).to.equal('B'); 43 }); 44 45 test('Create New Target Set option should correctly add target set', async () => { 46 // Initialize component 47 let targetSets = { 48 'A': { 49 name: '1st target set', 50 targets: [ 51 { type: 'distance', distanceValue: 1, distanceUnit: 'miles' }, 52 { type: 'distance', distanceValue: 2, distanceUnit: 'miles' }, 53 { type: 'distance', distanceValue: 3, distanceUnit: 'miles' }, 54 ], 55 }, 56 'B': { 57 name: '2nd target set', 58 targets: [ 59 { type: 'distance', distanceValue: 1, distanceUnit: 'kilometers' }, 60 { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, 61 { type: 'distance', distanceValue: 10, distanceUnit: 'kilometers' }, 62 ], 63 }, 64 }; 65 const wrapper = shallowMount(TargetSetSelector, { 66 propsData: { 67 selectedTargetSet: '_new', 68 targetSets, 69 } 70 }); 71 await wrapper.vm.$nextTick(); 72 73 // Assert new target set selected (key is unix timestamp in milliseconds) 74 const key1 = wrapper.find('select').element.value; 75 expect(parseInt(key1)).to.be.closeTo(parseInt(Date.now().toString()), 1000); 76 77 // Assert target set options were correctly updated 78 let options = wrapper.findAll('option'); 79 expect(options[0].element.text).to.equal('1st target set'); 80 expect(options[0].element.value).to.equal('A'); 81 expect(options[1].element.text).to.equal('2nd target set'); 82 expect(options[1].element.value).to.equal('B'); 83 expect(options[2].element.text).to.equal('New target set'); 84 expect(options[2].element.value).to.equal(key1) 85 expect(options[3].element.text).to.equal('[ Create New Target Set ]'); 86 expect(options[3].element.value).to.equal('_new'); 87 expect(options.length).to.equal(4); 88 89 // Assert update event emitted with correct target sets 90 expect(wrapper.emitted()['update:targetSets']).to.deep.equal([ 91 [{ 92 [key1]: { 93 name: 'New target set', 94 targets: [], 95 }, 96 ...targetSets, 97 }], 98 ]); 99 100 // Add another target set 101 await wrapper.find('select').setValue('_new'); 102 103 // Assert new target set selected (key is unix timestamp in milliseconds) 104 const key2 = wrapper.find('select').element.value; 105 expect(parseInt(key2)).to.be.closeTo(parseInt(Date.now().toString()), 1000); 106 expect(key2).to.not.equal(key1); 107 108 // Assert target set options were correctly updated 109 options = wrapper.findAll('option'); 110 expect(options[0].element.text).to.equal('1st target set'); 111 expect(options[0].element.value).to.equal('A'); 112 expect(options[1].element.text).to.equal('2nd target set'); 113 expect(options[1].element.value).to.equal('B'); 114 expect(options[2].element.text).to.equal('New target set'); 115 expect(options[2].element.value).to.equal(key1) 116 expect(options[3].element.text).to.equal('New target set'); 117 expect(options[3].element.value).to.equal(key2); 118 expect(options[4].element.text).to.equal('[ Create New Target Set ]'); 119 expect(options[4].element.value).to.equal('_new'); 120 expect(options.length).to.equal(5); 121 122 // Assert update event emitted with correct target sets 123 expect(wrapper.emitted()['update:targetSets']).to.deep.equal([ 124 [{ 125 [key1]: { 126 name: 'New target set', 127 targets: [], 128 }, 129 ...targetSets, 130 }], 131 [{ 132 [key1]: { 133 name: 'New target set', 134 targets: [], 135 }, 136 ...targetSets, 137 [key2]: { 138 name: 'New target set', 139 targets: [], 140 }, 141 }], 142 ]); 143 }); 144 145 test('Revert event should correctly reset a default target set', async () => { 146 // Initialize component 147 let targetSets = { 148 '_split_targets': { 149 name: '1st target set', 150 targets: [ 151 { type: 'distance', distanceValue: 1, distanceUnit: 'miles' }, 152 { type: 'distance', distanceValue: 2, distanceUnit: 'miles' }, 153 { type: 'distance', distanceValue: 3, distanceUnit: 'miles' }, 154 ], 155 }, 156 '1234567890123': { 157 name: '2nd target set', 158 targets: [ 159 { type: 'distance', distanceValue: 1, distanceUnit: 'kilometers' }, 160 { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, 161 { type: 'distance', distanceValue: 10, distanceUnit: 'kilometers' }, 162 ], 163 }, 164 }; 165 const wrapper = shallowMount(TargetSetSelector, { 166 propsData: { 167 selectedTargetSet: '_split_targets', 168 targetSets, 169 } 170 }); 171 172 // Add target set 173 await wrapper.findComponent({ name: 'target-editor' }).trigger('revert'); 174 175 // Assert target set options were correctly updated 176 const options = wrapper.findAll('option'); 177 expect(options[0].element.text).to.equal('5K Mile Splits'); 178 expect(options[0].element.value).to.equal('_split_targets'); 179 expect(options[1].element.text).to.equal('2nd target set'); 180 expect(options[1].element.value).to.equal('1234567890123'); 181 expect(options[2].element.text).to.equal('[ Create New Target Set ]'); 182 expect(options[2].element.value).to.equal('_new'); 183 expect(options.length).to.equal(3); 184 185 // Assert update event emitted with correct target sets 186 expect(wrapper.emitted()['update:targetSets']).to.deep.equal([ 187 [{ 188 '_split_targets': { 189 name: '5K Mile Splits', 190 targets: [ 191 { type: 'distance', distanceValue: 1, distanceUnit: 'miles' }, 192 { type: 'distance', distanceValue: 2, distanceUnit: 'miles' }, 193 { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, 194 ], 195 }, 196 '1234567890123': { 197 name: '2nd target set', 198 targets: [ 199 { type: 'distance', distanceValue: 1, distanceUnit: 'kilometers' }, 200 { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, 201 { type: 'distance', distanceValue: 10, distanceUnit: 'kilometers' }, 202 ], 203 }, 204 }], 205 ]); 206 }); 207 208 test('Revert event should correctly delete a custom target set', async () => { 209 // Initialize component 210 let targetSets = { 211 '_split_targets': { 212 name: '1st target set', 213 targets: [ 214 { type: 'distance', distanceValue: 1, distanceUnit: 'miles' }, 215 { type: 'distance', distanceValue: 2, distanceUnit: 'miles' }, 216 { type: 'distance', distanceValue: 3, distanceUnit: 'miles' }, 217 ], 218 }, 219 '1234567890123': { 220 name: '2nd target set', 221 targets: [ 222 { type: 'distance', distanceValue: 1, distanceUnit: 'kilometers' }, 223 { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, 224 { type: 'distance', distanceValue: 10, distanceUnit: 'kilometers' }, 225 ], 226 }, 227 }; 228 const wrapper = shallowMount(TargetSetSelector, { 229 propsData: { 230 selectedTargetSet: '1234567890123', 231 targetSets, 232 } 233 }); 234 235 // Add target set 236 await wrapper.findComponent({ name: 'target-editor' }).trigger('revert'); 237 238 // Assert target set options were correctly updated 239 const options = wrapper.findAll('option'); 240 expect(options[0].element.text).to.equal('1st target set'); 241 expect(options[0].element.value).to.equal('_split_targets'); 242 expect(options[1].element.text).to.equal('[ Create New Target Set ]'); 243 expect(options[1].element.value).to.equal('_new'); 244 expect(options.length).to.equal(2); 245 246 // Assert update event emitted with correct target sets 247 expect(wrapper.emitted()['update:targetSets']).to.deep.equal([ 248 [{ 249 '_split_targets': { 250 name: '1st target set', 251 targets: [ 252 { type: 'distance', distanceValue: 1, distanceUnit: 'miles' }, 253 { type: 'distance', distanceValue: 2, distanceUnit: 'miles' }, 254 { type: 'distance', distanceValue: 3, distanceUnit: 'miles' }, 255 ], 256 }, 257 }], 258 ]); 259 }); 260 261 test('edit button should open target editor with the correct props for default set', async () => { 262 // Initialize component 263 const targetSets = { 264 '_split_targets': { 265 name: '5K Mile Splits', 266 targets: [ 267 { type: 'distance', distanceValue: 1, distanceUnit: 'miles' }, 268 { type: 'distance', distanceValue: 2, distanceUnit: 'miles' }, 269 { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, 270 ], 271 }, 272 }; 273 const wrapper = shallowMount(TargetSetSelector, { 274 propsData: { 275 selectedTargetSet: '_split_targets', 276 targetSets, 277 defaultUnitSystem: 'fake-unit-system', 278 } 279 }); 280 281 // Mock showModal function 282 wrapper.vm.dialogElement.showModal = vi.fn(); 283 284 // Click edit button 285 await wrapper.find('button').trigger('click'); 286 287 // Assert target editor props are correct 288 const targetEditor = wrapper.findComponent({ name: 'target-editor' }); 289 expect(targetEditor.vm.modelValue).to.deep.equal(targetSets._split_targets); 290 expect(targetEditor.vm.isCustomSet).to.equal(false); 291 expect(targetEditor.vm.defaultUnitSystem).to.equal('fake-unit-system'); 292 }); 293 294 test('edit button should open target editor with the correct props for custom set', async () => { 295 // Initialize component 296 const targetSets = { 297 '1234567890123': { 298 name: '2nd target set', 299 targets: [ 300 { type: 'distance', distanceValue: 1, distanceUnit: 'kilometers' }, 301 { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, 302 { type: 'distance', distanceValue: 10, distanceUnit: 'kilometers' }, 303 ], 304 }, 305 }; 306 const wrapper = shallowMount(TargetSetSelector, { 307 propsData: { 308 selectedTargetSet: '1234567890123', 309 targetSets, 310 defaultUnitSystem: 'fake-unit-system', 311 } 312 }); 313 314 // Mock showModal function 315 wrapper.vm.dialogElement.showModal = vi.fn(); 316 317 // Click edit button 318 await wrapper.find('button').trigger('click'); 319 320 // Assert target editor props are correct 321 const targetEditor = wrapper.findComponent({ name: 'target-editor' }); 322 expect(targetEditor.vm.modelValue).to.deep.equal(targetSets['1234567890123']); 323 expect(targetEditor.vm.isCustomSet).to.equal(true); 324 expect(targetEditor.vm.defaultUnitSystem).to.equal('fake-unit-system'); 325 }); 326 327 test('should sort target set after target editor is closed', async () => { 328 // Initialize component 329 let targetSets = { 330 '_split_targets': { 331 name: '5K Mile Splits', 332 targets: [], 333 }, 334 }; 335 const wrapper = shallowMount(TargetSetSelector, { 336 propsData: { 337 selectedTargetSet: '_split_targets', 338 targetSets, 339 } 340 }); 341 342 // Mock modal close function 343 wrapper.vm.dialogElement.close = vi.fn(); 344 345 // Update targets and trigger close event 346 await wrapper.findComponent({ name: 'target-editor' }).setValue({ 347 name: '5K Mile Splits', 348 targets: [ 349 { type: 'time', timeValue: 60 }, 350 { type: 'distance', distanceValue: 1, distanceUnit: 'miles' }, 351 { type: 'distance', distanceValue: 2, distanceUnit: 'miles' }, 352 { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, 353 { type: 'distance', distanceValue: 3, distanceUnit: 'miles' }, 354 ], 355 }); 356 await wrapper.findComponent({ name: 'target-editor' }).vm.$emit('close'); 357 358 // Assert update events were emitted correctly 359 expect(wrapper.emitted()['update:targetSets']).to.deep.equal([ 360 [{ 361 _split_targets: { 362 name: '5K Mile Splits', 363 targets: [ 364 { type: 'time', timeValue: 60 }, 365 { type: 'distance', distanceValue: 1, distanceUnit: 'miles' }, 366 { type: 'distance', distanceValue: 2, distanceUnit: 'miles' }, 367 { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, 368 { type: 'distance', distanceValue: 3, distanceUnit: 'miles' }, 369 ], 370 }, 371 }], 372 [{ 373 _split_targets: { 374 name: '5K Mile Splits', 375 targets: [ 376 { type: 'distance', distanceValue: 1, distanceUnit: 'miles' }, 377 { type: 'distance', distanceValue: 2, distanceUnit: 'miles' }, 378 { type: 'distance', distanceValue: 3, distanceUnit: 'miles' }, 379 { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, 380 { type: 'time', timeValue: 60 }, 381 ], 382 }, 383 }], 384 ]); 385 }); 386 387 test('should correctly pass setType prop to TargetEditor', async () => { 388 const wrapper = shallowMount(TargetSetSelector, { 389 propsData: { 390 selectedTargetSet: '_new', 391 targetSets: {}, 392 setType: 'foo' 393 }, 394 }); 395 396 // Assert target editor props are correct 397 expect(wrapper.findComponent({ name: 'target-editor' }).vm.setType).to.equal('foo'); 398 }); 399 400 test('should correctly pass customWorkoutNames prop to TargetEditor', async () => { 401 const wrapper = shallowMount(TargetSetSelector, { 402 propsData: { 403 selectedTargetSet: '_new', 404 targetSets: {}, 405 customWorkoutNames: false, 406 } 407 }); 408 409 // Assert target editor props are correct 410 expect(wrapper.findComponent({ name: 'target-editor' }).vm.customWorkoutNames).to.equal(false); 411 412 // Update customWorkoutNames prop 413 await wrapper.setProps({ customWorkoutNames: true }); 414 415 // Assert target editor props are correct 416 expect(wrapper.findComponent({ name: 'target-editor' }).vm.customWorkoutNames).to.equal(true); 417 });