running-tools

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

commit 812bd6e41ecc3c837558f70d5e56c2996c8d3178
parent fb265046ad1b05575d47e7f48beffe44c8ec8182
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date:   Tue,  9 Jul 2024 19:32:42 -0700

Refactor e2e tests

Diffstat:
Mtests/e2e/batch-calculator.spec.js | 77++++++++++++++++++++++++-----------------------------------------------------
Mtests/e2e/cross-calculator.spec.js | 2+-
Mtests/e2e/pace-calculator.spec.js | 88++++++++++++++++++++++++-------------------------------------------------------
Mtests/e2e/race-calculator.spec.js | 109++++++++++++++++++++++++-------------------------------------------------------
Mtests/e2e/split-calculator.spec.js | 152++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Mtests/e2e/unit-calculator.spec.js | 43++++++++++---------------------------------
Mtests/e2e/workout-calculator.spec.js | 100+++++++++++++++++++++++--------------------------------------------------------
7 files changed, 212 insertions(+), 359 deletions(-)

diff --git a/tests/e2e/batch-calculator.spec.js b/tests/e2e/batch-calculator.spec.js @@ -1,6 +1,15 @@ import { test, expect } from '@playwright/test'; -test('Basic usage', async ({ page }) => { +test('Batch calculator', async ({ page }) => { + // Structure: + // - Test workout batch results, including modified prediction model + // - Test pace batch results, including modified default units + // - Test race batch results, including modified Riegel exponent + // - Reload page + // - Assert race batch results are still the same + // - Assert pace batch results are still the same + // - Assert workout batch results are still the same + await page.goto('/'); // Go to batch calculator @@ -117,40 +126,6 @@ test('Basic usage', async ({ page }) => { await expect(page.getByRole('row').nth(15).getByRole('cell').nth(2)).toHaveText('2:40.09'); await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(17); await expect(page.getByRole('row')).toHaveCount(16); -}); - -test('Save settings across page reloads', async ({ page }) => { - // Go to batch calculator - await page.goto('/'); - await page.getByRole('button', { name: 'Batch Calculator' }).click(); - - // Enter input pace (2 mi in 10:30) - await page.getByLabel('Input distance value').fill('2'); - await page.getByLabel('Input distance unit').selectOption('Miles'); - await page.getByLabel('Input duration hours').fill('0'); - await page.getByLabel('Input duration minutes').fill('10'); - await page.getByLabel('Input duration seconds').fill('30'); - - // Enter batch options (15 x 10s increments) - await page.getByLabel('Duration increment minutes').fill('0'); - await page.getByLabel('Duration increment seconds').fill('10'); - await page.getByLabel('Number of rows').fill('15'); - - // Change workout prediction model - await page.getByText('Advanced Options').click(); - await page.getByLabel('Prediction model').selectOption('Riegel\'s Model'); - - // Change calculator - await page.getByLabel('Calculator').selectOption('Pace Calculator'); - - // Change default units - await page.getByLabel('Default units').selectOption('Kilometers'); - - // Change calculator - await page.getByLabel('Calculator').selectOption('Race Calculator'); - - // Change Riegel exponent - await page.getByLabel('Riegel Exponent').fill('1.12'); // Reload page await page.reload(); @@ -167,25 +142,8 @@ test('Save settings across page reloads', async ({ page }) => { await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(17); await expect(page.getByRole('row')).toHaveCount(16); - // Change calculator - await page.getByLabel('Calculator').selectOption('Workout Calculator'); - - // Assert workout results are correct - 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:40.78'); - 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:16.51'); - await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(5); - await expect(page.getByRole('row')).toHaveCount(16); - - // Change calculator + // Assert pace results are correct (inputs and options not reset) await page.getByLabel('Calculator').selectOption('Pace Calculator'); - - // Assert pace results are correct await expect(page.getByRole('row').nth(0).getByRole('cell').nth(0)).toHaveText('2 mi'); await expect(page.getByRole('row').nth(0).getByRole('cell').nth(6)).toHaveText('800 m'); await expect(page.getByRole('row').nth(0).getByRole('cell').nth(28)).toHaveText('10:00'); @@ -199,4 +157,17 @@ test('Save settings across page reloads', async ({ page }) => { await expect(page.getByRole('row').nth(15).getByRole('cell').nth(28)).toHaveText('2.51 km'); await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(31); await expect(page.getByRole('row')).toHaveCount(16); + + // Assert workout results are correct (inputs and options not reset) + await page.getByLabel('Calculator').selectOption('Workout 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 @ 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:40.78'); + 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:16.51'); + await expect(page.getByRole('row').nth(15).getByRole('cell')).toHaveCount(5); + await expect(page.getByRole('row')).toHaveCount(16); }); diff --git a/tests/e2e/cross-calculator.spec.js b/tests/e2e/cross-calculator.spec.js @@ -1,6 +1,6 @@ import { test, expect } from '@playwright/test'; -test('Save and update state when navigating between calculators', async ({ page }) => { +test('Cross-calculator', async ({ page }) => { // Go to batch calculator await page.goto('/'); await page.getByRole('button', { name: 'Batch Calculator' }).click(); diff --git a/tests/e2e/pace-calculator.spec.js b/tests/e2e/pace-calculator.spec.js @@ -1,9 +1,17 @@ import { test, expect } from '@playwright/test'; -test('Basic usage', async ({ page }) => { - await page.goto('/'); +test('Pace Calculator', async ({ page }) => { + // Structure: + // - Test standard pace results + // - Test different default units + // - Test modified default target set + // - Test custom target set + // - Reload page + // - Assert outputs are still the same + // - Test target set deletion and reversion // Go to pace calculator + await page.goto('/'); await page.getByRole('button', { name: 'Pace Calculator' }).click(); await expect(page).toHaveTitle('Pace Calculator - Running Tools'); @@ -27,22 +35,8 @@ test('Basic usage', async ({ page }) => { await expect(page.getByRole('row').nth(11)).toHaveText('1 mi' + '7:45.00'); await expect(page.getByRole('row').nth(13)).toHaveText('2.08 km' + '10:00'); await expect(page.getByRole('row')).toHaveCount(31); -}); - -test('Customize target sets', async ({ page }) => { - // Go to pace calculator - await page.goto('/'); - await page.getByRole('button', { name: 'Pace Calculator' }).click(); - - // Enter input pace (2 mi in 15:30) - await page.getByLabel('Input distance value').fill('2'); - await page.getByLabel('Input distance unit').selectOption('Miles'); - await page.getByLabel('Input duration hours').fill('0'); - await page.getByLabel('Input duration minutes').fill('15'); - await page.getByLabel('Input duration seconds').fill('30'); // Edit default target set - await page.getByText('Advanced Options').click(); await page.getByRole('button', { name: 'Edit target set' }).click(); await page.getByLabel('Target set label').fill('Less-common Pace Targets'); await page.getByLabel('Target distance value').nth(10).fill('1.01'); @@ -58,9 +52,9 @@ test('Customize target sets', async ({ page }) => { // Assert paces are correct await expect(page.getByRole('row').nth(11)).toHaveText('1.01 mi' + '7:49.65'); - await expect(page.getByRole('row').nth(13)).toHaveText('1.29 mi' + '10:01'); + await expect(page.getByRole('row').nth(13)).toHaveText('2.08 km' + '10:01'); await expect(page.getByRole('row').nth(14)).toHaveText('1.5 mi' + '11:37.50'); - await expect(page.getByRole('row').nth(18)).toHaveText('2.45 mi' + '19:00'); + await expect(page.getByRole('row').nth(18)).toHaveText('3.95 km' + '19:00'); await expect(page.getByRole('row')).toHaveCount(33); // Create custom target set @@ -85,14 +79,23 @@ test('Customize target sets', async ({ page }) => { await expect(page.getByRole('row').nth(2)).toHaveText('800 m' + '3:51.15'); await expect(page.getByRole('row')).toHaveCount(3); + // Reload page + await page.reload(); + + // Assert paces are correct (custom targets and default units not reset) + await expect(page.getByRole('row').nth(1)).toHaveText('0.4 km' + '1:55.57'); + await expect(page.getByRole('row').nth(2)).toHaveText('800 m' + '3:51.15'); + await expect(page.getByRole('row')).toHaveCount(3); + // Switch target set + await page.getByText('Advanced Options').click(); await page.getByLabel('Selected target set').selectOption('Less-common Pace Targets'); // Assert paces are correct await expect(page.getByRole('row').nth(11)).toHaveText('1.01 mi' + '7:49.65'); - await expect(page.getByRole('row').nth(13)).toHaveText('1.29 mi' + '10:01'); + await expect(page.getByRole('row').nth(13)).toHaveText('2.08 km' + '10:01'); await expect(page.getByRole('row').nth(14)).toHaveText('1.5 mi' + '11:37.50'); - await expect(page.getByRole('row').nth(18)).toHaveText('2.45 mi' + '19:00'); + await expect(page.getByRole('row').nth(18)).toHaveText('3.95 km' + '19:00'); await expect(page.getByRole('row')).toHaveCount(33); // Delete custom target set @@ -103,9 +106,9 @@ test('Customize target sets', async ({ page }) => { // Assert paces are correct (back to default target set) await expect(page.getByRole('row').nth(11)).toHaveText('1.01 mi' + '7:49.65'); - await expect(page.getByRole('row').nth(13)).toHaveText('1.29 mi' + '10:01'); + await expect(page.getByRole('row').nth(13)).toHaveText('2.08 km' + '10:01'); await expect(page.getByRole('row').nth(14)).toHaveText('1.5 mi' + '11:37.50'); - await expect(page.getByRole('row').nth(18)).toHaveText('2.45 mi' + '19:00'); + await expect(page.getByRole('row').nth(18)).toHaveText('3.95 km' + '19:00'); await expect(page.getByRole('row')).toHaveCount(33); // Revert target set @@ -116,49 +119,10 @@ test('Customize target sets', async ({ page }) => { // Assert paces are correct await expect(page.getByRole('row').nth(11)).toHaveText('1 mi' + '7:45.00'); - await expect(page.getByRole('row').nth(13)).toHaveText('1.29 mi' + '10:00'); + await expect(page.getByRole('row').nth(13)).toHaveText('2.08 km' + '10:00'); await expect(page.getByRole('row')).toHaveCount(31); // Assert title was reset await page.getByRole('button', { name: 'Edit target set' }).click(); await expect(page.getByLabel('Target set label')).toHaveValue('Common Pace Targets'); }); - -test('Save settings across page reloads', async ({ page }) => { - // Go to pace calculator - await page.goto('/'); - await page.getByRole('button', { name: 'Pace Calculator' }).click(); - - // Enter input pace (2 mi in 15:30) - await page.getByLabel('Input distance value').fill('2'); - await page.getByLabel('Input distance unit').selectOption('Miles'); - await page.getByLabel('Input duration hours').fill('0'); - await page.getByLabel('Input duration minutes').fill('15'); - await page.getByLabel('Input duration seconds').fill('30'); - - // Create custom target set - await page.getByText('Advanced Options').click(); - await page.getByLabel('Selected target set').selectOption('[ Create New Target Set ]'); - - // Edit new target set - await expect(page.getByLabel('Target set label')).toHaveValue('New target set'); - await page.getByLabel('Target set label').fill('Less-common Pace Targets'); - await page.getByRole('button', { name: 'Add distance target' }).click(); - await page.getByLabel('Target distance value').last().fill('1.01'); - await page.getByLabel('Target distance unit').last().selectOption('Miles'); - await page.getByRole('button', { name: 'Add time target' }).click(); - await page.getByLabel('Target duration minutes').last().fill('19'); - await page.getByLabel('Target duration seconds').last().fill('0'); - await page.getByRole('button', { name: 'Close' }).click(); - - // Change default units - await page.getByLabel('Default units').selectOption('Kilometers'); - - // Reload page - await page.reload(); - - // Assert paces are correct (custom targets and default units not reset) - await expect(page.getByRole('row').nth(1)).toHaveText('1.01 mi' + '7:49.65'); - await expect(page.getByRole('row').nth(2)).toHaveText('3.95 km' + '19:00'); - await expect(page.getByRole('row')).toHaveCount(3); -}); diff --git a/tests/e2e/race-calculator.spec.js b/tests/e2e/race-calculator.spec.js @@ -1,6 +1,16 @@ import { test, expect } from '@playwright/test'; -test('Basic usage', async ({ page }) => { +test('Race Calculator', async ({ page }) => { + // Structure: + // - Test standard race results + // - Test different default units + // - Test different prediction options + // - Test modified default target set + // - Test custom target set + // - Reload page + // - Assert outputs are still the same + // - Test target set deletion and reversion + // Go to race calculator await page.goto('/'); await page.getByRole('button', { name: 'Race Calculator' }).click(); @@ -48,22 +58,8 @@ test('Basic usage', async ({ page }) => { await expect(page.getByRole('row').nth(5)).toHaveText('1 mi' + '4:49.86' + '3:00 / km'); await expect(page.getByRole('row').nth(10)).toHaveText('5 km' + '17:11.77' + '3:26 / km'); await expect(page.getByRole('row')).toHaveCount(17); -}); - -test('Customize target sets', async ({ page }) => { - // Go to race calculator - await page.goto('/'); - await page.getByRole('button', { name: 'Race Calculator' }).click(); - - // Enter input race (2 mi in 10:30) - await page.getByLabel('Input race distance value').fill('2'); - await page.getByLabel('Input race distance unit').selectOption('Miles'); - await page.getByLabel('Input race duration hours').fill('0'); - await page.getByLabel('Input race duration minutes').fill('10'); - await page.getByLabel('Input race duration seconds').fill('30'); // Edit default target set - await page.getByText('Advanced Options').click(); await page.getByRole('button', { name: 'Edit target set' }).click(); await page.getByLabel('Target set label').fill('Less-common Race Targets'); await page.getByLabel('Target distance value').nth(4).fill('1.01'); @@ -76,9 +72,9 @@ test('Customize target sets', async ({ page }) => { await page.getByRole('button', { name: 'Close' }).click(); // Assert race predictions are correct - await expect(page.getByRole('row').nth(5)).toHaveText('1.01 mi' + '4:58.81' + '4:56 / mi'); - await expect(page.getByRole('row').nth(6)).toHaveText('1.5 mi' + '7:41.60' + '5:08 / mi'); - await expect(page.getByRole('row').nth(12)).toHaveText('3.49 mi' + '19:00' + '5:27 / mi'); + await expect(page.getByRole('row').nth(5)).toHaveText('1.01 mi' + '4:53.11' + '3:00 / km'); + await expect(page.getByRole('row').nth(6)).toHaveText('1.5 mi' + '7:36.47' + '3:09 / km'); + await expect(page.getByRole('row').nth(12)).toHaveText('5.47 km' + '19:00' + '3:29 / km'); await expect(page.getByRole('row')).toHaveCount(19); // Create custom target set @@ -99,17 +95,26 @@ test('Customize target sets', async ({ page }) => { await page.getByRole('button', { name: 'Close' }).click(); // Assert race predictions are correct - await expect(page.getByRole('row').nth(1)).toHaveText('5 km' + '16:47.58' + '5:24 / mi'); - await expect(page.getByRole('row').nth(2)).toHaveText('10 km' + '34:53.84' + '5:37 / mi'); + await expect(page.getByRole('row').nth(1)).toHaveText('5 km' + '17:11.77' + '3:26 / km'); + await expect(page.getByRole('row').nth(2)).toHaveText('10 km' + '37:22.53' + '3:44 / km'); + await expect(page.getByRole('row')).toHaveCount(3); + + // Reload page + await page.reload(); + + // Assert race predictions are correct (custom targets, default units, and model settings not reset) + await expect(page.getByRole('row').nth(1)).toHaveText('5 km' + '17:11.77' + '3:26 / km'); + await expect(page.getByRole('row').nth(2)).toHaveText('10 km' + '37:22.53' + '3:44 / km'); await expect(page.getByRole('row')).toHaveCount(3); // Switch target set + await page.getByText('Advanced Options').click(); await page.getByLabel('Selected target set').selectOption('Less-common Race Targets'); // Assert race predictions are correct - await expect(page.getByRole('row').nth(5)).toHaveText('1.01 mi' + '4:58.81' + '4:56 / mi'); - await expect(page.getByRole('row').nth(6)).toHaveText('1.5 mi' + '7:41.60' + '5:08 / mi'); - await expect(page.getByRole('row').nth(12)).toHaveText('3.49 mi' + '19:00' + '5:27 / mi'); + await expect(page.getByRole('row').nth(5)).toHaveText('1.01 mi' + '4:53.11' + '3:00 / km'); + await expect(page.getByRole('row').nth(6)).toHaveText('1.5 mi' + '7:36.47' + '3:09 / km'); + await expect(page.getByRole('row').nth(12)).toHaveText('5.47 km' + '19:00' + '3:29 / km'); await expect(page.getByRole('row')).toHaveCount(19); // Delete custom target set @@ -118,13 +123,10 @@ test('Customize target sets', async ({ page }) => { await expect(page.getByLabel('Target set label')).toHaveValue('XC Race Targets'); await page.getByRole('button', { name: 'Delete target set' }).click(); - // Switch to default target set - await page.getByLabel('Selected target set').selectOption('Less-common Race Targets'); - // Assert race predictions are correct (back to default target set) - await expect(page.getByRole('row').nth(5)).toHaveText('1.01 mi' + '4:58.81' + '4:56 / mi'); - await expect(page.getByRole('row').nth(6)).toHaveText('1.5 mi' + '7:41.60' + '5:08 / mi'); - await expect(page.getByRole('row').nth(12)).toHaveText('3.49 mi' + '19:00' + '5:27 / mi'); + await expect(page.getByRole('row').nth(5)).toHaveText('1.01 mi' + '4:53.11' + '3:00 / km'); + await expect(page.getByRole('row').nth(6)).toHaveText('1.5 mi' + '7:36.47' + '3:09 / km'); + await expect(page.getByRole('row').nth(12)).toHaveText('5.47 km' + '19:00' + '3:29 / km'); await expect(page.getByRole('row')).toHaveCount(19); // Revert target set @@ -134,56 +136,11 @@ test('Customize target sets', async ({ page }) => { await page.getByRole('button', { name: 'Close' }).click(); // Assert paces are correct - await expect(page.getByRole('row').nth(5)).toHaveText('1 mi' + '4:55.53' + '4:56 / mi'); - await expect(page.getByRole('row').nth(10)).toHaveText('5 km' + '16:47.58' + '5:24 / mi'); + await expect(page.getByRole('row').nth(5)).toHaveText('1 mi' + '4:49.86' + '3:00 / km'); + await expect(page.getByRole('row').nth(10)).toHaveText('5 km' + '17:11.77' + '3:26 / km'); await expect(page.getByRole('row')).toHaveCount(17); // Assert title was reset await page.getByRole('button', { name: 'Edit target set' }).click(); await expect(page.getByLabel('Target set label')).toHaveValue('Common Race Targets'); }); - -test('Save settings across page reloads', async ({ page }) => { - // Go to race calculator - await page.goto('/'); - await page.getByRole('button', { name: 'Race Calculator' }).click(); - - // Enter input race (2 mi in 10:30) - await page.getByLabel('Input race distance value').fill('2'); - await page.getByLabel('Input race distance unit').selectOption('Miles'); - await page.getByLabel('Input race duration hours').fill('0'); - await page.getByLabel('Input race duration minutes').fill('10'); - await page.getByLabel('Input race duration seconds').fill('30'); - - // Create custom target set - await page.getByText('Advanced Options').click(); - await page.getByLabel('Selected target set').selectOption('[ Create New Target Set ]'); - - // Edit new target set - await expect(page.getByLabel('Target set label')).toHaveValue('New target set'); - await page.getByLabel('Target set label').fill('Less-common Race Targets'); - await page.getByRole('button', { name: 'Add distance target' }).click(); - await page.getByLabel('Target distance value').last().fill('1.01'); - await page.getByLabel('Target distance unit').last().selectOption('Miles'); - await page.getByRole('button', { name: 'Add time target' }).click(); - await page.getByLabel('Target duration minutes').last().fill('19'); - await page.getByLabel('Target duration seconds').last().fill('0'); - await page.getByRole('button', { name: 'Close' }).click(); - - // Change default units - await page.getByLabel('Default units').selectOption('Kilometers'); - - // Change prediction model - await page.getByLabel('Prediction model').selectOption('Riegel\'s Model'); - - // Change Riegel exponent - await page.getByLabel('Riegel Exponent').fill('1.12'); - - // Reload page - await page.reload(); - - // Assert race predictions are correct (custom targets, default units, and model settings not reset) - await expect(page.getByRole('row').nth(1)).toHaveText('1.01 mi' + '4:53.11' + '3:00 / km'); - await expect(page.getByRole('row').nth(2)).toHaveText('5.47 km' + '19:00' + '3:29 / km'); - await expect(page.getByRole('row')).toHaveCount(3); -}); diff --git a/tests/e2e/split-calculator.spec.js b/tests/e2e/split-calculator.spec.js @@ -1,6 +1,15 @@ import { test, expect } from '@playwright/test'; -test('Basic usage', async ({ page }) => { +test('Split Calculator', async ({ page }) => { + // Structure: + // - Test standard split results + // - Test different default units + // - Test modified default target set + // - Test custom target set + // - Reload page + // - Assert outputs are still the same + // - Test target set deletion and reversion + // Go to split calculator await page.goto('/'); await page.getByRole('button', { name: 'Split Calculator' }).click(); @@ -26,24 +35,14 @@ test('Basic usage', async ({ page }) => { // Change default units await page.getByLabel('Default units').selectOption('Kilometers'); - // Assert paces are correct + // Assert times and paces are correct + 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:21 / 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:02 / 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:39 / km'); -}); - -test('Customize target sets', async ({ page }) => { - // Go to split calculator - await page.goto('/'); - await page.getByRole('button', { name: 'Split Calculator' }).click(); - - // Enter input 5K splits (7:00, 6:30, 6:30) - await page.getByLabel('Split duration minutes').nth(0).fill('7'); - await page.getByLabel('Split duration seconds').nth(0).fill('0'); - await page.getByLabel('Split duration minutes').nth(1).fill('6'); - await page.getByLabel('Split duration seconds').nth(1).fill('30'); - await page.getByLabel('Split duration minutes').nth(2).fill('6'); - await page.getByLabel('Split duration seconds').nth(2).fill('30'); + await expect(page.getByRole('row')).toHaveCount(4); // Edit target set await page.getByRole('button', { name: 'Edit target set' }).click(); @@ -59,13 +58,13 @@ test('Customize target sets', async ({ page }) => { // Assert times and paces are correct (new distances are processed) 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('7:02 / mi'); + 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('6:32 / mi'); + 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('13:30.00'); - await expect(page.getByRole('row').nth(3).getByRole('cell').nth(3)).toHaveText('0:00 / mi'); + await expect(page.getByRole('row').nth(3).getByRole('cell').nth(3)).toHaveText('0:00 / km'); await expect(page.getByRole('row').nth(4).getByRole('cell').nth(1)).toHaveText('20:00.00'); - await expect(page.getByRole('row').nth(4).getByRole('cell').nth(3)).toHaveText('52:18 / mi'); + await expect(page.getByRole('row').nth(4).getByRole('cell').nth(3)).toHaveText('32:30 / km'); await expect(page.getByRole('row')).toHaveCount(5); // Update third and fourth splits @@ -77,13 +76,13 @@ test('Customize target sets', async ({ page }) => { // Assert times and paces are correct (new input splits are processed) 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('7:02 / mi'); + 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('6:32 / mi'); + 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('19:30.00'); - await expect(page.getByRole('row').nth(3).getByRole('cell').nth(3)).toHaveText('6:02 / mi'); + await expect(page.getByRole('row').nth(3).getByRole('cell').nth(3)).toHaveText('3:45 / km'); await expect(page.getByRole('row').nth(4).getByRole('cell').nth(1)).toHaveText('20:00.00'); - await expect(page.getByRole('row').nth(4).getByRole('cell').nth(3)).toHaveText('4:01 / mi'); + await expect(page.getByRole('row').nth(4).getByRole('cell').nth(3)).toHaveText('2:30 / km'); await expect(page.getByRole('row')).toHaveCount(5); // Create custom target set @@ -104,10 +103,37 @@ test('Customize target sets', async ({ page }) => { await page.getByRole('button', { name: 'Close' }).click(); // Assert times and paces are correct (input splits initialized to zero) + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('0.4 km'); await expect(page.getByRole('row').nth(1).getByRole('cell').nth(1)).toHaveText('0:00.00'); - await expect(page.getByRole('row').nth(1).getByRole('cell').nth(3)).toHaveText('0:00 / mi'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(3)).toHaveText('0:00 / km'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(0)).toHaveText('800 m'); await expect(page.getByRole('row').nth(2).getByRole('cell').nth(1)).toHaveText('0:00.00'); - await expect(page.getByRole('row').nth(2).getByRole('cell').nth(3)).toHaveText('0:00 / mi'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(3)).toHaveText('0:00 / km'); + await expect(page.getByRole('row')).toHaveCount(3); + + // Enter input 800m splits (0:55, 1:05) + await page.getByLabel('Split duration minutes').nth(0).fill('0'); + await page.getByLabel('Split duration seconds').nth(0).fill('55'); + await page.getByLabel('Split duration minutes').nth(1).fill('1'); + await page.getByLabel('Split duration seconds').nth(1).fill('5'); + + // Assert times and paces are correct + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(1)).toHaveText('0:55.00'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(3)).toHaveText('2:18 / km'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(1)).toHaveText('2:00.00'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(3)).toHaveText('2:43 / km'); + await expect(page.getByRole('row')).toHaveCount(3); + + // Reload page + await page.reload(); + + // Assert times and paces are correct (custom targets, split times, and default units not reset) + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('0.4 km'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(1)).toHaveText('0:55.00'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(3)).toHaveText('2:18 / km'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(0)).toHaveText('800 m'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(1)).toHaveText('2:00.00'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(3)).toHaveText('2:43 / km'); await expect(page.getByRole('row')).toHaveCount(3); // Switch target set @@ -115,51 +141,51 @@ test('Customize target sets', async ({ page }) => { // Assert times and paces are correct (input splits are 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('7:02 / mi'); + 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('6:32 / mi'); + 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('19:30.00'); - await expect(page.getByRole('row').nth(3).getByRole('cell').nth(3)).toHaveText('6:02 / mi'); + await expect(page.getByRole('row').nth(3).getByRole('cell').nth(3)).toHaveText('3:45 / km'); await expect(page.getByRole('row').nth(4).getByRole('cell').nth(1)).toHaveText('20:00.00'); - await expect(page.getByRole('row').nth(4).getByRole('cell').nth(3)).toHaveText('4:01 / mi'); + await expect(page.getByRole('row').nth(4).getByRole('cell').nth(3)).toHaveText('2:30 / km'); await expect(page.getByRole('row')).toHaveCount(5); -}); -test('Save settings and state across page reloads', async ({ page }) => { - // Go to split calculator - await page.goto('/'); - await page.getByRole('button', { name: 'Split Calculator' }).click(); + // Delete custom target set + await page.getByLabel('Selected target set').selectOption('800m Splits'); + await page.getByRole('button', { name: 'Edit target set' }).click(); + await expect(page.getByLabel('Target set label')).toHaveValue('800m Splits'); + await page.getByRole('button', { name: 'Delete target set' }).click(); - // Create custom target set - await page.getByLabel('Selected target set').selectOption('[ Create New Target Set ]'); + // Assert times and paces are correct (back to default target set) + 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('19:30.00'); + await expect(page.getByRole('row').nth(3).getByRole('cell').nth(3)).toHaveText('3:45 / km'); + await expect(page.getByRole('row').nth(4).getByRole('cell').nth(1)).toHaveText('20:00.00'); + await expect(page.getByRole('row').nth(4).getByRole('cell').nth(3)).toHaveText('2:30 / km'); + await expect(page.getByRole('row')).toHaveCount(5); - // Edit new target set - await expect(page.getByLabel('Target set label')).toHaveValue('New target set'); - await page.getByLabel('Target set label').fill('800m Splits'); - await page.getByRole('button', { name: 'Add distance target' }).click(); - await page.getByLabel('Target distance value').nth(0).fill('0.4'); - await page.getByLabel('Target distance unit').nth(0).selectOption('Kilometers'); - await page.getByRole('button', { name: 'Add distance target' }).click(); - await page.getByLabel('Target distance value').nth(1).fill('800'); - await page.getByLabel('Target distance unit').nth(1).selectOption('Meters'); + // Revert target set + await page.getByRole('button', { name: 'Edit target set' }).click(); + await expect(page.getByLabel('Target set label')).toHaveValue('5K 1600m Splits'); + await page.getByRole('button', { name: 'Revert target set' }).click(); await page.getByRole('button', { name: 'Close' }).click(); - // Enter 800m (0:55, 1:05) - await page.getByLabel('Split duration minutes').nth(0).fill('0'); - await page.getByLabel('Split duration seconds').nth(0).fill('55'); - await page.getByLabel('Split duration minutes').nth(1).fill('1'); - await page.getByLabel('Split duration seconds').nth(1).fill('5'); - - // Change default units - await page.getByLabel('Default units').selectOption('Kilometers'); - - // Reload page - await page.reload(); + // Assert times and paces are correct (split times are reverted) + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(0)).toHaveText('1 mi'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(1)).toHaveText('0:00.00'); + await expect(page.getByRole('row').nth(1).getByRole('cell').nth(3)).toHaveText('0:00 / km'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(0)).toHaveText('2 mi'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(1)).toHaveText('0:00.00'); + await expect(page.getByRole('row').nth(2).getByRole('cell').nth(3)).toHaveText('0:00 / km'); + await expect(page.getByRole('row').nth(3).getByRole('cell').nth(0)).toHaveText('5 km'); + await expect(page.getByRole('row').nth(3).getByRole('cell').nth(1)).toHaveText('0:00.00'); + await expect(page.getByRole('row').nth(3).getByRole('cell').nth(3)).toHaveText('0:00 / km'); + await expect(page.getByRole('row')).toHaveCount(4); - // Assert paces are correct (custom targets, split times, and default units not reset) - await expect(page.getByRole('row').nth(1).getByRole('cell').nth(1)).toHaveText('0:55.00'); - await expect(page.getByRole('row').nth(1).getByRole('cell').nth(3)).toHaveText('2:18 / km'); - await expect(page.getByRole('row').nth(2).getByRole('cell').nth(1)).toHaveText('2:00.00'); - await expect(page.getByRole('row').nth(2).getByRole('cell').nth(3)).toHaveText('2:43 / km'); - await expect(page.getByRole('row')).toHaveCount(3); + // Assert title was reset + await page.getByRole('button', { name: 'Edit target set' }).click(); + await expect(page.getByLabel('Target set label')).toHaveValue('5K Mile Splits'); }); diff --git a/tests/e2e/unit-calculator.spec.js b/tests/e2e/unit-calculator.spec.js @@ -1,6 +1,15 @@ import { test, expect } from '@playwright/test'; -test('Basic usage', async ({ page }) => { +test('Unit Calculator', async ({ page }) => { + // Structure: + // - Test distance unit conversion + // - Test speed and pace unit conversion + // - Test time unit conversion + // - Reload page + // - Assert distance inputs are still loaded + // - Assert time inputs are still loaded + // - Assert speed and pace inputs are still loaded + // Go to unit calculator await page.goto('/'); await page.getByRole('button', { name: 'Unit Calculator' }).click(); @@ -43,38 +52,6 @@ test('Basic usage', async ({ page }) => { await page.getByLabel('Output units').selectOption('seconds'); await expect(page.getByLabel('Output value')).toHaveText('24872.100'); - // Return to speed and pace category - await page.getByLabel('Selected unit category').selectOption('Speed & Pace'); - await expect(page.getByLabel('Output value')).toHaveText('00:09:39.366'); -}); - -test('Save state across page reloads', async ({ page }) => { - // Go to unit calculator - await page.goto('/'); - await page.getByRole('button', { name: 'Unit Calculator' }).click(); - - // Convert distance units (5000m to mi) - await page.getByLabel('Input units').selectOption('Meters'); - await page.getByLabel('Input value').fill('5000'); - await page.getByLabel('Output units').selectOption('Miles'); - await expect(page.getByLabel('Output value')).toHaveText('3.107'); - - // Convert time units (6:54:32.100 to seconds) - await page.getByLabel('Selected unit category').selectOption('Time'); - await page.getByLabel('Input units').selectOption('hh:mm:ss'); - await page.getByLabel('Input time hours').fill('6'); - await page.getByLabel('Input time minutes').fill('54'); - await page.getByLabel('Input time seconds').fill('32.1'); - await page.getByLabel('Output units').selectOption('seconds'); - await expect(page.getByLabel('Output value')).toHaveText('24872.100'); - - // Convert speed and pace units (10 kph to time per mile) - await page.getByLabel('Selected unit category').selectOption('Speed & Pace'); - await page.getByLabel('Input units').selectOption('Kilometers per Hour'); - await page.getByLabel('Input value').fill('10'); - await page.getByLabel('Output units').selectOption('Time per Mile'); - await expect(page.getByLabel('Output value')).toHaveText('00:09:39.366'); - // Reload page await page.reload(); diff --git a/tests/e2e/workout-calculator.spec.js b/tests/e2e/workout-calculator.spec.js @@ -1,6 +1,15 @@ import { test, expect } from '@playwright/test'; -test('Basic usage', async ({ page }) => { +test('Workout Calculator', async ({ page }) => { + // Structure: + // - Test standard workout results + // - Test different prediction options + // - Test modified default target set + // - Test custom target set + // - Reload page + // - Assert outputs are still the same + // - Test target set deletion and reversion + // Go to workout calculator await page.goto('/'); await page.getByRole('button', { name: 'Workout Calculator' }).click(); @@ -34,22 +43,8 @@ test('Basic usage', async ({ page }) => { await expect(page.getByRole('row').nth(1)).toHaveText('400 m @ 1 mi' + '1:12.04'); await expect(page.getByRole('row').nth(3)).toHaveText('1600 m @ 1:00:00' + '6:17.47'); await expect(page.getByRole('row')).toHaveCount(5); -}); - -test('Customize target sets', async ({ page }) => { - // Go to workout calculator - await page.goto('/'); - await page.getByRole('button', { name: 'Workout Calculator' }).click(); - - // Enter input race (2 mi in 10:30) - await page.getByLabel('Input race distance value').fill('2'); - await page.getByLabel('Input race distance unit').selectOption('Miles'); - await page.getByLabel('Input race duration hours').fill('0'); - await page.getByLabel('Input race duration minutes').fill('10'); - await page.getByLabel('Input race duration seconds').fill('30'); // Edit default target set - await page.getByText('Advanced Options').click(); await page.getByRole('button', { name: 'Edit target set' }).click(); await page.getByLabel('Target set label').fill('Less-common Workout Targets'); await page.getByLabel('Split distance value').nth(0).fill('401'); @@ -68,8 +63,8 @@ test('Customize target sets', async ({ page }) => { // Assert workout splits are correct await expect(page.getByRole('row').nth(1)).toHaveText('401 m @ 2 mi' + '1:18.49'); - await expect(page.getByRole('row').nth(2)).toHaveText('600 m @ 19:00' + '2:01.73'); - await expect(page.getByRole('row').nth(4)).toHaveText('1 mi @ 10 km' + '5:36.97'); + await expect(page.getByRole('row').nth(2)).toHaveText('600 m @ 19:00' + '2:05.14'); + await expect(page.getByRole('row').nth(4)).toHaveText('1 mi @ 10 km' + '6:00.90'); await expect(page.getByRole('row')).toHaveCount(7); // Create custom target set @@ -94,17 +89,26 @@ test('Customize target sets', async ({ page }) => { await page.getByRole('button', { name: 'Close' }).click(); // Assert workout splits are correct - await expect(page.getByRole('row').nth(1)).toHaveText('800 m @ 5 km' + '2:41.21'); - await expect(page.getByRole('row').nth(2)).toHaveText('1600 m @ 10 km' + '5:35.01'); + await expect(page.getByRole('row').nth(1)).toHaveText('800 m @ 5 km' + '2:45.08'); + await expect(page.getByRole('row').nth(2)).toHaveText('1600 m @ 10 km' + '5:58.80'); + await expect(page.getByRole('row')).toHaveCount(3); + + // Reload page + await page.reload(); + + // Assert workout splits are correct (custom targets and model settings not reset) + await expect(page.getByRole('row').nth(1)).toHaveText('800 m @ 5 km' + '2:45.08'); + await expect(page.getByRole('row').nth(2)).toHaveText('1600 m @ 10 km' + '5:58.80'); await expect(page.getByRole('row')).toHaveCount(3); // Switch target set + await page.getByText('Advanced Options').click(); await page.getByLabel('Selected target set').selectOption('Less-common Workout Targets'); // Assert workout splits are correct await expect(page.getByRole('row').nth(1)).toHaveText('401 m @ 2 mi' + '1:18.49'); - await expect(page.getByRole('row').nth(2)).toHaveText('600 m @ 19:00' + '2:01.73'); - await expect(page.getByRole('row').nth(4)).toHaveText('1 mi @ 10 km' + '5:36.97'); + await expect(page.getByRole('row').nth(2)).toHaveText('600 m @ 19:00' + '2:05.14'); + await expect(page.getByRole('row').nth(4)).toHaveText('1 mi @ 10 km' + '6:00.90'); await expect(page.getByRole('row')).toHaveCount(7); // Delete custom target set @@ -118,8 +122,8 @@ test('Customize target sets', async ({ page }) => { // Assert workout splits are correct (back to default target set) await expect(page.getByRole('row').nth(1)).toHaveText('401 m @ 2 mi' + '1:18.49'); - await expect(page.getByRole('row').nth(2)).toHaveText('600 m @ 19:00' + '2:01.73'); - await expect(page.getByRole('row').nth(4)).toHaveText('1 mi @ 10 km' + '5:36.97'); + await expect(page.getByRole('row').nth(2)).toHaveText('600 m @ 19:00' + '2:05.14'); + await expect(page.getByRole('row').nth(4)).toHaveText('1 mi @ 10 km' + '6:00.90'); await expect(page.getByRole('row')).toHaveCount(7); // Revert target set @@ -129,57 +133,11 @@ test('Customize target sets', async ({ page }) => { await page.getByRole('button', { name: 'Close' }).click(); // Assert paces are correct - await expect(page.getByRole('row').nth(1)).toHaveText('400 m @ 1 mi' + '1:13.45'); - await expect(page.getByRole('row').nth(3)).toHaveText('1600 m @ 1:00:00' + '5:45.44'); + await expect(page.getByRole('row').nth(1)).toHaveText('400 m @ 1 mi' + '1:12.04'); + await expect(page.getByRole('row').nth(3)).toHaveText('1600 m @ 1:00:00' + '6:17.47'); await expect(page.getByRole('row')).toHaveCount(5); // Assert title was reset await page.getByRole('button', { name: 'Edit target set' }).click(); await expect(page.getByLabel('Target set label')).toHaveValue('Common Workout Targets'); }); - -test('Save settings across page reloads', async ({ page }) => { - // Go to workout calculator - await page.goto('/'); - await page.getByRole('button', { name: 'Workout Calculator' }).click(); - - // Enter input race (2 mi in 10:30) - await page.getByLabel('Input race distance value').fill('2'); - await page.getByLabel('Input race distance unit').selectOption('Miles'); - await page.getByLabel('Input race duration hours').fill('0'); - await page.getByLabel('Input race duration minutes').fill('10'); - await page.getByLabel('Input race duration seconds').fill('30'); - - // Create custom target set - await page.getByText('Advanced Options').click(); - await page.getByLabel('Selected target set').selectOption('[ Create New Target Set ]'); - - // Edit new target set - await expect(page.getByLabel('Target set label')).toHaveValue('New target set'); - await page.getByLabel('Target set label').fill('Workout Target Set #2'); - await page.getByRole('button', { name: 'Add distance target' }).click(); - await page.getByLabel('Split distance value').last().fill('800'); - await page.getByLabel('Split distance unit').last().selectOption('Meters'); - await page.getByLabel('Target distance value').last().fill('5'); - await page.getByLabel('Target distance unit').last().selectOption('Kilometers'); - await page.getByRole('button', { name: 'Add distance target' }).click(); - await page.getByLabel('Split distance value').last().fill('1600'); - await page.getByLabel('Split distance unit').last().selectOption('Meters'); - await page.getByLabel('Target distance value').last().fill('10'); - await page.getByLabel('Target distance unit').last().selectOption('Kilometers'); - await page.getByRole('button', { name: 'Close' }).click(); - - // Change prediction model - await page.getByLabel('Prediction model').selectOption('Riegel\'s Model'); - - // Change Riegel exponent - await page.getByLabel('Riegel Exponent').fill('1.12'); - - // Reload page - await page.reload(); - - // Assert workout splits are correct (custom targets and model settings not reset) - await expect(page.getByRole('row').nth(1)).toHaveText('800 m @ 5 km' + '2:45.08'); - await expect(page.getByRole('row').nth(2)).toHaveText('1600 m @ 10 km' + '5:58.80'); - await expect(page.getByRole('row')).toHaveCount(3); -});