commit 147f47f096469669d4925a172f91ff35feba94f2
parent bfd85b24ed19608c23f7a2d4e9f5c2e7fd516ed6
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date: Sat, 28 Jun 2025 14:52:15 -0700
Use withDefaults macro for most prop definitions
Also removed unnecessary default prop values.
Diffstat:
11 files changed, 93 insertions(+), 105 deletions(-)
diff --git a/src/components/DoubleOutputTable.vue b/src/components/DoubleOutputTable.vue
@@ -28,7 +28,6 @@
<script setup lang="ts">
import { computed } from 'vue';
-import type { PropType } from 'vue';
import { ResultType } from '@/utils/calculators';
import type { TargetResult } from '@/utils/calculators';
@@ -37,42 +36,29 @@ import type { Target } from '@/utils/targets';
import { DistanceUnitData } from '@/utils/units';
import type { Distance, DistanceTime } from '@/utils/units';
-const props = defineProps({
+interface Props {
/**
* The method that generates the target table rows
*/
- calculateResult: {
- type: Function as PropType<(x: DistanceTime, y: Target) => TargetResult>,
- required: true,
- },
+ calculateResult: (x: DistanceTime, y: Target) => TargetResult,
/**
* The target set
*/
- targets: {
- type: Array<Target>,
- default: () => [],
- },
+ targets: Array<Target>,
/**
* The set of input times
*/
- inputTimes: {
- type: Array<number>,
- default: () => [],
- },
+ inputTimes: Array<number>,
/**
* The input distance
*/
- inputDistance: {
- type: Object as PropType<Distance>,
- default: () => ({
- distanceValue: 5,
- distanceUnit: 'kilometers',
- }),
- }
-});
+ inputDistance: Distance,
+}
+
+const props = defineProps<Props>();
/**
* The target table results
diff --git a/src/components/PaceInput.vue b/src/components/PaceInput.vue
@@ -18,8 +18,6 @@
</template>
<script setup lang="ts">
-import type { PropType } from 'vue';
-
import { DistanceUnits, DistanceUnitData } from '@/utils/units';
import type { DistanceTime } from '@/utils/units';
@@ -27,27 +25,19 @@ import DecimalInput from '@/components/DecimalInput.vue';
import TimeInput from '@/components/TimeInput.vue';
import useObjectModel from '@/composables/useObjectModel';
-const props = defineProps({
+interface Props {
/**
- * The prefix for each field's aria-label
+ * The prefix for each field's aria-label (defaults to 'Input')
*/
- label: {
- type: String,
- default: 'Input',
- },
+ label?: string,
/**
* The component value
*/
- modelValue: {
- type: Object as PropType<DistanceTime>,
- default: () => ({
- distanceValue: 5,
- distanceUnit: 'kilometers',
- time: 1200,
- }),
- },
-});
+ modelValue: DistanceTime,
+};
+
+const props = withDefaults(defineProps<Props>(), { label: 'Input' });
// Generate internal ref tied to modelValue prop
const emit = defineEmits(['update:modelValue']);
diff --git a/src/components/RaceOptions.vue b/src/components/RaceOptions.vue
@@ -18,25 +18,19 @@
</template>
<script setup lang="ts">
-import type { PropType } from 'vue';
-
import type { RaceOptions } from '@/utils/calculators';
import DecimalInput from '@/components/DecimalInput.vue';
import useObjectModel from '@/composables/useObjectModel';
-const props = defineProps({
+interface Props {
/**
* The component value
*/
- modelValue: {
- type: Object as PropType<RaceOptions>,
- default: () => ({
- model: 'AverageModel',
- riegelExponent: 1.06,
- }),
- },
-});
+ modelValue: RaceOptions,
+}
+
+const props = defineProps<Props>();
// Generate internal ref tied to modelValue prop
const emit = defineEmits(['update:modelValue']);
diff --git a/src/components/SingleOutputTable.vue b/src/components/SingleOutputTable.vue
@@ -38,36 +38,28 @@
<script setup lang="ts">
import { computed } from 'vue';
-import type { PropType } from 'vue';
import type { TargetResult } from '@/utils/calculators';
import type { Target } from '@/utils/targets';
-const props = defineProps({
+interface Props {
/**
* The method that generates the target table rows
*/
- calculateResult: {
- type: Function as PropType<(x: Target) => TargetResult>,
- required: true,
- },
+ calculateResult: (x: Target) => TargetResult,
/**
* The target set
*/
- targets: {
- type: Array<Target>,
- default: () => [],
- },
+ targets: Array<Target>,
/**
- * Whether to show result paces
+ * Whether to show result paces (defaults to false)
*/
- showPace: {
- type: Boolean,
- default: false,
- },
-});
+ showPace?: boolean,
+};
+
+const props = withDefaults(defineProps<Props>(), { showPace: false });
/**
* The target table results
diff --git a/src/components/SplitOutputTable.vue b/src/components/SplitOutputTable.vue
@@ -48,7 +48,6 @@
<script setup lang="ts">
import { computed } from 'vue';
-import type { PropType } from 'vue';
import { formatDuration, formatNumber } from '@/utils/format';
import type { SplitTarget } from '@/utils/targets';
@@ -69,20 +68,17 @@ interface SplitTargetResult {
interface Props {
/**
- * The unit system to use when showing result paces
+ * The unit system to use when showing result paces (defaults to metric)
*/
defaultUnitSystem?: UnitSystems,
/**
* The split targets
*/
- modelValue?: Array<SplitTarget>,
+ modelValue: Array<SplitTarget>,
};
-const props = withDefaults(defineProps<Props>(), {
- defaultUnitSystem: UnitSystems.Metric,
- modelValue: [],
-});
+const props = withDefaults(defineProps<Props>(), { defaultUnitSystem: UnitSystems.Metric });
// Generate internal ref tied to modelValue prop
const emit = defineEmits(['update:modelValue']);
diff --git a/src/components/TargetEditor.vue b/src/components/TargetEditor.vue
@@ -88,7 +88,6 @@
<script setup lang="ts">
import VueFeather from 'vue-feather';
-import type { PropType } from 'vue';
import { TargetType, TargetSetType, workoutTargetToString } from '@/utils/targets';
import type { StandardTargetSet, TargetSet, WorkoutTarget, WorkoutTargetSet } from '@/utils/targets';
@@ -100,26 +99,26 @@ import useObjectModel from '@/composables/useObjectModel';
interface Props {
/**
- * Whether to allow custom names for workout targets
+ * Whether to allow custom names for workout targets (defaults to false)
*/
customWorkoutNames?: boolean,
/**
- * The unit system to use when creating distance targets
+ * The unit system to use when creating distance targets (defaults to metric)
*/
defaultUnitSystem?: UnitSystems,
/**
- * Whether the target set is a custom or default set
+ * Whether the target set is a custom or default set (defaults to false)
*/
isCustomSet?: boolean,
/**
* The component value
*/
- modelValue?: TargetSet,
+ modelValue: TargetSet,
/**
- * The target set type ('standard', 'split', or 'workout')
+ * The target set type (Standard, Split, or Workout, defaults to Standard)
*/
setType?: TargetSetType,
}
@@ -128,10 +127,6 @@ const props = withDefaults(defineProps<Props>(), {
customWorkoutNames: false,
defaultUnitSystem: UnitSystems.Metric,
isCustomSet: false,
- modelValue: {
- name: 'New target set',
- targets: [],
- },
setType: TargetSetType.Standard,
});
diff --git a/src/components/TargetSetSelector.vue b/src/components/TargetSetSelector.vue
@@ -22,7 +22,6 @@
<script setup lang="ts">
import { computed, nextTick, ref } from 'vue';
-import type { PropType } from 'vue';
import VueFeather from 'vue-feather';
@@ -39,29 +38,29 @@ import useObjectModel from '@/composables/useObjectModel';
*/
const model = defineModel('selectedTargetSet', {
type: String,
- default: '_new',
+ required: true,
});
interface Props {
/**
- * Whether to allow custom names for workout targets
+ * Whether to allow custom names for workout targets (defaults to false)
*/
- customWorkoutNames?: Boolean,
+ customWorkoutNames?: boolean,
/**
- * The unit system to use when creating distance targets
+ * The unit system to use when creating distance targets (defaults to metric)
*/
defaultUnitSystem?: UnitSystems,
/**
- * The target set type ('standard', 'split', or 'workout')
+ * The target set type (Standard, Split, or Workout, defaults to Standard)
*/
setType?: TargetSetType,
/**
* The target sets
*/
- targetSets?: TargetSets,
+ targetSets: TargetSets,
};
@@ -69,7 +68,6 @@ const props = withDefaults(defineProps<Props>(), {
customWorkoutNames: false,
defaultUnitSystem: UnitSystems.Metric,
setType: TargetSetType.Standard,
- targetSets: {}
});
// Generate internal ref tied to modelValue prop
diff --git a/tests/unit/components/PaceInput.spec.js b/tests/unit/components/PaceInput.spec.js
@@ -22,7 +22,15 @@ test('should be initialized to modelValue', () => {
test('should emit event when inputs are modified', async () => {
// Initialize component
- const wrapper = shallowMount(PaceInput);
+ const wrapper = shallowMount(PaceInput, {
+ propsData: {
+ modelValue: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
+ },
+ });
// Update distance value
await wrapper.findComponent({ name: 'decimal-input' }).setValue(3);
diff --git a/tests/unit/components/RaceOptions.spec.js b/tests/unit/components/RaceOptions.spec.js
@@ -20,7 +20,14 @@ test('should be initialized to modelValue', () => {
test('should emit event when inputs are modified', async () => {
// Initialize component
- const wrapper = shallowMount(RaceOptions);
+ const wrapper = shallowMount(RaceOptions, {
+ propsData: {
+ modelValue: {
+ model: 'AverageModel',
+ riegelExponent: 1.06,
+ },
+ },
+ });
// Update model
await wrapper.find('select').setValue('CameronModel');
diff --git a/tests/unit/components/TargetEditor.spec.js b/tests/unit/components/TargetEditor.spec.js
@@ -165,7 +165,14 @@ test('should correctly render workout target set with custom names', async () =>
test('revert button should emit revert event', async () => {
// Initialize component
- const wrapper = shallowMount(TargetEditor);
+ const wrapper = shallowMount(TargetEditor, {
+ propsData: {
+ modelValue: {
+ name: 'My target set',
+ targets: [],
+ },
+ },
+ });
// Click revert button
await wrapper.find('button[title="Revert target set"]').trigger('click');
@@ -178,8 +185,12 @@ test('delete button should emit revert event', async () => {
// Initialize component
const wrapper = shallowMount(TargetEditor, {
propsData: {
+ modelValue: {
+ name: 'My target set',
+ targets: [],
+ },
isCustomSet: true,
- }
+ },
});
// Click delete button
@@ -191,7 +202,14 @@ test('delete button should emit revert event', async () => {
test('close button should emit close event', async () => {
// Initialize component
- const wrapper = shallowMount(TargetEditor);
+ const wrapper = shallowMount(TargetEditor, {
+ propsData: {
+ modelValue: {
+ name: 'My target set',
+ targets: [],
+ },
+ },
+ });
// Call close method
await wrapper.find('button[title="Close"]').trigger('click');
@@ -212,7 +230,7 @@ test('add distance target button should correctly add standard imperial distance
],
},
setType: 'standard',
- defaultUnitSystem: 'imperial'
+ defaultUnitSystem: 'imperial',
},
});
@@ -244,7 +262,7 @@ test('add distance target button should correctly add standard metric distance t
],
},
setType: 'standard',
- defaultUnitSystem: 'metric'
+ defaultUnitSystem: 'metric',
},
});
@@ -275,7 +293,7 @@ test('add distance target button should correctly add split imperial distance ta
],
},
setType: 'split',
- defaultUnitSystem: 'imperial'
+ defaultUnitSystem: 'imperial',
},
});
@@ -305,7 +323,7 @@ test('add distance target button should correctly add split metric distance targ
],
},
setType: 'split',
- defaultUnitSystem: 'metric'
+ defaultUnitSystem: 'metric',
},
});
@@ -344,7 +362,7 @@ test('add distance target button should correctly add workout imperial distance
],
},
setType: 'workout',
- defaultUnitSystem: 'imperial'
+ defaultUnitSystem: 'imperial',
},
});
@@ -396,7 +414,7 @@ test('add distance target button should correctly add workout metric distance ta
],
},
setType: 'workout',
- defaultUnitSystem: 'metric'
+ defaultUnitSystem: 'metric',
},
});
@@ -497,7 +515,7 @@ test('add time target button should correctly add workout imperial time target',
],
},
setType: 'workout',
- defaultUnitSystem: 'imperial'
+ defaultUnitSystem: 'imperial',
},
});
@@ -549,7 +567,7 @@ test('add time target button should correctly add workout metric time target', a
],
},
setType: 'workout',
- defaultUnitSystem: 'metric'
+ defaultUnitSystem: 'metric',
},
});
diff --git a/tests/unit/components/TargetSetSelector.spec.js b/tests/unit/components/TargetSetSelector.spec.js
@@ -387,8 +387,10 @@ test('should sort target set after target editor is closed', async () => {
test('should correctly pass setType prop to TargetEditor', async () => {
const wrapper = shallowMount(TargetSetSelector, {
propsData: {
+ selectedTargetSet: '_new',
+ targetSets: {},
setType: 'foo'
- }
+ },
});
// Assert target editor props are correct
@@ -398,6 +400,8 @@ test('should correctly pass setType prop to TargetEditor', async () => {
test('should correctly pass customWorkoutNames prop to TargetEditor', async () => {
const wrapper = shallowMount(TargetSetSelector, {
propsData: {
+ selectedTargetSet: '_new',
+ targetSets: {},
customWorkoutNames: false,
}
});