running-tools

A collection of tools for runners and their coaches
git clone https://git.ashermorgan.net/running-tools/
Log | Files | Refs | README

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 });