running-tools

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

TargetEditor.spec.js (21354B)


      1 import { test, expect } from 'vitest';
      2 import { shallowMount } from '@vue/test-utils';
      3 import TargetEditor from '@/components/TargetEditor.vue';
      4 
      5 test('should correctly render standard target set', async () => {
      6   // Initialize component
      7   const wrapper = shallowMount(TargetEditor, {
      8     propsData: {
      9       modelValue: {
     10         name: 'My target set',
     11         targets: [
     12           { distanceUnit: 'kilometers', distanceValue: 1.61, type: 'distance' },
     13           { distanceUnit: 'miles', distanceValue: 3.11, type: 'distance' },
     14           { time: 600, type: 'time' },
     15         ],
     16       },
     17       setType: 'standard',
     18       customWorkoutNames: true, // name input should not be rendered
     19     },
     20   });
     21 
     22   // Assert target set correctly rendered
     23   expect(wrapper.find('input').element.value).to.equal('My target set');
     24   const rows = wrapper.findAll('tbody tr');
     25   expect(rows[0].findAll('input').length).to.equal(0);
     26   expect(rows[0].findComponent({ name: 'decimal-input' }).vm.modelValue).to.equal(1.61);
     27   expect(rows[0].find('select').element.value).to.equal('kilometers');
     28   expect(rows[1].findAll('input').length).to.equal(0);
     29   expect(rows[1].findComponent({ name: 'decimal-input' }).vm.modelValue).to.equal(3.11);
     30   expect(rows[1].find('select').element.value).to.equal('miles');
     31   expect(rows[2].findAll('input').length).to.equal(0);
     32   expect(rows[2].findComponent({ name: 'time-input' }).vm.modelValue).to.equal(600);
     33   expect(rows.length).to.equal(3);
     34 });
     35 
     36 test('should correctly render split target set', async () => {
     37   // Initialize component
     38   const wrapper = shallowMount(TargetEditor, {
     39     propsData: {
     40       modelValue: {
     41         name: 'My target set',
     42         targets: [
     43           { distanceUnit: 'kilometers', distanceValue: 1.61, type: 'distance' },
     44           { distanceUnit: 'miles', distanceValue: 3.11, type: 'distance' },
     45         ],
     46       },
     47       setType: 'split',
     48     },
     49   });
     50 
     51   // Assert target set correctly rendered
     52   expect(wrapper.find('input').element.value).to.equal('My target set');
     53   const rows = wrapper.findAll('tbody tr');
     54   expect(rows[0].findAll('input').length).to.equal(0);
     55   expect(rows[0].findComponent({ name: 'decimal-input' }).vm.modelValue).to.equal(1.61);
     56   expect(rows[0].find('select').element.value).to.equal('kilometers');
     57   expect(rows[1].findAll('input').length).to.equal(0);
     58   expect(rows[1].findComponent({ name: 'decimal-input' }).vm.modelValue).to.equal(3.11);
     59   expect(rows[1].find('select').element.value).to.equal('miles');
     60   expect(rows.length).to.equal(2);
     61 });
     62 
     63 test('should correctly render workout target set without custom names', async () => {
     64   // Initialize component
     65   const wrapper = shallowMount(TargetEditor, {
     66     propsData: {
     67       modelValue: {
     68         name: 'My target set',
     69         targets: [
     70           {
     71             distanceUnit: 'miles', distanceValue: 2,
     72             splitUnit: 'meters', splitValue: 400,
     73             type: 'distance',
     74           },
     75           {
     76             time: 6000,
     77             splitUnit: 'kilometers', splitValue: 2,
     78             type: 'time',
     79           },
     80           {
     81             distanceUnit: 'kilometers', distanceValue: 5,
     82             splitUnit: 'miles', splitValue: 1,
     83             type: 'distance'
     84           },
     85         ],
     86       },
     87       setType: 'workout',
     88     },
     89   });
     90 
     91   // Assert target set correctly rendered
     92   expect(wrapper.find('input').element.value).to.equal('My target set');
     93   const rows = wrapper.findAll('tbody tr');
     94   expect(rows[0].findAll('input').length).to.equal(0);
     95   expect(rows[0].findAllComponents({ name: 'decimal-input' })[0].vm.modelValue).to.equal(400);
     96   expect(rows[0].findAll('select')[0].element.value).to.equal('meters');
     97   expect(rows[0].findAllComponents({ name: 'decimal-input' })[1].vm.modelValue).to.equal(2);
     98   expect(rows[0].findAll('select')[1].element.value).to.equal('miles');
     99   expect(rows[1].findAll('input').length).to.equal(0);
    100   expect(rows[1].findComponent({ name: 'decimal-input' }).vm.modelValue).to.equal(2);
    101   expect(rows[1].find('select').element.value).to.equal('kilometers');
    102   expect(rows[1].findComponent({ name: 'time-input' }).vm.modelValue).to.equal(6000);
    103   expect(rows[2].findAll('input').length).to.equal(0);
    104   expect(rows[2].findAllComponents({ name: 'decimal-input' })[0].vm.modelValue).to.equal(1);
    105   expect(rows[2].findAll('select')[0].element.value).to.equal('miles');
    106   expect(rows[2].findAllComponents({ name: 'decimal-input' })[1].vm.modelValue).to.equal(5);
    107   expect(rows[2].findAll('select')[1].element.value).to.equal('kilometers');
    108   expect(rows.length).to.equal(3);
    109 });
    110 
    111 test('should correctly render workout target set with custom names', async () => {
    112   // Initialize component
    113   const wrapper = shallowMount(TargetEditor, {
    114     propsData: {
    115       modelValue: {
    116         name: 'My target set',
    117         targets: [
    118           {
    119             // customName is undefined
    120             distanceUnit: 'miles', distanceValue: 2,
    121             splitUnit: 'meters', splitValue: 400,
    122             type: 'distance',
    123           },
    124           {
    125             customName: '',
    126             time: 6000,
    127             splitUnit: 'kilometers', splitValue: 2,
    128             type: 'time',
    129           },
    130           {
    131             customName: 'my custom name',
    132             distanceUnit: 'kilometers', distanceValue: 5,
    133             splitUnit: 'miles', splitValue: 1,
    134             type: 'distance'
    135           },
    136         ],
    137       },
    138       setType: 'workout',
    139       customWorkoutNames: true,
    140     },
    141   });
    142 
    143   // Assert target set correctly rendered
    144   expect(wrapper.find('input').element.value).to.equal('My target set');
    145   const rows = wrapper.findAll('tbody tr');
    146   expect(rows[0].find('input').element.value).to.equal('');
    147   expect(rows[0].find('input').element.placeholder).to.equal('400 m @ 2 mi');
    148   expect(rows[0].findAllComponents({ name: 'decimal-input' })[0].vm.modelValue).to.equal(400);
    149   expect(rows[0].findAll('select')[0].element.value).to.equal('meters');
    150   expect(rows[0].findAllComponents({ name: 'decimal-input' })[1].vm.modelValue).to.equal(2);
    151   expect(rows[0].findAll('select')[1].element.value).to.equal('miles');
    152   expect(rows[1].find('input').element.value).to.equal('');
    153   expect(rows[1].find('input').element.placeholder).to.equal('2 km @ 1:40:00');
    154   expect(rows[1].findComponent({ name: 'decimal-input' }).vm.modelValue).to.equal(2);
    155   expect(rows[1].find('select').element.value).to.equal('kilometers');
    156   expect(rows[1].findComponent({ name: 'time-input' }).vm.modelValue).to.equal(6000);
    157   expect(rows[2].find('input').element.value).to.equal('my custom name');
    158   expect(rows[2].find('input').element.placeholder).to.equal('1 mi @ 5 km');
    159   expect(rows[2].findAllComponents({ name: 'decimal-input' })[0].vm.modelValue).to.equal(1);
    160   expect(rows[2].findAll('select')[0].element.value).to.equal('miles');
    161   expect(rows[2].findAllComponents({ name: 'decimal-input' })[1].vm.modelValue).to.equal(5);
    162   expect(rows[2].findAll('select')[1].element.value).to.equal('kilometers');
    163   expect(rows.length).to.equal(3);
    164 });
    165 
    166 test('revert button should emit revert event', async () => {
    167   // Initialize component
    168   const wrapper = shallowMount(TargetEditor, {
    169     propsData: {
    170       modelValue: {
    171         name: 'My target set',
    172         targets: [],
    173       },
    174     },
    175   });
    176 
    177   // Click revert button
    178   await wrapper.find('button[title="Revert target set"]').trigger('click');
    179 
    180   // Assert revert event was emitted
    181   expect(wrapper.emitted().revert.length).to.equal(1);
    182 });
    183 
    184 test('delete button should emit revert event', async () => {
    185   // Initialize component
    186   const wrapper = shallowMount(TargetEditor, {
    187     propsData: {
    188       modelValue: {
    189         name: 'My target set',
    190         targets: [],
    191       },
    192       isCustomSet: true,
    193     },
    194   });
    195 
    196   // Click delete button
    197   await wrapper.find('button[title="Delete target set"]').trigger('click');
    198 
    199   // Assert revert event was emitted
    200   expect(wrapper.emitted().revert.length).to.equal(1);
    201 });
    202 
    203 test('close button should emit close event', async () => {
    204   // Initialize component
    205   const wrapper = shallowMount(TargetEditor, {
    206     propsData: {
    207       modelValue: {
    208         name: 'My target set',
    209         targets: [],
    210       },
    211     },
    212   });
    213 
    214   // Call close method
    215   await wrapper.find('button[title="Close"]').trigger('click');
    216 
    217   // Assert close event was emitted
    218   expect(wrapper.emitted().close.length).to.equal(1);
    219 });
    220 
    221 test('add distance target button should correctly add standard imperial distance target', async () => {
    222   // Initialize component
    223   const wrapper = shallowMount(TargetEditor, {
    224     propsData: {
    225       modelValue: {
    226         name: 'My target set',
    227         targets: [
    228           { distanceUnit: 'miles', distanceValue: 0, type: 'distance' },
    229           { time: 0, type: 'time' },
    230         ],
    231       },
    232       setType: 'standard',
    233       defaultUnitSystem: 'imperial',
    234     },
    235   });
    236 
    237   // Add distance target
    238   await wrapper.find('button[title="Add distance target"]').trigger('click');
    239 
    240   // Assert input event was emitted
    241   expect(wrapper.emitted()['update:modelValue']).to.deep.equal([
    242     [{
    243       name: 'My target set',
    244       targets: [
    245         { distanceUnit: 'miles', distanceValue: 0, type: 'distance' },
    246         { time: 0, type: 'time' },
    247         { distanceUnit: 'miles', distanceValue: 1, type: 'distance'},
    248       ],
    249     }],
    250   ]);
    251 });
    252 
    253 test('add distance target button should correctly add standard metric distance target', async () => {
    254   // Initialize component
    255   const wrapper = shallowMount(TargetEditor, {
    256     propsData: {
    257       modelValue: {
    258         name: 'My target set',
    259         targets: [
    260           { distanceUnit: 'miles', distanceValue: 0, type: 'distance' },
    261           { time: 0, type: 'time' },
    262         ],
    263       },
    264       setType: 'standard',
    265       defaultUnitSystem: 'metric',
    266     },
    267   });
    268 
    269   // Add distance target
    270   await wrapper.find('button[title="Add distance target"]').trigger('click');
    271 
    272   // Assert input event was emitted
    273   expect(wrapper.emitted()['update:modelValue']).to.deep.equal([
    274     [{
    275       name: 'My target set',
    276       targets: [
    277         { distanceUnit: 'miles', distanceValue: 0, type: 'distance' },
    278         { time: 0, type: 'time' },
    279         { distanceUnit: 'kilometers', distanceValue: 1, type: 'distance'},
    280       ],
    281     }],
    282   ]);
    283 });
    284 
    285 test('add distance target button should correctly add split imperial distance target', async () => {
    286   // Initialize component
    287   const wrapper = shallowMount(TargetEditor, {
    288     propsData: {
    289       modelValue: {
    290         name: 'My target set',
    291         targets: [
    292           { distanceUnit: 'miles', distanceValue: 0, type: 'distance' },
    293         ],
    294       },
    295       setType: 'split',
    296       defaultUnitSystem: 'imperial',
    297     },
    298   });
    299 
    300   // Add distance target
    301   await wrapper.find('button[title="Add distance target"]').trigger('click');
    302 
    303   // Assert input event was emitted
    304   expect(wrapper.emitted()['update:modelValue']).to.deep.equal([
    305     [{
    306       name: 'My target set',
    307       targets: [
    308         { distanceUnit: 'miles', distanceValue: 0, type: 'distance' },
    309         { distanceUnit: 'miles', distanceValue: 1, type: 'distance'},
    310       ],
    311     }],
    312   ]);
    313 });
    314 
    315 test('add distance target button should correctly add split metric distance target', async () => {
    316   // Initialize component
    317   const wrapper = shallowMount(TargetEditor, {
    318     propsData: {
    319       modelValue: {
    320         name: 'My target set',
    321         targets: [
    322           { distanceUnit: 'miles', distanceValue: 0, type: 'distance' },
    323         ],
    324       },
    325       setType: 'split',
    326       defaultUnitSystem: 'metric',
    327     },
    328   });
    329 
    330   // Add distance target
    331   await wrapper.find('button[title="Add distance target"]').trigger('click');
    332 
    333   // Assert input event was emitted
    334   expect(wrapper.emitted()['update:modelValue']).to.deep.equal([
    335     [{
    336       name: 'My target set',
    337       targets: [
    338         { distanceUnit: 'miles', distanceValue: 0, type: 'distance' },
    339         { distanceUnit: 'kilometers', distanceValue: 1, type: 'distance'},
    340       ],
    341     }],
    342   ]);
    343 });
    344 
    345 test('add distance target button should correctly add workout imperial distance target', async () => {
    346   // Initialize component
    347   const wrapper = shallowMount(TargetEditor, {
    348     propsData: {
    349       modelValue: {
    350         name: 'My target set',
    351         targets: [
    352           {
    353             distanceUnit: 'miles', distanceValue: 2,
    354             splitUnit: 'meters', splitValue: 400,
    355             type: 'distance',
    356           },
    357           {
    358             time: 6000,
    359             splitUnit: 'kilometers', splitValue: 2,
    360             type: 'time',
    361           },
    362         ],
    363       },
    364       setType: 'workout',
    365       defaultUnitSystem: 'imperial',
    366     },
    367   });
    368 
    369   // Add distance target
    370   await wrapper.find('button[title="Add distance target"]').trigger('click');
    371 
    372   // Assert input event was emitted
    373   expect(wrapper.emitted()['update:modelValue']).to.deep.equal([
    374     [{
    375       name: 'My target set',
    376       targets: [
    377         {
    378           distanceUnit: 'miles', distanceValue: 2,
    379           splitUnit: 'meters', splitValue: 400,
    380           type: 'distance',
    381         },
    382         {
    383           time: 6000,
    384           splitUnit: 'kilometers', splitValue: 2,
    385           type: 'time',
    386         },
    387         {
    388           distanceUnit: 'miles', distanceValue: 1,
    389           splitUnit: 'miles', splitValue: 1,
    390           type: 'distance'
    391         },
    392       ],
    393     }],
    394   ]);
    395 });
    396 
    397 test('add distance target button should correctly add workout metric distance target', async () => {
    398   // Initialize component
    399   const wrapper = shallowMount(TargetEditor, {
    400     propsData: {
    401       modelValue: {
    402         name: 'My target set',
    403         targets: [
    404           {
    405             distanceUnit: 'miles', distanceValue: 2,
    406             splitUnit: 'meters', splitValue: 400,
    407             type: 'distance',
    408           },
    409           {
    410             time: 6000,
    411             splitUnit: 'kilometers', splitValue: 2,
    412             type: 'time',
    413           },
    414         ],
    415       },
    416       setType: 'workout',
    417       defaultUnitSystem: 'metric',
    418     },
    419   });
    420 
    421   // Add distance target
    422   await wrapper.find('button[title="Add distance target"]').trigger('click');
    423 
    424   // Assert input event was emitted
    425   expect(wrapper.emitted()['update:modelValue']).to.deep.equal([
    426     [{
    427       name: 'My target set',
    428       targets: [
    429         {
    430           distanceUnit: 'miles', distanceValue: 2,
    431           splitUnit: 'meters', splitValue: 400,
    432           type: 'distance',
    433         },
    434         {
    435           time: 6000,
    436           splitUnit: 'kilometers', splitValue: 2,
    437           type: 'time',
    438         },
    439         {
    440           distanceUnit: 'kilometers', distanceValue: 1,
    441           splitUnit: 'kilometers', splitValue: 1,
    442           type: 'distance'
    443         },
    444       ],
    445     }],
    446   ]);
    447 });
    448 
    449 test('add time target button should correctly add standard time target', async () => {
    450   // Initialize component
    451   const wrapper = shallowMount(TargetEditor, {
    452     propsData: {
    453       modelValue: {
    454         name: 'My target set',
    455         targets: [
    456           { distanceUnit: 'miles', distanceValue: 0, type: 'distance' },
    457           { time: 0, type: 'time' },
    458         ],
    459       },
    460       setType: 'standard',
    461     },
    462   });
    463 
    464   // Add time target
    465   await wrapper.find('button[title="Add time target"]').trigger('click');
    466 
    467   // Assert input event was emitted
    468   expect(wrapper.emitted()['update:modelValue']).to.deep.equal([
    469     [{ name: 'My target set',
    470       targets: [
    471         { distanceUnit: 'miles', distanceValue: 0, type: 'distance' },
    472         { time: 0, type: 'time' },
    473         { time: 600, type: 'time' },
    474       ],
    475     }],
    476   ]);
    477 });
    478 
    479 test('add time target button should be hidden for split target sets', async () => {
    480   // Initialize component
    481   const wrapper = shallowMount(TargetEditor, {
    482     propsData: {
    483       modelValue: {
    484         name: 'My target set',
    485         targets: [
    486           { distanceUnit: 'miles', distanceValue: 1, type: 'distance' },
    487           { distanceUnit: 'miles', distanceValue: 2, type: 'distance' },
    488         ],
    489       },
    490       setType: 'split',
    491     },
    492   });
    493 
    494   // Add time target
    495   expect(wrapper.findAll('button[title="Add time target"]')).toHaveLength(0);
    496 });
    497 
    498 test('add time target button should correctly add workout imperial time target', async () => {
    499   // Initialize component
    500   const wrapper = shallowMount(TargetEditor, {
    501     propsData: {
    502       modelValue: {
    503         name: 'My target set',
    504         targets: [
    505           {
    506             distanceUnit: 'miles', distanceValue: 2,
    507             splitUnit: 'meters', splitValue: 400,
    508             type: 'distance',
    509           },
    510           {
    511             time: 6000,
    512             splitUnit: 'kilometers', splitValue: 2,
    513             type: 'time',
    514           },
    515         ],
    516       },
    517       setType: 'workout',
    518       defaultUnitSystem: 'imperial',
    519     },
    520   });
    521 
    522   // Add distance target
    523   await wrapper.find('button[title="Add time target"]').trigger('click');
    524 
    525   // Assert input event was emitted
    526   expect(wrapper.emitted()['update:modelValue']).to.deep.equal([
    527     [{
    528       name: 'My target set',
    529       targets: [
    530         {
    531           distanceUnit: 'miles', distanceValue: 2,
    532           splitUnit: 'meters', splitValue: 400,
    533           type: 'distance',
    534         },
    535         {
    536           time: 6000,
    537           splitUnit: 'kilometers', splitValue: 2,
    538           type: 'time',
    539         },
    540         {
    541           time: 600,
    542           splitUnit: 'miles', splitValue: 1,
    543           type: 'time'
    544         },
    545       ],
    546     }],
    547   ]);
    548 });
    549 
    550 test('add time target button should correctly add workout metric time target', async () => {
    551   // Initialize component
    552   const wrapper = shallowMount(TargetEditor, {
    553     propsData: {
    554       modelValue: {
    555         name: 'My target set',
    556         targets: [
    557           {
    558             distanceUnit: 'miles', distanceValue: 2,
    559             splitUnit: 'meters', splitValue: 400,
    560             type: 'distance',
    561           },
    562           {
    563             time: 6000,
    564             splitUnit: 'kilometers', splitValue: 2,
    565             type: 'time',
    566           },
    567         ],
    568       },
    569       setType: 'workout',
    570       defaultUnitSystem: 'metric',
    571     },
    572   });
    573 
    574   // Add distance target
    575   await wrapper.find('button[title="Add time target"]').trigger('click');
    576 
    577   // Assert input event was emitted
    578   expect(wrapper.emitted()['update:modelValue']).to.deep.equal([
    579     [{
    580       name: 'My target set',
    581       targets: [
    582         {
    583           distanceUnit: 'miles', distanceValue: 2,
    584           splitUnit: 'meters', splitValue: 400,
    585           type: 'distance',
    586         },
    587         {
    588           time: 6000,
    589           splitUnit: 'kilometers', splitValue: 2,
    590           type: 'time',
    591         },
    592         {
    593           time: 600,
    594           splitUnit: 'kilometers', splitValue: 1,
    595           type: 'time'
    596         },
    597       ],
    598     }],
    599   ]);
    600 });
    601 
    602 test('should emit input event when targets are updated', async () => {
    603   // Initialize component
    604   const wrapper = shallowMount(TargetEditor, {
    605     propsData: {
    606       modelValue: {
    607         name: 'My target set',
    608         targets: [
    609           { distanceUnit: 'miles', distanceValue: 2, type: 'distance' },
    610         ],
    611       },
    612     },
    613   });
    614 
    615   // Update distance value
    616   await wrapper.findComponent({ name: 'decimal-input' }).setValue(3);
    617 
    618   // Assert input event was emitted
    619   expect(wrapper.emitted()['update:modelValue']).to.deep.equal([
    620     [
    621       {
    622         name: 'My target set',
    623         targets: [
    624           { distanceUnit: 'miles', distanceValue: 3, type: 'distance' },
    625         ],
    626       },
    627     ],
    628   ]);
    629 });
    630 
    631 test('should emit input event when target set name is updated', async () => {
    632   // Initialize component
    633   const wrapper = shallowMount(TargetEditor, {
    634     propsData: {
    635       modelValue: {
    636         name: 'My target set',
    637         targets: [
    638           { distanceUnit: 'miles', distanceValue: 2, type: 'distance' },
    639         ],
    640       },
    641     },
    642   });
    643 
    644   // Update distance value
    645   await wrapper.find('input').setValue('My target set #2');
    646 
    647   // Assert input event was emitted
    648   expect(wrapper.emitted()['update:modelValue']).to.deep.equal([
    649     [
    650       {
    651         name: 'My target set #2',
    652         targets: [
    653           { distanceUnit: 'miles', distanceValue: 2, type: 'distance' },
    654         ],
    655       },
    656     ],
    657   ]);
    658 });
    659 
    660 test('removeTarget button should correctly remove target', async () => {
    661   // Initialize component
    662   const wrapper = shallowMount(TargetEditor, {
    663     propsData: {
    664       modelValue: {
    665         name: 'My target set',
    666         targets: [
    667           { distanceUnit: 'miles', distanceValue: 1, type: 'distance' },
    668           { distanceUnit: 'miles', distanceValue: 2, type: 'distance' },
    669           { distanceUnit: 'miles', distanceValue: 3, type: 'distance' },
    670         ],
    671       },
    672     },
    673   });
    674 
    675   // Remove 2nd target
    676   await wrapper.findAll('button[title="Remove target"]')[1].trigger('click');
    677 
    678   // Assert input event was emitted
    679   expect(wrapper.emitted()['update:modelValue']).to.deep.equal([
    680     [{
    681       name: 'My target set',
    682       targets: [
    683         { distanceUnit: 'miles', distanceValue: 1, type: 'distance' },
    684         { distanceUnit: 'miles', distanceValue: 3, type: 'distance' },
    685       ],
    686     }],
    687   ]);
    688 });
    689 
    690 test('should display message when target set is empty', async () => {
    691   // Initialize component
    692   const wrapper = shallowMount(TargetEditor, {
    693     propsData: {
    694       modelValue: {
    695         name: 'My target set',
    696         targets: [],
    697       },
    698     },
    699   });
    700 
    701   // Assert message correctly rendered
    702   const rows = wrapper.findAll('tbody tr');
    703   expect(rows[0].text()).to.equal('There aren\'t any targets in this set yet.');
    704   expect(rows.length).to.equal(1);
    705 });