commit 0ad27a6907f79aaebb3cf7a8c7d9c5e2c71a79a8
parent cd745cb3c2383acfad03df9d1d576bb3278540b9
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date: Fri, 22 Aug 2025 19:42:05 -0700
Reorganize localStorage items
Move *-calculator-input items to *-calculator-options.input. Migration
scripts and corresponding end-to-end tests not yet updated.
Diffstat:
14 files changed, 542 insertions(+), 329 deletions(-)
diff --git a/src/components/AdvancedOptionsInput.vue b/src/components/AdvancedOptionsInput.vue
@@ -25,10 +25,10 @@
</select>
</div>
- <div v-if="batchOptions && props.batchInput && props.type === Calculators.Workout"
+ <div v-if="batchOptions && props.type === Calculators.Workout"
v-show="(options as WorkoutOptions).customTargetNames">
Batch column label:
- <input v-model="batchOptions.label" :placeholder="formatDistance(props.batchInput, false)"
+ <input v-model="batchOptions.label" :placeholder="formatDistance(batchOptions.input, false)"
aria-label="Batch column label"/>
</div>
@@ -56,27 +56,21 @@
<script setup lang="ts">
import { Calculators } from '@/core/calculators';
-import type { BatchOptions, GlobalOptions, StandardOptions, RaceOptions,
+import type { BatchOptions, GlobalOptions, PaceOptions, RaceOptions, SplitOptions,
WorkoutOptions } from '@/core/calculators';
import { RacePredictionModels } from '@/core/racePrediction';
import type { TargetSets } from '@/core/targets';
import { formatDistance } from '@/core/units';
-import type { DistanceTime } from '@/core/units';
import DecimalInput from '@/components/DecimalInput.vue';
import TargetSetSelector from '@/components/TargetSetSelector.vue';
import useObjectModel from '@/composables/useObjectModel';
-type CalculatorOptions = StandardOptions | RaceOptions | WorkoutOptions;
+type CalculatorOptions = PaceOptions | RaceOptions | SplitOptions | WorkoutOptions;
const props = defineProps<{
/*
- * The batch calculator input (if applicable, used to generate custom batch label placeholder)
- */
- batchInput?: DistanceTime,
-
- /*
* The batch calculator options (if applicable)
*/
batchOptions?: BatchOptions,
diff --git a/src/core/calculators.ts b/src/core/calculators.ts
@@ -39,16 +39,20 @@ export interface GlobalOptions {
defaultUnitSystem: UnitSystems,
racePredictionOptions: RacePredictionOptions,
};
-export interface StandardOptions {
+export interface SplitOptions {
selectedTargetSet: string,
};
-export type RaceOptions = StandardOptions;
-export interface WorkoutOptions extends RaceOptions {
+export interface PaceOptions extends SplitOptions {
+ input: DistanceTime,
+};
+export type RaceOptions = PaceOptions;
+export interface WorkoutOptions extends PaceOptions {
customTargetNames: boolean,
};
export interface BatchOptions {
calculator: Calculators.Pace | Calculators.Race | Calculators.Workout,
increment: number,
+ input: DistanceTime,
label: string,
rows: number,
};
@@ -87,20 +91,24 @@ export const defaultInput: DistanceTime = {
export const defaultBatchOptions: BatchOptions = {
calculator: Calculators.Workout,
increment: 15,
+ input: defaultInput,
label: '',
rows: 20,
};
-export const defaultPaceOptions: StandardOptions = {
+export const defaultPaceOptions: PaceOptions = {
+ input: defaultInput,
selectedTargetSet: '_pace_targets',
};
export const defaultRaceOptions: RaceOptions = {
+ input: defaultInput,
selectedTargetSet: '_race_targets',
};
-export const defaultSplitOptions: StandardOptions = {
+export const defaultSplitOptions: SplitOptions = {
selectedTargetSet: '_split_targets',
};
export const defaultWorkoutOptions: WorkoutOptions = {
customTargetNames: false,
+ input: defaultInput,
selectedTargetSet: '_workout_targets',
};
diff --git a/src/views/BatchCalculator.vue b/src/views/BatchCalculator.vue
@@ -2,20 +2,20 @@
<div class="calculator">
<h2>Batch Input</h2>
<div class="input">
- <pace-input v-model="input" aria-label="Input"/>
+ <pace-input v-model="batchOptions.input" aria-label="Input"/>
</div>
<h2>Batch Options</h2>
<div class="input">
<div>
Increment:
- <time-input v-model="options.increment" label="Duration increment" :show-hours="false"/>
+ <time-input v-model="batchOptions.increment" label="Duration increment" :show-hours="false"/>
×
- <integer-input v-model="options.rows" min="1" aria-label="Number of rows"/>
+ <integer-input v-model="batchOptions.rows" min="1" aria-label="Number of rows"/>
</div>
<div>
Calculator:
- <select aria-label="Calculator" v-model="options.calculator">
+ <select aria-label="Calculator" v-model="batchOptions.calculator">
<option :value="calculators.Calculators.Pace">Pace Calculator</option>
<option :value="calculators.Calculators.Race">Race Calculator</option>
<option :value="calculators.Calculators.Workout">Workout Calculator</option>
@@ -27,9 +27,9 @@
<summary>
<h2>Advanced Options</h2>
</summary>
- <advanced-options-input :batch-input="input" v-model:batch-options="options"
+ <advanced-options-input v-model:batch-options="batchOptions"
v-model:globalOptions="globalOptions" v-model:options="calcOptions"
- v-model:targetSets="targetSets" :type="options.calculator"/>
+ v-model:targetSets="targetSets" :type="batchOptions.calculator"/>
</details>
<h2>Batch Results</h2>
@@ -44,7 +44,7 @@
import { computed } from 'vue';
import * as calculators from '@/core/calculators';
-import type { BatchOptions, GlobalOptions, RaceOptions, StandardOptions, TargetResult,
+import type { BatchOptions, GlobalOptions, PaceOptions, RaceOptions, TargetResult,
WorkoutOptions } from '@/core/calculators';
import * as targetUtils from '@/core/targets';
import { formatDistance } from '@/core/units';
@@ -59,20 +59,25 @@ import TimeInput from '@/components/TimeInput.vue';
import useStorage from '@/composables/useStorage';
/*
- * The input pace
+ * The global options
*/
-const input = useStorage<DistanceTime>('batch-calculator-input', calculators.defaultInput);
+const globalOptions = useStorage<GlobalOptions>('global-options', calculators.defaultGlobalOptions);
/*
- * The batch input options
+ * The batch calculator options
*/
-const options = useStorage<BatchOptions>('batch-calculator-options',
+const batchOptions = useStorage<BatchOptions>('batch-calculator-options',
calculators.defaultBatchOptions);
/*
- * The global options
+ * The options for each calculator
*/
-const globalOptions = useStorage<GlobalOptions>('global-options', calculators.defaultGlobalOptions);
+const paceOptions = useStorage<PaceOptions>('pace-calculator-options',
+ calculators.defaultPaceOptions);
+const raceOptions = useStorage<RaceOptions>('race-calculator-options',
+ calculators.defaultRaceOptions);
+const workoutOptions = useStorage<WorkoutOptions>('workout-calculator-options',
+ calculators.defaultWorkoutOptions);
/*
* The target sets for each calculator
@@ -85,21 +90,11 @@ const workoutTargetSets = useStorage<targetUtils.WorkoutTargetSets>(
'workout-calculator-target-sets', targetUtils.defaultWorkoutTargetSets);
/*
- * The options for each calculator
- */
-const paceOptions = useStorage<StandardOptions>('pace-calculator-options',
- calculators.defaultPaceOptions);
-const raceOptions = useStorage<RaceOptions>('race-calculator-options',
- calculators.defaultRaceOptions);
-const workoutOptions = useStorage<WorkoutOptions>('workout-calculator-options',
- calculators.defaultWorkoutOptions);
-
-/*
* The input distance
*/
const inputDistance = computed<Distance>(() => ({
- distanceValue: input.value.distanceValue,
- distanceUnit: input.value.distanceUnit,
+ distanceValue: batchOptions.value.input.distanceValue,
+ distanceUnit: batchOptions.value.input.distanceUnit,
}));
/*
@@ -107,8 +102,8 @@ const inputDistance = computed<Distance>(() => ({
*/
const inputTimes = computed<Array<number>>(() => {
const results = [];
- for (let i = 0; i < options.value.rows; i++) {
- results.push(input.value.time + options.value.increment * i);
+ for (let i = 0; i < batchOptions.value.rows; i++) {
+ results.push(batchOptions.value.input.time + batchOptions.value.increment * i);
}
return results;
});
@@ -118,7 +113,7 @@ const inputTimes = computed<Array<number>>(() => {
*/
const targetSets = computed<targetUtils.TargetSets>({
get: () => {
- switch (options.value.calculator) {
+ switch (batchOptions.value.calculator) {
case (calculators.Calculators.Pace): {
return paceTargetSets.value;
}
@@ -132,7 +127,7 @@ const targetSets = computed<targetUtils.TargetSets>({
}
},
set: (newValue: targetUtils.TargetSets) => {
- switch (options.value.calculator) {
+ switch (batchOptions.value.calculator) {
case (calculators.Calculators.Pace): {
paceTargetSets.value = newValue as targetUtils.StandardTargetSets;
break;
@@ -153,9 +148,9 @@ const targetSets = computed<targetUtils.TargetSets>({
/*
* The options for the current calculator
*/
-const calcOptions = computed<StandardOptions | RaceOptions | WorkoutOptions>({
+const calcOptions = computed<PaceOptions | RaceOptions | WorkoutOptions>({
get: () => {
- switch (options.value.calculator) {
+ switch (batchOptions.value.calculator) {
case (calculators.Calculators.Pace): {
return paceOptions.value;
}
@@ -168,10 +163,10 @@ const calcOptions = computed<StandardOptions | RaceOptions | WorkoutOptions>({
}
}
},
- set: (newValue: StandardOptions | RaceOptions | WorkoutOptions) => {
- switch(options.value.calculator) {
+ set: (newValue: PaceOptions | RaceOptions | WorkoutOptions) => {
+ switch(batchOptions.value.calculator) {
case (calculators.Calculators.Pace): {
- paceOptions.value = newValue as StandardOptions;
+ paceOptions.value = newValue as PaceOptions;
break;
}
case (calculators.Calculators.Race): {
@@ -191,7 +186,7 @@ const calcOptions = computed<StandardOptions | RaceOptions | WorkoutOptions>({
* The appropriate calculate_results function for the current calculator
*/
const calculateResult = computed<(x: DistanceTime, y: targetUtils.Target) => TargetResult>(() => {
- switch(options.value.calculator) {
+ switch(batchOptions.value.calculator) {
case (calculators.Calculators.Pace): {
return (x,y) => calculators.calculatePaceResults(x, y, globalOptions.value.defaultUnitSystem,
false);
@@ -212,11 +207,11 @@ const calculateResult = computed<(x: DistanceTime, y: targetUtils.Target) => Tar
* The label to render for the batch column
*/
const batchColumnLabel = computed<string>(() => {
- if (options.value.calculator == calculators.Calculators.Workout &&
- (calcOptions.value as WorkoutOptions).customTargetNames && options.value.label) {
- return options.value.label;
+ if (batchOptions.value.calculator == calculators.Calculators.Workout &&
+ (calcOptions.value as WorkoutOptions).customTargetNames && batchOptions.value.label) {
+ return batchOptions.value.label;
} else {
- return formatDistance(input.value, false);
+ return formatDistance(batchOptions.value.input, false);
}
});
</script>
diff --git a/src/views/PaceCalculator.vue b/src/views/PaceCalculator.vue
@@ -2,7 +2,7 @@
<div class="calculator">
<h2>Input Pace</h2>
<div class="input">
- <pace-input v-model="input"/>
+ <pace-input v-model="paceOptions.input"/>
</div>
<details>
@@ -10,24 +10,23 @@
<h2>Advanced Options</h2>
</summary>
<advanced-options-input v-model:globalOptions="globalOptions"
- v-model:options="options" v-model:targetSets="targetSets" :type="Calculators.Pace"/>
+ v-model:options="paceOptions" v-model:targetSets="targetSets" :type="Calculators.Pace"/>
</details>
<h2>Equivalent Paces</h2>
<single-output-table class="output" :calculate-result="x =>
- calculatePaceResults(input, x, globalOptions.defaultUnitSystem, true)"
- :targets="targetSets[options.selectedTargetSet] ?
- targetSets[options.selectedTargetSet].targets : []"/>
+ calculatePaceResults(paceOptions.input, x, globalOptions.defaultUnitSystem, true)"
+ :targets="targetSets[paceOptions.selectedTargetSet] ?
+ targetSets[paceOptions.selectedTargetSet].targets : []"/>
</div>
</template>
<script setup lang="ts">
-import { Calculators, calculatePaceResults, defaultGlobalOptions, defaultInput,
+import { Calculators, calculatePaceResults, defaultGlobalOptions,
defaultPaceOptions } from '@/core/calculators';
-import type { GlobalOptions, StandardOptions } from '@/core/calculators';
+import type { GlobalOptions, PaceOptions } from '@/core/calculators';
import { defaultPaceTargetSets } from '@/core/targets';
import type { StandardTargetSets } from '@/core/targets';
-import type { DistanceTime } from '@/core/units';
import AdvancedOptionsInput from '@/components/AdvancedOptionsInput.vue';
import PaceInput from '@/components/PaceInput.vue';
@@ -36,19 +35,14 @@ import SingleOutputTable from '@/components/SingleOutputTable.vue';
import useStorage from '@/composables/useStorage';
/*
- * The input pace
- */
-const input = useStorage<DistanceTime>('pace-calculator-input', defaultInput);
-
-/*
* The global options
*/
const globalOptions = useStorage<GlobalOptions>('global-options', defaultGlobalOptions);
/*
- * The current selected target set
+ * The pace calculator options
*/
-const options = useStorage<StandardOptions>('pace-calculator-options', defaultPaceOptions);
+const paceOptions = useStorage<PaceOptions>('pace-calculator-options', defaultPaceOptions);
/*
* The target sets
diff --git a/src/views/RaceCalculator.vue b/src/views/RaceCalculator.vue
@@ -2,7 +2,7 @@
<div class="calculator">
<h2>Input Race Result</h2>
<div class="input">
- <pace-input v-model="input" label="Input race"/>
+ <pace-input v-model="raceOptions.input" label="Input race"/>
</div>
<details>
@@ -27,28 +27,27 @@
<h2>Advanced Options</h2>
</summary>
<advanced-options-input v-model:globalOptions="globalOptions"
- v-model:options="options" v-model:targetSets="targetSets" :type="Calculators.Race"/>
+ v-model:options="raceOptions" v-model:targetSets="targetSets" :type="Calculators.Race"/>
</details>
<h2>Equivalent Race Results</h2>
- <single-output-table class="output" show-pace
- :calculate-result="x => calculateRaceResults(input, x, globalOptions.racePredictionOptions,
- globalOptions.defaultUnitSystem, true)"
- :targets="targetSets[options.selectedTargetSet] ?
- targetSets[options.selectedTargetSet].targets : []"/>
+ <single-output-table class="output" show-pace :calculate-result="x =>
+ calculateRaceResults(raceOptions.input, x, globalOptions.racePredictionOptions,
+ globalOptions.defaultUnitSystem, true)"
+ :targets="targetSets[raceOptions.selectedTargetSet] ?
+ targetSets[raceOptions.selectedTargetSet].targets : []"/>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
-import { Calculators, calculateRaceResults, calculateRaceStats, defaultGlobalOptions, defaultInput,
+import { Calculators, calculateRaceResults, calculateRaceStats, defaultGlobalOptions,
defaultRaceOptions } from '@/core/calculators';
import type { GlobalOptions, RaceOptions, RaceStats } from '@/core/calculators';
import { defaultRaceTargetSets } from '@/core/targets';
import type { StandardTargetSets } from '@/core/targets';
import { formatNumber } from '@/core/units';
-import type { DistanceTime } from '@/core/units';
import AdvancedOptionsInput from '@/components/AdvancedOptionsInput.vue';
import PaceInput from '@/components/PaceInput.vue';
@@ -57,11 +56,6 @@ import SingleOutputTable from '@/components/SingleOutputTable.vue';
import useStorage from '@/composables/useStorage';
/*
- * The input race
- */
-const input = useStorage<DistanceTime>('race-calculator-input', defaultInput);
-
-/*
* The global options
*/
const globalOptions = useStorage<GlobalOptions>('global-options', defaultGlobalOptions);
@@ -69,7 +63,7 @@ const globalOptions = useStorage<GlobalOptions>('global-options', defaultGlobalO
/*
* The race calculator options
*/
-const options = useStorage<RaceOptions>('race-calculator-options', defaultRaceOptions);
+const raceOptions = useStorage<RaceOptions>('race-calculator-options', defaultRaceOptions);
/*
* The race calculator target sets
@@ -80,7 +74,7 @@ const targetSets = useStorage<StandardTargetSets>('race-calculator-target-sets',
/*
* The statistics for the current input race
*/
-const raceStats = computed<RaceStats>(() => calculateRaceStats(input.value));
+const raceStats = computed<RaceStats>(() => calculateRaceStats(raceOptions.value.input));
</script>
<style scoped>
diff --git a/src/views/SplitCalculator.vue b/src/views/SplitCalculator.vue
@@ -2,7 +2,7 @@
<div class="calculator">
<div class="input">
<advanced-options-input v-model:globalOptions="globalOptions"
- v-model:options="options" v-model:targetSets="targetSets" :type="Calculators.Split"/>
+ v-model:options="splitOptions" v-model:targetSets="targetSets" :type="Calculators.Split"/>
</div>
<div class="output">
@@ -16,7 +16,7 @@
import { computed } from 'vue';
import { Calculators, defaultGlobalOptions, defaultSplitOptions } from '@/core/calculators';
-import type { GlobalOptions, StandardOptions } from '@/core/calculators';
+import type { GlobalOptions, SplitOptions } from '@/core/calculators';
import { defaultSplitTargetSets } from '@/core/targets';
import type { SplitTargetSets } from '@/core/targets';
@@ -33,7 +33,7 @@ const globalOptions = useStorage<GlobalOptions>('global-options', defaultGlobalO
/*
* The split calculator options
*/
-const options = useStorage<StandardOptions>('split-calculator-options', defaultSplitOptions);
+const splitOptions = useStorage<SplitOptions>('split-calculator-options', defaultSplitOptions);
/*
* The split calculator target sets
@@ -46,15 +46,15 @@ const targetSets = useStorage<SplitTargetSets>('split-calculator-target-sets',
*/
const targetSet = computed({
get: () => {
- if (targetSets.value[options.value.selectedTargetSet]) {
- return targetSets.value[options.value.selectedTargetSet].targets
+ if (targetSets.value[splitOptions.value.selectedTargetSet]) {
+ return targetSets.value[splitOptions.value.selectedTargetSet].targets
} else {
return []
}
},
set: (newValue) => {
- if (targetSets.value[options.value.selectedTargetSet]) {
- targetSets.value[options.value.selectedTargetSet].targets = newValue;
+ if (targetSets.value[splitOptions.value.selectedTargetSet]) {
+ targetSets.value[splitOptions.value.selectedTargetSet].targets = newValue;
}
},
});
diff --git a/src/views/WorkoutCalculator.vue b/src/views/WorkoutCalculator.vue
@@ -2,7 +2,7 @@
<div class="calculator">
<h2>Input Race Result</h2>
<div class="input">
- <pace-input v-model="input" label="Input race"/>
+ <pace-input v-model="workoutOptions.input" label="Input race"/>
</div>
<details>
@@ -10,25 +10,24 @@
<h2>Advanced Options</h2>
</summary>
<advanced-options-input v-model:globalOptions="globalOptions"
- v-model:options="options" v-model:targetSets="targetSets" :type="Calculators.Workout"/>
+ v-model:options="workoutOptions" v-model:targetSets="targetSets" :type="Calculators.Workout"/>
</details>
<h2>Workout Splits</h2>
- <single-output-table class="output"
- :calculate-result="x => calculateWorkoutResults(input, x as WorkoutTarget,
- globalOptions.racePredictionOptions, options.customTargetNames, true)"
- :targets="targetSets[options.selectedTargetSet] ?
- targetSets[options.selectedTargetSet].targets : []"/>
+ <single-output-table class="output" :calculate-result="x =>
+ calculateWorkoutResults(workoutOptions.input, x as WorkoutTarget,
+ globalOptions.racePredictionOptions, workoutOptions.customTargetNames, true)"
+ :targets="targetSets[workoutOptions.selectedTargetSet] ?
+ targetSets[workoutOptions.selectedTargetSet].targets : []"/>
</div>
</template>
<script setup lang="ts">
-import { Calculators, calculateWorkoutResults, defaultGlobalOptions, defaultInput,
+import { Calculators, calculateWorkoutResults, defaultGlobalOptions,
defaultWorkoutOptions } from '@/core/calculators';
import type { GlobalOptions, WorkoutOptions } from '@/core/calculators';
import { defaultWorkoutTargetSets } from '@/core/targets';
import type { WorkoutTarget, WorkoutTargetSets } from '@/core/targets';
-import type { DistanceTime } from '@/core/units';
import AdvancedOptionsInput from '@/components/AdvancedOptionsInput.vue';
import PaceInput from '@/components/PaceInput.vue';
@@ -37,11 +36,6 @@ import SingleOutputTable from '@/components/SingleOutputTable.vue';
import useStorage from '@/composables/useStorage';
/*
- * The input race
- */
-const input = useStorage<DistanceTime>('workout-calculator-input', defaultInput);
-
-/*
* The global options
*/
const globalOptions = useStorage<GlobalOptions>('global-options', defaultGlobalOptions);
@@ -49,7 +43,7 @@ const globalOptions = useStorage<GlobalOptions>('global-options', defaultGlobalO
/*
* The race prediction options
*/
-const options = useStorage<WorkoutOptions>('workout-calculator-options', defaultWorkoutOptions);
+const workoutOptions = useStorage<WorkoutOptions>('workout-calculator-options', defaultWorkoutOptions);
/*
* The target sets
diff --git a/tests/e2e/cross-calculator.spec.js b/tests/e2e/cross-calculator.spec.js
@@ -219,7 +219,7 @@ test('Cross-calculator', async ({ page }) => {
// Assert localStorage entries are correct
{
// Assert global localStorage entries are correct
- expect(await page.evaluate(() => localStorage.length)).toEqual(16);
+ expect(await page.evaluate(() => localStorage.length)).toEqual(12);
expect(await page.evaluate(() => localStorage.getItem('running-tools.global-options')))
.toEqual(JSON.stringify({
defaultUnitSystem: 'metric',
@@ -231,30 +231,32 @@ test('Cross-calculator', async ({ page }) => {
// Assert localStorage entries for the batch calculator are correct
expect(await page.evaluate(() =>
- localStorage.getItem('running-tools.batch-calculator-input'))).toEqual(JSON.stringify({
- distanceValue: 2,
- distanceUnit: 'miles',
- time: 630,
- }));
- expect(await page.evaluate(() =>
localStorage.getItem('running-tools.batch-calculator-options'))).toEqual(JSON.stringify({
calculator: 'race',
increment: 10,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 630,
+ },
label: '',
rows: 15,
}));
// Assert localStorage entries for the pace calculator are correct
- expect(await page.evaluate(() =>
- localStorage.getItem('running-tools.pace-calculator-input'))).toEqual(JSON.stringify({
- distanceValue: 2,
- distanceUnit: 'miles',
- time: 930,
- }));
const paceCalculatorKey = parseInt(JSON.parse(await page.evaluate(() =>
localStorage.getItem('running-tools.pace-calculator-options'))).selectedTargetSet);
expect(paceCalculatorKey - parseInt(Date.now().toString())).toBeLessThan(100000);
expect(await page.evaluate(() =>
+ localStorage.getItem('running-tools.pace-calculator-options'))).toEqual(JSON.stringify({
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 930,
+ },
+ selectedTargetSet: paceCalculatorKey.toString(),
+ }));
+ expect(await page.evaluate(() =>
localStorage.getItem('running-tools.pace-calculator-target-sets'))).toEqual(JSON.stringify({
_pace_targets: {
name: 'Common Pace Targets',
@@ -303,13 +305,12 @@ test('Cross-calculator', async ({ page }) => {
// Assert localStorage entries for the race calculator are correct
expect(await page.evaluate(() =>
- localStorage.getItem('running-tools.race-calculator-input'))).toEqual(JSON.stringify({
- distanceValue: 2,
- distanceUnit: 'miles',
- time: 630,
- }));
- expect(await page.evaluate(() =>
localStorage.getItem('running-tools.race-calculator-options'))).toEqual(JSON.stringify({
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 630,
+ },
selectedTargetSet: '_race_targets',
}));
expect(await page.evaluate(() =>
@@ -379,14 +380,13 @@ test('Cross-calculator', async ({ page }) => {
// Assert localStorage entries for the workout calculator are correct
expect(await page.evaluate(() =>
- localStorage.getItem('running-tools.workout-calculator-input'))).toEqual(JSON.stringify({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 301,
- }));
- expect(await page.evaluate(() =>
localStorage.getItem('running-tools.workout-calculator-options'))).toEqual(JSON.stringify({
customTargetNames: true,
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 301,
+ },
selectedTargetSet: '_workout_targets',
}));
expect(await page.evaluate(() =>
diff --git a/tests/unit/components/AdvancedOptionsInput.spec.js b/tests/unit/components/AdvancedOptionsInput.spec.js
@@ -14,6 +14,11 @@ test('should be correctly render pace options according to props', () => {
},
},
options: {
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: 'B',
},
targetSets: {
@@ -80,6 +85,11 @@ test('should be correctly render race options according to props', () => {
},
},
options: {
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: '_new',
},
type: 'race',
@@ -114,6 +124,11 @@ test('should render riegel exponent field only for supported race prediction mod
},
},
options: {
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: '_new',
},
type: 'race',
@@ -187,6 +202,11 @@ test('should be correctly render workout options according to props', () => {
},
options: {
customTargetNames: true,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: '_new',
},
targetSets: {},
@@ -220,9 +240,10 @@ test('should only show batch column label field when applicable', async () => {
},
options: {
customTargetNames: true,
- predictionOptions: {
- model: 'PurdyPointsModel',
- riegelExponent: 1.2,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
},
selectedTargetSet: '_new',
},
@@ -236,16 +257,16 @@ test('should only show batch column label field when applicable', async () => {
expect(wrapper.findAll('input[aria-label="Batch column label"]')).to.have
.length(0);
- // Add batchInput and batchOptions but disable workout target name customization
+ // Add batchOptions but disable workout target name customization
await wrapper.setProps({
- batchInput: { // added
- distanceValue: 2,
- distanceUnit: 'miles',
- time: 600,
- },
batchOptions: { // added
calculator: 'workout',
increment: 32,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
label: 'foo',
rows: 15,
},
@@ -258,9 +279,10 @@ test('should only show batch column label field when applicable', async () => {
},
options: {
customTargetNames: false, // disabled
- predictionOptions: {
- model: 'PurdyPointsModel',
- riegelExponent: 1.2,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
},
selectedTargetSet: '_new',
},
@@ -273,14 +295,14 @@ test('should only show batch column label field when applicable', async () => {
// Enable workout target name customization
await wrapper.setProps({
- batchInput: {
- distanceValue: 2,
- distanceUnit: 'miles',
- time: 600,
- },
batchOptions: {
calculator: 'workout',
increment: 32,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
label: 'foo',
rows: 15,
},
@@ -293,9 +315,10 @@ test('should only show batch column label field when applicable', async () => {
},
options: {
customTargetNames: true, // enabled
- predictionOptions: {
- model: 'PurdyPointsModel',
- riegelExponent: 1.2,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
},
selectedTargetSet: '_new',
},
@@ -310,14 +333,14 @@ test('should only show batch column label field when applicable', async () => {
// Switch to race calculator
await wrapper.setProps({
- batchInput: {
- distanceValue: 2,
- distanceUnit: 'miles',
- time: 600,
- },
batchOptions: {
calculator: 'workout',
increment: 32,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
label: 'foo',
rows: 15,
},
@@ -329,9 +352,10 @@ test('should only show batch column label field when applicable', async () => {
},
},
options: {
- predictionOptions: {
- model: 'PurdyPointsModel',
- riegelExponent: 1.2,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
},
selectedTargetSet: '_new',
},
@@ -357,9 +381,10 @@ test('should pass correct props to TargetSetSelector', async () => {
},
options: {
customTargetNames: false,
- predictionOptions: {
- model: 'AverageModel',
- riegelExponent: 1.06,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
},
selectedTargetSet: 'B',
},
@@ -429,6 +454,11 @@ test('should emit input events when options are modified', async () => {
},
options: {
customTargetNames: false,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: '_new',
},
targetSets: {},
@@ -506,10 +536,20 @@ test('should emit input events when options are modified', async () => {
expect(wrapper.emitted()['update:options']).to.deep.equal([
[{
customTargetNames: false,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: 'B',
}],
[{
customTargetNames: true,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: 'B',
}],
]);
diff --git a/tests/unit/views/BatchCalculator.spec.js b/tests/unit/views/BatchCalculator.spec.js
@@ -29,35 +29,16 @@ test('should load global options from localStorage', async () => {
});
});
-test('should load input from localStorage', async () => {
- // Initialize localStorage
- localStorage.setItem('running-tools.batch-calculator-input', JSON.stringify({
- distanceValue: 2,
- distanceUnit: 'miles',
- time: 600,
- }));
-
- // Initialize component
- const wrapper = shallowMount(BatchCalculator);
-
- // Assert options loaded
- expect(wrapper.findComponent({ name: 'pace-input' }).vm.modelValue).to.deep.equal({
- distanceValue: 2,
- distanceUnit: 'miles',
- time: 600,
- });
- expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.batchInput).to.deep.equal({
- distanceValue: 2,
- distanceUnit: 'miles',
- time: 600,
- });
-});
-
test('should load batch options from localStorage', async () => {
// Initialize localStorage
localStorage.setItem('running-tools.batch-calculator-options', JSON.stringify({
calculator: 'race',
increment: 32,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
label: 'foo',
rows: 15,
}));
@@ -67,10 +48,20 @@ test('should load batch options from localStorage', async () => {
// Assert options loaded
expect(wrapper.find('select[aria-label="Calculator"]').element.value).to.equal('race');
+ expect(wrapper.findComponent({ name: 'pace-input' }).vm.modelValue).to.deep.equal({
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ });
expect(wrapper.findComponent({ name: 'time-input' }).vm.modelValue).to.equal(32);
expect(wrapper.findComponent({ name: 'integer-input' }).vm.modelValue).to.equal(15);
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.batchOptions).to.deep.equal({
calculator: 'race',
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
increment: 32,
label: 'foo',
rows: 15,
@@ -130,13 +121,28 @@ test('should load calculator options from localStorage', async () => {
}
}));
localStorage.setItem('running-tools.pace-calculator-options', JSON.stringify({
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 300,
+ },
selectedTargetSet: 'A',
}));
localStorage.setItem('running-tools.race-calculator-options', JSON.stringify({
+ input: {
+ distanceValue: 1.1,
+ distanceUnit: 'miles',
+ time: 310,
+ },
selectedTargetSet: 'C',
}));
localStorage.setItem('running-tools.workout-calculator-options', JSON.stringify({
customTargetNames: true,
+ input: {
+ distanceValue: 1.2,
+ distanceUnit: 'miles',
+ time: 320,
+ },
selectedTargetSet: 'E',
}));
@@ -146,6 +152,11 @@ test('should load calculator options from localStorage', async () => {
// Assert pace calculator options are loaded
await wrapper.find('select[aria-label="Calculator"]').setValue('pace');
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.options).to.deep.equal({
+ input: {
+ distanceValue: 1.0,
+ distanceUnit: 'miles',
+ time: 300,
+ },
selectedTargetSet: 'A',
});
expect(wrapper.findComponent({ name: 'double-output-table' }).vm.targets)
@@ -154,6 +165,11 @@ test('should load calculator options from localStorage', async () => {
// Assert race calculator options are loaded
await wrapper.find('select[aria-label="Calculator"]').setValue('race');
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.options).to.deep.equal({
+ input: {
+ distanceValue: 1.1,
+ distanceUnit: 'miles',
+ time: 310,
+ },
selectedTargetSet: 'C',
});
expect(wrapper.findComponent({ name: 'double-output-table' }).vm.targets)
@@ -163,6 +179,11 @@ test('should load calculator options from localStorage', async () => {
await wrapper.find('select[aria-label="Calculator"]').setValue('workout');
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.options).to.deep.equal({
customTargetNames: true,
+ input: {
+ distanceValue: 1.2,
+ distanceUnit: 'miles',
+ time: 320,
+ },
selectedTargetSet: 'E',
});
expect(wrapper.findComponent({ name: 'double-output-table' }).vm.targets)
@@ -195,7 +216,7 @@ test('should save global options to localStorage when modified', async () => {
}));
});
-test('should save input to localStorage when modified', async () => {
+test('should save batch options to localStorage when modified', async () => {
// Initialize component
const wrapper = shallowMount(BatchCalculator);
@@ -206,17 +227,18 @@ test('should save input to localStorage when modified', async () => {
time: 600,
});
- // Assert input saved
- expect(localStorage.getItem('running-tools.batch-calculator-input')).to.equal(JSON.stringify({
- distanceValue: 2,
- distanceUnit: 'miles',
- time: 600,
+ // Assert options saved
+ expect(localStorage.getItem('running-tools.batch-calculator-options')).to.equal(JSON.stringify({
+ calculator: 'workout',
+ increment: 15,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
+ label: '',
+ rows: 20,
}));
-});
-
-test('should save batch options to localStorage when modified', async () => {
- // Initialize component
- const wrapper = shallowMount(BatchCalculator);
// Update increment value
await wrapper.findComponent({ name: 'time-input' }).setValue(32);
@@ -225,6 +247,11 @@ test('should save batch options to localStorage when modified', async () => {
expect(localStorage.getItem('running-tools.batch-calculator-options')).to.equal(JSON.stringify({
calculator: 'workout',
increment: 32,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
label: '',
rows: 20,
}));
@@ -236,6 +263,11 @@ test('should save batch options to localStorage when modified', async () => {
expect(localStorage.getItem('running-tools.batch-calculator-options')).to.equal(JSON.stringify({
calculator: 'workout',
increment: 32,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
label: '',
rows: 15,
}));
@@ -244,6 +276,11 @@ test('should save batch options to localStorage when modified', async () => {
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
calculator: 'workout',
increment: 32,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
label: 'foo',
rows: 15,
}, 'batch-options');
@@ -252,6 +289,11 @@ test('should save batch options to localStorage when modified', async () => {
expect(localStorage.getItem('running-tools.batch-calculator-options')).to.equal(JSON.stringify({
calculator: 'workout',
increment: 32,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
label: 'foo',
rows: 15,
}));
@@ -263,6 +305,11 @@ test('should save batch options to localStorage when modified', async () => {
expect(localStorage.getItem('running-tools.batch-calculator-options')).to.equal(JSON.stringify({
calculator: 'race',
increment: 32,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
label: 'foo',
rows: 15,
}));
@@ -303,6 +350,11 @@ test('should save calculator options to localStorage when modified', async () =>
}
}));
localStorage.setItem('running-tools.pace-calculator-options', JSON.stringify({
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 300,
+ },
selectedTargetSet: 'B',
}));
localStorage.setItem('running-tools.race-calculator-target-sets', JSON.stringify({
@@ -315,6 +367,11 @@ test('should save calculator options to localStorage when modified', async () =>
}
}));
localStorage.setItem('running-tools.race-calculator-options', JSON.stringify({
+ input: {
+ distanceValue: 1.1,
+ distanceUnit: 'miles',
+ time: 310,
+ },
selectedTargetSet: 'D',
}));
localStorage.setItem('running-tools.workout-calculator-target-sets', JSON.stringify({
@@ -328,6 +385,11 @@ test('should save calculator options to localStorage when modified', async () =>
}));
localStorage.setItem('running-tools.workout-calculator-options', JSON.stringify({
customWorkoutNames: false,
+ input: {
+ distanceValue: 1.2,
+ distanceUnit: 'miles',
+ time: 320,
+ },
selectedTargetSet: 'F',
}));
@@ -337,6 +399,11 @@ test('should save calculator options to localStorage when modified', async () =>
// Update pace calculator options X
await wrapper.find('select[aria-label="Calculator"]').setValue('pace');
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
+ input: {
+ distanceValue: 1.0,
+ distanceUnit: 'miles',
+ time: 300,
+ },
selectedTargetSet: 'A',
}, 'options');
expect(wrapper.findComponent({ name: 'double-output-table' }).vm.targets)
@@ -345,6 +412,11 @@ test('should save calculator options to localStorage when modified', async () =>
// Update race calculator options
await wrapper.find('select[aria-label="Calculator"]').setValue('race');
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
+ input: {
+ distanceValue: 1.1,
+ distanceUnit: 'miles',
+ time: 310,
+ },
selectedTargetSet: 'C',
}, 'options');
expect(wrapper.findComponent({ name: 'double-output-table' }).vm.targets)
@@ -354,6 +426,11 @@ test('should save calculator options to localStorage when modified', async () =>
await wrapper.find('select[aria-label="Calculator"]').setValue('workout');
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
customTargetNames: true,
+ input: {
+ distanceValue: 1.2,
+ distanceUnit: 'miles',
+ time: 320,
+ },
selectedTargetSet: 'E',
}, 'options');
expect(wrapper.findComponent({ name: 'double-output-table' }).vm.targets)
@@ -361,13 +438,28 @@ test('should save calculator options to localStorage when modified', async () =>
// Assert options saved to localStorage
expect(localStorage.getItem('running-tools.pace-calculator-options')).to.equal(JSON.stringify({
+ input: {
+ distanceValue: 1.0,
+ distanceUnit: 'miles',
+ time: 300,
+ },
selectedTargetSet: 'A',
}));
expect(localStorage.getItem('running-tools.race-calculator-options')).to.equal(JSON.stringify({
+ input: {
+ distanceValue: 1.1,
+ distanceUnit: 'miles',
+ time: 310,
+ },
selectedTargetSet: 'C',
}));
expect(localStorage.getItem('running-tools.workout-calculator-options')).to.equal(JSON.stringify({
customTargetNames: true,
+ input: {
+ distanceValue: 1.2,
+ distanceUnit: 'miles',
+ time: 320,
+ },
selectedTargetSet: 'E',
}));
});
@@ -436,6 +528,11 @@ test('should pass correct input props to DoubleOutputTable', async () => {
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
calculator: 'workout',
increment: 10,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
label: 'foo',
rows: 15,
}, 'batchOptions');
@@ -453,6 +550,11 @@ test('should pass correct input props to DoubleOutputTable', async () => {
// Enable target name customization
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
customTargetNames: true,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: '_workout_targets',
}, 'options');
@@ -494,14 +596,14 @@ test('should correctly set AdvancedOptionsInput props', async () => {
await wrapper.findComponent({ name: 'integer-input' }).setValue(15);
// Assert batch props are correct
- expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.batchInput).to.deep.equal({
- distanceValue: 2,
- distanceUnit: 'miles',
- time: 600,
- });
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.batchOptions).to.deep.equal({
calculator: 'workout',
increment: 32,
+ input: {
+ distanceValue: 2,
+ distanceUnit: 'miles',
+ time: 600,
+ },
label: '',
rows: 15,
});
@@ -517,6 +619,11 @@ test('should correctly set AdvancedOptionsInput props', async () => {
},
});
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.options).to.deep.equal({
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: '_pace_targets',
});
@@ -531,6 +638,11 @@ test('should correctly set AdvancedOptionsInput props', async () => {
},
});
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.options).to.deep.equal({
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: '_race_targets',
});
@@ -546,6 +658,11 @@ test('should correctly set AdvancedOptionsInput props', async () => {
});
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.options).to.deep.equal({
customTargetNames: false,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: '_workout_targets',
});
});
@@ -560,10 +677,20 @@ test('should correctly calculate outputs', async () => {
},
}));
localStorage.setItem('running-tools.race-calculator-options', JSON.stringify({
+ input: {
+ distanceValue: 1.1,
+ distanceUnit: 'miles',
+ time: 310,
+ },
selectedTargetSet: '_race_targets',
}));
localStorage.setItem('running-tools.workout-calculator-options', JSON.stringify({
customTargetNames: false,
+ input: {
+ distanceValue: 1.2,
+ distanceUnit: 'miles',
+ time: 320,
+ },
selectedTargetSet: '_workout_targets',
}));
diff --git a/tests/unit/views/PaceCalculator.spec.js b/tests/unit/views/PaceCalculator.spec.js
@@ -25,26 +25,7 @@ test('should load global options from localStorage', async () => {
.defaultUnitSystem).to.equal('imperial');
});
-test('should load input pace from localStorage', async () => {
- // Initialize localStorage
- localStorage.setItem('running-tools.pace-calculator-input', JSON.stringify({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 600,
- }));
-
- // Initialize component
- const wrapper = shallowMount(PaceCalculator);
-
- // Assert data loaded
- expect(wrapper.findComponent({ name: 'pace-input' }).vm.modelValue).to.deep.equal({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 600,
- });
-});
-
-test('should load local options and target sets from localStorage', async () => {
+test('should load pace options and target sets from localStorage', async () => {
// Initialize localStorage
const targetSets = {
'_pace_targets': {
@@ -66,6 +47,11 @@ test('should load local options and target sets from localStorage', async () =>
};
localStorage.setItem('running-tools.pace-calculator-target-sets', JSON.stringify(targetSets));
localStorage.setItem('running-tools.pace-calculator-options', JSON.stringify({
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
selectedTargetSet: 'B',
}));
@@ -73,7 +59,17 @@ test('should load local options and target sets from localStorage', async () =>
const wrapper = shallowMount(PaceCalculator);
// Assert selection is loaded
+ expect(wrapper.findComponent({ name: 'pace-input' }).vm.modelValue).to.deep.equal({
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ });
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.options).to.deep.equal({
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
selectedTargetSet: 'B',
});
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.targetSets)
@@ -105,26 +101,7 @@ test('should save global options to localStorage when modified', async () => {
}));
});
-test('should save input pace to localStorage', async () => {
- // Initialize component
- const wrapper = shallowMount(PaceCalculator);
-
- // Enter input pace data
- await wrapper.findComponent({ name: 'pace-input' }).setValue({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 600,
- });
-
- // Assert data saved to localStorage
- expect(localStorage.getItem('running-tools.pace-calculator-input')).to.equal(JSON.stringify({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 600,
- }));
-});
-
-test('should save local options and target sets to localStorage when modified', async () => {
+test('should save pace options and target sets to localStorage when modified', async () => {
const targetSets = {
'_pace_targets': {
name: 'Pace targets #1',
@@ -147,10 +124,32 @@ test('should save local options and target sets to localStorage when modified',
// Initialize component
const wrapper = shallowMount(PaceCalculator);
+ // Update input pace
+ await wrapper.findComponent({ name: 'pace-input' }).setValue({
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ });
+
+ // New input pace should be saved to localStorage
+ expect(localStorage.getItem('running-tools.pace-calculator-options')).to.equal(JSON.stringify({
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
+ selectedTargetSet: '_pace_targets',
+ }));
+
// Update target sets and selected target set
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue(targetSets,
'targetSets');
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
selectedTargetSet: 'B',
}, 'options');
@@ -158,6 +157,11 @@ test('should save local options and target sets to localStorage when modified',
expect(localStorage.getItem('running-tools.pace-calculator-target-sets'))
.to.equal(JSON.stringify(targetSets));
expect(localStorage.getItem('running-tools.pace-calculator-options')).to.equal(JSON.stringify({
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
selectedTargetSet: 'B',
}));
});
@@ -245,15 +249,27 @@ test('should correctly handle null target set', async () => {
const wrapper = shallowMount(PaceCalculator);
// Switch to invalid target set
- await wrapper.findComponent({ name: 'advanced-options-input' })
- .setValue({ selectedTargetSet: 'does_not_exist' }, 'options');
+ await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
+ selectedTargetSet: 'does_not_exist'
+ }, 'options');
// Assert empty array passed to SingleOutputTable component
expect(wrapper.findComponent({ name: 'single-output-table' }).vm.targets).to.deep.equal([]);
// Switch to valid target set
- await wrapper.findComponent({ name: 'advanced-options-input' })
- .setValue({ selectedTargetSet: '_pace_targets' }, 'options');
+ await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
+ selectedTargetSet: '_pace_targets'
+ }, 'options');
// Assert valid targets passed to SingleOutputTable component
const paceTargets = defaultTargetSets._pace_targets.targets;
diff --git a/tests/unit/views/RaceCalculator.spec.js b/tests/unit/views/RaceCalculator.spec.js
@@ -30,26 +30,7 @@ test('should load global options from localStorage', async () => {
});
});
-test('should load input race from localStorage', async () => {
- // Initialize localStorage
- localStorage.setItem('running-tools.race-calculator-input', JSON.stringify({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 600,
- }));
-
- // Initialize component
- const wrapper = shallowMount(RaceCalculator);
-
- // Assert data loaded
- expect(wrapper.findComponent({ name: 'pace-input' }).vm.modelValue).to.deep.equal({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 600,
- });
-});
-
-test('should load local options and target sets from localStorage', async () => {
+test('should load race options and target sets from localStorage', async () => {
// Initialize localStorage
const targetSets = {
'_race_targets': {
@@ -71,6 +52,11 @@ test('should load local options and target sets from localStorage', async () =>
};
localStorage.setItem('running-tools.race-calculator-target-sets', JSON.stringify(targetSets));
localStorage.setItem('running-tools.race-calculator-options', JSON.stringify({
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
selectedTargetSet: 'B',
}));
@@ -78,7 +64,17 @@ test('should load local options and target sets from localStorage', async () =>
const wrapper = shallowMount(RaceCalculator);
// Assert data loaded
+ expect(wrapper.findComponent({ name: 'pace-input' }).vm.modelValue).to.deep.equal({
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ });
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.options).to.deep.equal({
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
selectedTargetSet: 'B',
});
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.targetSets)
@@ -110,25 +106,6 @@ test('should save global options to localStorage when modified', async () => {
}));
});
-test('should save input race to localStorage', async () => {
- // Initialize component
- const wrapper = shallowMount(RaceCalculator);
-
- // Enter input race data
- await wrapper.findComponent({ name: 'pace-input' }).setValue({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 600,
- });
-
- // Assert data saved to localStorage
- expect(localStorage.getItem('running-tools.race-calculator-input')).to.equal(JSON.stringify({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 600,
- }));
-});
-
test('should save local options and target sets to localStorage when modified', async () => {
const targetSets = {
'_race_targets': {
@@ -152,10 +129,32 @@ test('should save local options and target sets to localStorage when modified',
// Initialize component
const wrapper = shallowMount(RaceCalculator);
+ // Update input race
+ await wrapper.findComponent({ name: 'pace-input' }).setValue({
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ });
+
+ // Assert data saved to localStorage
+ expect(localStorage.getItem('running-tools.race-calculator-options')).to.equal(JSON.stringify({
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
+ selectedTargetSet: '_race_targets',
+ }));
+
// Update target sets and selected target set
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue(targetSets,
'targetSets');
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
selectedTargetSet: 'B',
}, 'options');
@@ -163,6 +162,11 @@ test('should save local options and target sets to localStorage when modified',
expect(localStorage.getItem('running-tools.race-calculator-target-sets'))
.to.equal(JSON.stringify(targetSets));
expect(localStorage.getItem('running-tools.race-calculator-options')).to.equal(JSON.stringify({
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
selectedTargetSet: 'B',
}));
});
@@ -208,6 +212,11 @@ test('should correctly handle null target set', async () => {
// Switch to invalid target set
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: 'does_not_exist',
}, 'options');
@@ -216,6 +225,11 @@ test('should correctly handle null target set', async () => {
// Switch to valid target set
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: '_race_targets',
}, 'options');
diff --git a/tests/unit/views/SplitCalculator.spec.js b/tests/unit/views/SplitCalculator.spec.js
@@ -26,7 +26,7 @@ test('should load global options from localStorage', async () => {
.to.equal('imperial');
});
-test('should load local options and target sets from localStorage', async () => {
+test('should load split options and target sets from localStorage', async () => {
// Initialize localStorage
const targetSets = {
'_split_targets': {
@@ -105,7 +105,7 @@ test('should save global options to localStorage when modified', async () => {
}));
});
-test('should save local options and target sets to localStorage when modified', async () => {
+test('should save split options and target sets to localStorage when modified', async () => {
const targetSets1 = {
'_split_targets': {
name: 'Split targets',
diff --git a/tests/unit/views/WorkoutCalculator.spec.js b/tests/unit/views/WorkoutCalculator.spec.js
@@ -30,26 +30,7 @@ test('should load global options from localStorage', async () => {
});
});
-test('should load input race from localStorage', async () => {
- // Initialize localStorage
- localStorage.setItem('running-tools.workout-calculator-input', JSON.stringify({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 600,
- }));
-
- // Initialize component
- const wrapper = shallowMount(WorkoutCalculator);
-
- // Assert data loaded
- expect(wrapper.findComponent({ name: 'pace-input' }).vm.modelValue).to.deep.equal({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 600,
- });
-});
-
-test('should load local options and target sets from localStorage', async () => {
+test('should load workout options and target sets from localStorage', async () => {
// Initialize localStorage
const targetSets = {
'_workout_targets': {
@@ -97,6 +78,11 @@ test('should load local options and target sets from localStorage', async () =>
localStorage.setItem('running-tools.workout-calculator-target-sets', JSON.stringify(targetSets));
localStorage.setItem('running-tools.workout-calculator-options', JSON.stringify({
customTargetNames: true,
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
selectedTargetSet: 'B',
}));
@@ -106,6 +92,11 @@ test('should load local options and target sets from localStorage', async () =>
// Assert data loaded
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.options).to.deep.equal({
customTargetNames: true,
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
selectedTargetSet: 'B',
});
expect(wrapper.findComponent({ name: 'advanced-options-input' }).vm.targetSets)
@@ -137,26 +128,7 @@ test('should save global options to localStorage when modified', async () => {
}));
});
-test('should save input race to localStorage', async () => {
- // Initialize component
- const wrapper = shallowMount(WorkoutCalculator);
-
- // Enter input race data
- await wrapper.findComponent({ name: 'pace-input' }).setValue({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 600,
- });
-
- // Assert data saved to localStorage
- expect(localStorage.getItem('running-tools.workout-calculator-input')).to.equal(JSON.stringify({
- distanceValue: 1,
- distanceUnit: 'miles',
- time: 600,
- }));
-});
-
-test('should save local options and target sets to localStorage when modified', async () => {
+test('should save workout options and target sets to localStorage when modified', async () => {
const targetSets = {
'_workout_targets': {
name: 'Workout targets #1',
@@ -204,11 +176,56 @@ test('should save local options and target sets to localStorage when modified',
// Initialize component
const wrapper = shallowMount(WorkoutCalculator);
- // Update target sets, selected target set, and target name customization
+ // Update input race
+ await wrapper.findComponent({ name: 'pace-input' }).setValue({
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ });
+
+ // Assert data saved to localStorage
+ expect(localStorage.getItem('running-tools.workout-calculator-options')).to.equal(JSON.stringify({
+ customTargetNames: false,
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
+ selectedTargetSet: '_workout_targets',
+ }));
+
+ // Update target name customization
+ await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
+ customTargetNames: true,
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
+ selectedTargetSet: '_workout_targets',
+ }, 'options');
+
+ // Assert data saved to localStorage
+ expect(localStorage.getItem('running-tools.workout-calculator-options')).to.equal(JSON.stringify({
+ customTargetNames: true,
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
+ selectedTargetSet: '_workout_targets',
+ }));
+
+ // Update target sets and selected target set
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue(targetSets,
'targetSets');
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
customTargetNames: true,
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
selectedTargetSet: 'B',
}, 'options');
@@ -217,6 +234,11 @@ test('should save local options and target sets to localStorage when modified',
.to.equal(JSON.stringify(targetSets));
expect(localStorage.getItem('running-tools.workout-calculator-options')).to.equal(JSON.stringify({
customTargetNames: true,
+ input: {
+ distanceValue: 1,
+ distanceUnit: 'miles',
+ time: 600,
+ },
selectedTargetSet: 'B',
}));
});
@@ -253,6 +275,11 @@ test('should correctly handle null target set', async () => {
// Switch to invalid target set
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
customTargetNames: false,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: 'does_not_exist',
}, 'options');
@@ -262,6 +289,11 @@ test('should correctly handle null target set', async () => {
// Switch to valid target set
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
customTargetNames: false,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: '_workout_targets',
}, 'options');
@@ -306,6 +338,11 @@ test('should correctly calculate results according to options', async () => {
// Update target name customization
await wrapper.findComponent({ name: 'advanced-options-input' }).setValue({
customTargetNames: true,
+ input: {
+ distanceValue: 5,
+ distanceUnit: 'kilometers',
+ time: 1200,
+ },
selectedTargetSet: '_workout_targets',
}, 'options');