running-tools

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

commit f769b7223707836c499faa9aecb3f791810a9e6a
parent 3c076bf99f924796a82d729bafa3f3ec9db3e928
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date:   Sat, 12 Jul 2025 13:38:33 -0700

Update storage migration logic and its e2e tests

Ensure that calculator options fields always have the selectedTargetSet
field defined.

Diffstat:
Msrc/utils/storage.ts | 34++++++++++++++++++----------------
Mtests/e2e/cross-calculator.spec.js | 264+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mtests/unit/utils/storage.spec.js | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
3 files changed, 339 insertions(+), 32 deletions(-)

diff --git a/src/utils/storage.ts b/src/utils/storage.ts @@ -1,7 +1,8 @@ -import { RacePredictionModel } from '@/utils/races'; +import { deepCopy } from '@/utils/misc'; +import { defaultRaceOptions, defaultWorkoutOptions } from '@/utils/calculators'; // The global localStorage prefix -const prefix = 'running-tools'; +const LocalStoragePrefix = 'running-tools'; /** * Read an object from a localStorage item @@ -10,7 +11,7 @@ const prefix = 'running-tools'; */ export function get<Type>(key: string): Type | null { try { - return JSON.parse(localStorage.getItem(`${prefix}.${key}`) || ''); + return JSON.parse(localStorage.getItem(`${LocalStoragePrefix}.${key}`) || ''); } catch { return null; } @@ -22,7 +23,7 @@ export function get<Type>(key: string): Type | null { * @param {Type} value The object to write */ export function set<Type>(key: string, value: Type) { - localStorage.setItem(`${prefix}.${key}`, JSON.stringify(value)); + localStorage.setItem(`${LocalStoragePrefix}.${key}`, JSON.stringify(value)); } /** @@ -30,7 +31,7 @@ export function set<Type>(key: string, value: Type) { * @param {string} key The localStorage item's key */ export function unset(key: string) { - localStorage.removeItem(`${prefix}.${key}`); + localStorage.removeItem(`${LocalStoragePrefix}.${key}`); } /** @@ -49,16 +50,17 @@ export function migrate() { // Move race-calculator-target-set into race-calculator-options (>1.4.1) const raceSelectedTargetSet = get<string>('race-calculator-target-set'); - const raceOptions = get<any>('race-calculator-options') || { - model: RacePredictionModel.AverageModel, - riegelExponent: 1.06, - selectedTargetSet: '_race_targets', - }; + const raceOptions = get<any>('race-calculator-options') + || deepCopy(defaultRaceOptions); if (raceSelectedTargetSet !== null) { raceOptions.selectedTargetSet = raceSelectedTargetSet; set('race-calculator-options', raceOptions); unset('race-calculator-target-set'); } + if (raceOptions !== null && raceOptions.selectedTargetSet === undefined) { + raceOptions.selectedTargetSet = defaultRaceOptions.selectedTargetSet; + set('race-calculator-options', raceOptions); + } // Move split-calculator-target-set into new split-calculator-options (>1.4.1) const splitSelectedTargetSet = get<string>('split-calculator-target-set'); @@ -70,17 +72,17 @@ export function migrate() { // Move workout-calculator-target-set into workout-calculator-options (>1.4.1) const workoutSelectedTargetSet = get<string>('workout-calculator-target-set'); - const workoutOptions = get<any>('workout-calculator-options') || { - customTargetNames: false, - model: RacePredictionModel.AverageModel, - riegelExponent: 1.06, - selectedTargetSet: '_workout_targets', - }; + const workoutOptions = get<any>('workout-calculator-options') + || deepCopy(defaultWorkoutOptions); if (workoutSelectedTargetSet !== null) { workoutOptions.selectedTargetSet = workoutSelectedTargetSet; set('workout-calculator-options', workoutOptions); unset('workout-calculator-target-set'); } + if (workoutOptions !== null && workoutOptions.selectedTargetSet === undefined) { + workoutOptions.selectedTargetSet = defaultWorkoutOptions.selectedTargetSet; + set('workout-calculator-options', workoutOptions); + } // Add customTargetNames property to workout-calculator-options (>1.4.1) if (workoutOptions.customTargetNames === undefined) { diff --git a/tests/e2e/cross-calculator.spec.js b/tests/e2e/cross-calculator.spec.js @@ -713,14 +713,93 @@ test('v1.4.1 Migration', async ({ page }) => { }) )); - // Reload the app and assert localStorage is updated + // Reload the app and assert general localStorage entries are correct await page.goto('/'); + expect(await page.evaluate(() => localStorage.length)).toEqual(16); + expect(await page.evaluate(() => localStorage.getItem('running-tools.default-unit-system'))) + .toEqual(JSON.stringify('metric')); + + // 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, + 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, + })); expect(await page.evaluate(() => localStorage.getItem('running-tools.pace-calculator-options'))) .toEqual(JSON.stringify({ selectedTargetSet: '123456789', })); expect(await page.evaluate(() => localStorage.getItem('running-tools.pace-calculator-target-set'))).toBeNull(); + expect(await page.evaluate(() => + localStorage.getItem('running-tools.pace-calculator-target-sets'))).toEqual(JSON.stringify({ + _pace_targets: { + name: 'Common Pace Targets', + targets: [ + { type: 'distance', distanceValue: 100, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 200, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 300, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 400, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 600, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 800, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 1000, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 1200, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 1500, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 1600, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 1, distanceUnit: 'miles' }, + { type: 'distance', distanceValue: 2, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 3, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 3200, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 2, distanceUnit: 'miles' }, + { type: 'distance', distanceValue: 4, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 3, distanceUnit: 'miles' }, + { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 6, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 8, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 5, distanceUnit: 'miles' }, + { type: 'distance', distanceValue: 6, distanceUnit: 'miles' }, + { type: 'distance', distanceValue: 10, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 8, distanceUnit: 'miles' }, + { type: 'distance', distanceValue: 10, distanceUnit: 'miles' }, + { type: 'distance', distanceValue: 0.5, distanceUnit: 'marathons' }, + { type: 'distance', distanceValue: 1, distanceUnit: 'marathons' }, + { type: 'time', time: 600 }, + { type: 'time', time: 1800 }, + { type: 'time', time: 3600 }, + ], + }, + '123456789': { + name: '800m Splits', + targets: [ + { type: 'distance', distanceValue: 0.4, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 800, distanceUnit: 'meters' }, + { type: 'time', time: 600 }, + ], + }, + })); + + // 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({ model: 'RiegelModel', @@ -729,12 +808,79 @@ test('v1.4.1 Migration', async ({ page }) => { })); expect(await page.evaluate(() => localStorage.getItem('running-tools.race-calculator-target-set'))).toBeNull(); + expect(await page.evaluate(() => + localStorage.getItem('running-tools.race-calculator-target-sets'))).toEqual(JSON.stringify({ + _race_targets: { + name: 'Common Race Targets', + targets: [ + { type: 'distance', distanceValue: 400, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 800, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 1500, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 1600, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 1, distanceUnit: 'miles' }, + { type: 'distance', distanceValue: 3000, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 3200, distanceUnit: 'meters' }, + { type: 'distance', distanceValue: 2, distanceUnit: 'miles' }, + { type: 'distance', distanceValue: 3, distanceUnit: 'miles' }, + { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 6, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 8, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 10, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 15, distanceUnit: 'kilometers' }, + { type: 'distance', distanceValue: 0.5, distanceUnit: 'marathons' }, + { type: 'distance', distanceValue: 1, distanceUnit: 'marathons' }, + ], + }, + })); + + // Assert localStorage entries for the split calculator are correct expect(await page.evaluate(() => localStorage.getItem('running-tools.split-calculator-options'))) .toEqual(JSON.stringify({ selectedTargetSet: '_split_targets', })); expect(await page.evaluate(() => + localStorage.getItem('running-tools.split-calculator-target-sets'))).toEqual(JSON.stringify({ + _split_targets: { + name: '5K 1600m Splits', + targets: [ + { type: 'distance', distanceValue: 1.6, distanceUnit: 'kilometers', splitTime: 420 }, + { type: 'distance', distanceValue: 3.2, distanceUnit: 'kilometers', splitTime: 390 }, + { type: 'distance', distanceValue: 5, distanceUnit: 'kilometers', splitTime: 390 }, + ], + }, + })); + expect(await page.evaluate(() => localStorage.getItem('running-tools.split-calculator-target-set'))).toBeNull(); + + // Assert localStorage entries for the unit calculator are correct + expect(await page.evaluate(() => localStorage.getItem('running-tools.unit-calculator-category'))) + .toEqual(JSON.stringify('speed_and_pace')); + expect(await page.evaluate(() => + localStorage.getItem('running-tools.unit-calculator-inputs'))).toEqual(JSON.stringify({ + distance: { + inputValue: 1, + inputUnit: 'miles', + outputUnit: 'kilometers', + }, + time: { + inputValue: 1, + inputUnit: 'seconds', + outputUnit: 'hh:mm:ss', + }, + speed_and_pace: { + inputValue: 10, + inputUnit: 'kilometers_per_hour', + outputUnit: 'seconds_per_mile', + }, + })); + + // 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({ model: 'VO2MaxModel', @@ -744,13 +890,119 @@ test('v1.4.1 Migration', async ({ page }) => { })); expect(await page.evaluate(() => localStorage.getItem('running-tools.workout-calculator-target-set'))).toBeNull(); + expect(await page.evaluate(() => + localStorage.getItem('running-tools.workout-calculator-target-sets'))).toEqual(JSON.stringify({ + _workout_targets: { + name: 'Common Workout Targets', + targets: [ + { + splitValue: 400, splitUnit: 'meters', + type: 'distance', distanceValue: 1, distanceUnit: 'miles', + }, + { + splitValue: 800, splitUnit: 'meters', + type: 'distance', distanceValue: 5, distanceUnit: 'kilometers', + }, + { + splitValue: 1600, splitUnit: 'meters', + type: 'time', time: 3600, + }, + { + splitValue: 1, splitUnit: 'miles', + type: 'distance', distanceValue: 1, distanceUnit: 'marathons', + }, + ], + }, + })); + + // Assert pace results are correct (inputs and options not reset) + await page.getByRole('button', { name: 'Batch Calculator' }).click(); + await expect(page.getByRole('row').nth(0).getByRole('cell').nth(0)).toHaveText('2 mi'); + await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m'); + await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(17); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:24'); + await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(17); + await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50'); + await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('2:56'); + await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(17); + await expect(page.getByRole('row')).toHaveCount(16); + + // Assert pace results are correct (inputs and options not reset, new pace targets loaded) + await page.getByLabel('Calculator').selectOption('Pace Calculator'); + await expect(page.getByRole('row').nth(0).getByRole('cell').nth(0)).toHaveText('2 mi'); + await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m'); + await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(4); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:37'); + await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(4); + await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50'); + await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:11'); + await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(4); + await expect(page.getByRole('row')).toHaveCount(16); - // Assert migrated settings are correctly initialized and/or loaded + // Assert workout results are correct (new workout options loaded) + await page.getByLabel('Calculator').selectOption('Workout Calculator'); + await expect(page.getByLabel('Target name customization')).toHaveValue('false'); + await expect(page.getByRole('row').nth(0).getByRole('cell').nth(0)).toHaveText('2 mi'); + await expect(page.getByRole('row').nth(0).getByRole('cell').nth(2)).toHaveText('800 m @ 5 km'); + await expect(page.getByRole('row').nth(0).getByRole('cell')).toHaveCount(5); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('10:30'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(2)).toHaveText('2:42'); + await expect(page.getByRole('row').nth(1).getByRole('cell')).toHaveCount(5); + await expect(page.getByRole('row').nth(15).getByRole('cell').nth(0)).toHaveText('12:50'); + await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('3:17'); + await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(5); + await expect(page.getByRole('row')).toHaveCount(16); + + // Reset selected calculator + await page.getByLabel('Calculator').selectOption('Race Calculator'); + + // Return to pace calculator + await page.getByRole('link', { name: 'Back' }).click(); await page.getByRole('button', { name: 'Pace Calculator' }).click(); - await page.getByText('Advanced Options').click(); - await expect(page.getByLabel('Selected target set')).toHaveValue('123456789'); + + // Assert paces are correct (input pace not reset) + await expect(page.getByRole('row').nth(1)).toHaveText('0.4 km' + '1:55.58'); + await expect(page.getByRole('row').nth(2)).toHaveText('800 m' + '3:51.15'); + await expect(page.getByRole('row').nth(3)).toHaveText('2.08 km' + '10:00'); + await expect(page.getByRole('row')).toHaveCount(4); + + // Return to race calculator + await page.getByRole('link', { name: 'Back' }).click(); + await page.getByRole('button', { name: 'Race Calculator' }).click(); + + // Assert race predictions are correct (input race not resset and new prediction model loaded) + await expect(page.getByRole('row').nth(5)).toHaveText('1 mi' + '5:02.17' + '3:08 / km'); + await expect(page.getByRole('row').nth(10)).toHaveText('5 km' + '16:44.87' + '3:21 / km'); + await expect(page.getByRole('row')).toHaveCount(17); + + // Return to split calculator + await page.getByRole('link', { name: 'Back' }).click(); + await page.getByRole('button', { name: 'Split Calculator' }).click(); + + // Assert times and paces are correct (split times not reset) + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(1)).toHaveText('7:00.00'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(3)).toHaveText('4:23 / km'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(1)).toHaveText('13:30.00'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(3)).toHaveText('4:04 / km'); + await expect(page.getByRole('row').nth(3).getByRole('cell').nth(1)).toHaveText('20:00.00'); + await expect(page.getByRole('row').nth(3).getByRole('cell').nth(3)).toHaveText('3:37 / km'); + await expect(page.getByRole('row')).toHaveCount(4); + + // Return to unit calculator + await page.getByRole('link', { name: 'Back' }).click(); + await page.getByRole('button', { name: 'Unit Calculator' }).click(); + + // Assert result is correct (state not reset) + await expect(page.getByLabel('Output value')).toHaveText('00:09:39.364'); + + // Return to workout calculator await page.getByRole('link', { name: 'Back' }).click(); await page.getByRole('button', { name: 'Workout Calculator' }).click(); - await page.getByText('Advanced Options').click(); - await expect(page.getByLabel('Target name customization')).toHaveValue('false'); + + // Assert workout splits are correct (input race and prediction model not reset) + await expect(page.getByRole('row').nth(1)).toHaveText('400 m @ 1 mi' + '1:14.81'); + await expect(page.getByRole('row').nth(3)).toHaveText('1600 m @ 1:00:00' + '5:53.56'); + await expect(page.getByRole('row')).toHaveCount(5); }); diff --git a/tests/unit/utils/storage.spec.js b/tests/unit/utils/storage.spec.js @@ -53,37 +53,90 @@ describe('set method', () => { }); describe('migrate method', () => { - test('should correctly migrate <=1.4.1 workout calculator options', async () => { + test('should correctly migrate <=1.4.1 calculator options', async () => { // Initialize localStorage + localStorage.setItem('running-tools.pace-calculator-target-set', '"A"'); + localStorage.setItem('running-tools.race-calculator-options', + '{"model":"RiegelModel","riegelExponent":1.07}'); + localStorage.setItem('running-tools.race-calculator-target-set', '"B"'); + localStorage.setItem('running-tools.split-calculator-target-set', '"C"'); localStorage.setItem('running-tools.workout-calculator-options', - '{"model":"PurdyPointsModel","riegelExponent":1.1}'); + '{"model":"RiegelModel","riegelExponent":1.08}'); + localStorage.setItem('running-tools.workout-calculator-target-set', '"D"'); - // Run migratinos + // Run migrations storage.migrate(); // Assert localStorage entries correctly migrated + expect(localStorage.getItem('running-tools.pace-calculator-options')).to.equal( + '{"selectedTargetSet":"A"}'); + expect(localStorage.getItem('running-tools.pace-calculator-target-set')).to.equal(null); + expect(localStorage.getItem('running-tools.race-calculator-options')).to.equal( + '{"model":"RiegelModel","riegelExponent":1.07,"selectedTargetSet":"B"}'); + expect(localStorage.getItem('running-tools.race-calculator-target-set')).to.equal(null); + expect(localStorage.getItem('running-tools.split-calculator-options')).to.equal( + '{"selectedTargetSet":"C"}'); + expect(localStorage.getItem('running-tools.split-calculator-target-set')).to.equal(null); expect(localStorage.getItem('running-tools.workout-calculator-options')).to.equal( - '{"model":"PurdyPointsModel","riegelExponent":1.1,"customTargetNames":false}'); + '{"model":"RiegelModel","riegelExponent":1.08,"selectedTargetSet":"D",' + + '"customTargetNames":false}'); + expect(localStorage.getItem('running-tools.workout-calculator-target-set')).to.equal(null); }); - test('should not modify >1.4.1 workout calculator options', async () => { + test('should correctly migrate partial <=1.4.1 calculator options', async () => { + // Initialize localStorage (*-target-set options missing) + localStorage.setItem('running-tools.race-calculator-options', + '{"model":"RiegelModel","riegelExponent":1.07}'); + localStorage.setItem('running-tools.workout-calculator-options', + '{"model":"RiegelModel","riegelExponent":1.08}'); + + // Run migrations + storage.migrate(); + + // Assert localStorage entries correctly migrated + expect(localStorage.getItem('running-tools.race-calculator-options')).to.equal( + '{"model":"RiegelModel","riegelExponent":1.07,"selectedTargetSet":"_race_targets"}'); + expect(localStorage.getItem('running-tools.workout-calculator-options')).to.equal( + '{"model":"RiegelModel","riegelExponent":1.08,"selectedTargetSet":"_workout_targets",' + + '"customTargetNames":false}'); + }); + + + test('should not modify >1.4.1 calculator options', async () => { // Initialize localStorage + localStorage.setItem('running-tools.pace-calculator-options', + '{"selectedTargetSet":"A"}'); + localStorage.setItem('running-tools.race-calculator-options', + '{"model":"RiegelModel","riegelExponent":1.07,"selectedTargetSet":"B"}'); + localStorage.setItem('running-tools.split-calculator-options', + '{"selectedTargetSet":"C"}'); localStorage.setItem('running-tools.workout-calculator-options', - '{"customTargetNames":true,"model":"PurdyPointsModel","riegelExponent":1.1}'); + '{"customTargetNames":true,"model":"PurdyPointsModel","riegelExponent":1.08,' + + '"selectedTargetSet":"D"}'); - // Run migratinos + // Run migrations storage.migrate(); // Assert localStorage entries not modified + expect(localStorage.getItem('running-tools.pace-calculator-options')).to.equal( + '{"selectedTargetSet":"A"}'); + expect(localStorage.getItem('running-tools.race-calculator-options')).to.equal( + '{"model":"RiegelModel","riegelExponent":1.07,"selectedTargetSet":"B"}'); + expect(localStorage.getItem('running-tools.split-calculator-options')).to.equal( + '{"selectedTargetSet":"C"}'); expect(localStorage.getItem('running-tools.workout-calculator-options')).to.equal( - '{"customTargetNames":true,"model":"PurdyPointsModel","riegelExponent":1.1}'); + '{"customTargetNames":true,"model":"PurdyPointsModel","riegelExponent":1.08,' + + '"selectedTargetSet":"D"}'); }); - test('should not modify missing workout calculator options', async () => { - // Run migratinos + test('should not modify missing calculator options', async () => { + // Run migrations storage.migrate(); // Assert localStorage entries not modified + expect(localStorage.getItem('running-tools.pace-calculator-options')).to.equal(null); + expect(localStorage.getItem('running-tools.race-calculator-options')).to.equal(null); + expect(localStorage.getItem('running-tools.split-calculator-options')).to.equal(null); expect(localStorage.getItem('running-tools.workout-calculator-options')).to.equal(null); }); });