running-tools

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

commit 49de02063e07c29ea764fa088c034c8fd6df404e
parent 78feba7fc21b6777e9e70fe0350ebaa3536a4c09
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date:   Thu, 13 Jun 2024 11:56:26 -0700

Fix bug where new target sets were created twice

Diffstat:
Msrc/components/TargetSetSelector.vue | 51++++++++++++++++++++++++++-------------------------
Mtests/unit/components/TargetSetSelector.spec.js | 45++++++++++++++++++++++++++++++++++++---------
2 files changed, 62 insertions(+), 34 deletions(-)

diff --git a/src/components/TargetSetSelector.vue b/src/components/TargetSetSelector.vue @@ -20,7 +20,7 @@ </template> <script setup> -import { nextTick, ref, watch } from 'vue'; +import { computed, nextTick, ref } from 'vue'; import VueFeather from 'vue-feather'; @@ -63,40 +63,41 @@ defineProps({ }); /** - * The internal value - */ -const internalValue = ref(model.value); - -/** * The dialog element */ const dialogElement = ref(null); /** - * Update the internal value when the component value changes + * The internal value */ -watch(model, (newValue) => { - if (newValue !== internalValue.value) { - internalValue.value = newValue; - } +const internalValue = computed({ + get: () => { + if (model.value == '_new') { + newTargetSet(); + } + return model.value; + }, + set: async (newValue) => { + if (newValue == '_new') { + await nextTick(); // <select> won't update if value changed immediately + newTargetSet(); + } else { + model.value = newValue; + } + }, }); /** - * Update the component value when the internal value changes and create a new set if necessary + * Create and select a new target */ -watch(internalValue, async (newValue) => { - if (newValue == '_new') { - let key = Date.now().toString(); - targetSets.value[key] = { - name: 'New target set', - targets: [], - }; - await nextTick(); // <select> won't update if value changed immediately - model.value = key; - } else { - model.value = newValue; - } -}, { immediate: true }); +function newTargetSet() { + let key = Date.now().toString(); + targetSets.value[key] = { + name: 'New target set', + targets: [], + }; + model.value = key; +} /** * Revert or remove the current target set diff --git a/tests/unit/components/TargetSetSelector.spec.js b/tests/unit/components/TargetSetSelector.spec.js @@ -64,32 +64,59 @@ test('Create New Target Set option should correctly add target set', async () => }; const wrapper = shallowMount(TargetSetSelector, { propsData: { - selectedTargetSet: 'A', + selectedTargetSet: '_new', targetSets, } }); - - // Add target set - await wrapper.find('select').setValue('_new'); + await wrapper.vm.$nextTick(); // Assert new target set selected (key is unix timestamp in milliseconds) - const key = wrapper.find('select').element.value - expect(parseInt(key)).to.be.closeTo(parseInt(Date.now().toString()), 1000); + const key1 = wrapper.find('select').element.value; + expect(parseInt(key1)).to.be.closeTo(parseInt(Date.now().toString()), 1000); // Assert target set options were correctly updated - const options = wrapper.findAll('option'); + let options = wrapper.findAll('option'); expect(options[0].element.text).to.equal('1st target set'); expect(options[0].element.value).to.equal('A'); expect(options[1].element.text).to.equal('2nd target set'); expect(options[1].element.value).to.equal('B'); expect(options[2].element.text).to.equal('New target set'); - expect(options[2].element.value).to.match(/\d{12,14}/); + expect(options[2].element.value).to.equal(key1) expect(options[3].element.text).to.equal('[ Create New Target Set ]'); expect(options[3].element.value).to.equal('_new'); expect(options.length).to.equal(4); // Assert target sets were correctly updated - targetSets[options[2].element.value] = { + targetSets[key1] = { + name: 'New target set', + targets: [], + }; + expect(wrapper.vm.targetSets).to.deep.equal(targetSets); + + // Add another target set + await wrapper.find('select').setValue('_new'); + + // Assert new target set selected (key is unix timestamp in milliseconds) + const key2 = wrapper.find('select').element.value; + expect(parseInt(key2)).to.be.closeTo(parseInt(Date.now().toString()), 1000); + expect(key2).to.not.equal(key1); + + // Assert target set options were correctly updated + options = wrapper.findAll('option'); + expect(options[0].element.text).to.equal('1st target set'); + expect(options[0].element.value).to.equal('A'); + expect(options[1].element.text).to.equal('2nd target set'); + expect(options[1].element.value).to.equal('B'); + expect(options[2].element.text).to.equal('New target set'); + expect(options[2].element.value).to.equal(key1) + expect(options[3].element.text).to.equal('New target set'); + expect(options[3].element.value).to.equal(key2); + expect(options[4].element.text).to.equal('[ Create New Target Set ]'); + expect(options[4].element.value).to.equal('_new'); + expect(options.length).to.equal(5); + + // Assert target sets were correctly updated + targetSets[key2] = { name: 'New target set', targets: [], };