From ab7490be9014c84a50aff7050c96f3c1377b20e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20M=20J=20Barata=20Ribeiro?= <122732773+Barata-Ribeiro@users.noreply.github.com> Date: Sun, 28 Jun 2026 07:25:01 -0300 Subject: [PATCH 1/8] test: implement converter related tests --- .../converters/bytes.browser.test.tsx | 74 +++++++++++++++++++ .../converters/length.browser.test.tsx | 57 ++++++++++++++ .../converters/mass.browser.test.tsx | 55 ++++++++++++++ .../converters/speed.browser.test.tsx | 52 +++++++++++++ .../converters/temperature.browser.test.tsx | 72 ++++++++++++++++++ .../converters/time.browser.test.tsx | 56 ++++++++++++++ 6 files changed, 366 insertions(+) create mode 100644 tests/browser/components/converters/bytes.browser.test.tsx create mode 100644 tests/browser/components/converters/length.browser.test.tsx create mode 100644 tests/browser/components/converters/mass.browser.test.tsx create mode 100644 tests/browser/components/converters/speed.browser.test.tsx create mode 100644 tests/browser/components/converters/temperature.browser.test.tsx create mode 100644 tests/browser/components/converters/time.browser.test.tsx diff --git a/tests/browser/components/converters/bytes.browser.test.tsx b/tests/browser/components/converters/bytes.browser.test.tsx new file mode 100644 index 0000000..ddabfaf --- /dev/null +++ b/tests/browser/components/converters/bytes.browser.test.tsx @@ -0,0 +1,74 @@ +import { describe, expect, test } from 'vitest'; +import { render } from 'vitest-browser-react'; +import Bytes from '~/components/pages/converters/bytes'; + +describe('Bytes', () => { + describe('rendering', () => { + test('shows all unit labels', async () => { + const screen = await render(); + for (const label of [ + 'Bytes (B)', + 'Kilobytes (KB)', + 'Megabytes (MB)', + 'Gigabytes (GB)', + 'Terabytes (TB)', + 'Petabytes (PB)', + ]) { + await expect.element(screen.getByLabelText(label)).toBeInTheDocument(); + } + }); + + test('inputs start empty', async () => { + const screen = await render(); + await expect.element(screen.getByLabelText('Bytes (B)')).toHaveValue(''); + }); + }); + + describe('conversion', () => { + test.each([ + ['1000', 'Bytes (B)', 'Kilobytes (KB)', '1'], + ['1', 'Kilobytes (KB)', 'Bytes (B)', '1000'], + ['1', 'Megabytes (MB)', 'Kilobytes (KB)', '1000'], + ['1', 'Gigabytes (GB)', 'Megabytes (MB)', '1000'], + ['1', 'Terabytes (TB)', 'Gigabytes (GB)', '1000'], + ['1', 'Petabytes (PB)', 'Terabytes (TB)', '1000'], + ['0.5', 'Kilobytes (KB)', 'Bytes (B)', '500'], + ])('%s %s → %s %s', async (value, inputLabel, outputLabel, expected) => { + const screen = await render(); + await screen.getByLabelText(inputLabel).fill(value); + await expect.element(screen.getByLabelText(outputLabel)).toHaveValue(expected); + }); + + test('comma decimal separator converts correctly', async () => { + const screen = await render(); + await screen.getByLabelText('Kilobytes (KB)').fill('1,5'); + await expect.element(screen.getByLabelText('Bytes (B)')).toHaveValue('1.500'); + }); + }); + + describe('invalid input', () => { + test('ignores letters', async () => { + const screen = await render(); + const input = screen.getByLabelText('Bytes (B)'); + await input.fill('abc'); + await expect.element(input).toHaveValue(''); + }); + + test('ignores special characters', async () => { + const screen = await render(); + const input = screen.getByLabelText('Kilobytes (KB)'); + await input.fill('!@#'); + await expect.element(input).toHaveValue(''); + }); + }); + + describe('clearing', () => { + test('clearing the active field clears all others', async () => { + const screen = await render(); + await screen.getByLabelText('Bytes (B)').fill('1000'); + await screen.getByLabelText('Bytes (B)').fill(''); + await expect.element(screen.getByLabelText('Kilobytes (KB)')).toHaveValue(''); + await expect.element(screen.getByLabelText('Megabytes (MB)')).toHaveValue(''); + }); + }); +}); diff --git a/tests/browser/components/converters/length.browser.test.tsx b/tests/browser/components/converters/length.browser.test.tsx new file mode 100644 index 0000000..7f2655c --- /dev/null +++ b/tests/browser/components/converters/length.browser.test.tsx @@ -0,0 +1,57 @@ +import { describe, expect, test } from 'vitest'; +import { render } from 'vitest-browser-react'; +import Length from '~/components/pages/converters/length'; + +describe('Length', () => { + describe('rendering', () => { + test('shows all unit labels', async () => { + const screen = await render(); + for (const label of [ + 'Kilometers (km)', + 'Meters (m)', + 'Centimeters (cm)', + 'Millimeters (mm)', + 'Miles (mi)', + 'Yards (yd)', + 'Inches (in)', + 'Feet (ft)', + 'Nautical Miles (nmi)', + ]) { + await expect.element(screen.getByLabelText(label)).toBeInTheDocument(); + } + }); + }); + + describe('conversion', () => { + test.each([ + ['1', 'Kilometers (km)', 'Meters (m)', '1000'], + ['1000', 'Meters (m)', 'Kilometers (km)', '1'], + ['1', 'Meters (m)', 'Centimeters (cm)', '100'], + ['100', 'Centimeters (cm)', 'Meters (m)', '1'], + ['1', 'Meters (m)', 'Millimeters (mm)', '1000'], + ['1', 'Miles (mi)', 'Meters (m)', '1609.34'], + ])('%s %s → %s %s', async (value, inputLabel, outputLabel, expected) => { + const screen = await render(); + await screen.getByLabelText(inputLabel).fill(value); + await expect.element(screen.getByLabelText(outputLabel)).toHaveValue(expected); + }); + }); + + describe('invalid input', () => { + test('ignores letters', async () => { + const screen = await render(); + const input = screen.getByLabelText('Meters (m)'); + await input.fill('xyz'); + await expect.element(input).toHaveValue(''); + }); + }); + + describe('clearing', () => { + test('clearing the active field clears all others', async () => { + const screen = await render(); + await screen.getByLabelText('Kilometers (km)').fill('1'); + await screen.getByLabelText('Kilometers (km)').fill(''); + await expect.element(screen.getByLabelText('Meters (m)')).toHaveValue(''); + }); + }); +}); diff --git a/tests/browser/components/converters/mass.browser.test.tsx b/tests/browser/components/converters/mass.browser.test.tsx new file mode 100644 index 0000000..ea500c6 --- /dev/null +++ b/tests/browser/components/converters/mass.browser.test.tsx @@ -0,0 +1,55 @@ +import { describe, expect, test } from 'vitest'; +import { render } from 'vitest-browser-react'; +import Mass from '~/components/pages/converters/mass'; + +describe('Mass', () => { + describe('rendering', () => { + test('shows all unit labels', async () => { + const screen = await render(); + for (const label of [ + 'Tonnes (t)', + 'Kilograms (kg)', + 'Grams (g)', + 'Milligrams (mg)', + 'Pounds (lb)', + 'Ounces (oz)', + 'Stones (st)', + ]) { + await expect.element(screen.getByLabelText(label)).toBeInTheDocument(); + } + }); + }); + + describe('conversion', () => { + test.each([ + ['1', 'Kilograms (kg)', 'Grams (g)', '1000'], + ['1000', 'Grams (g)', 'Kilograms (kg)', '1'], + ['1', 'Tonnes (t)', 'Kilograms (kg)', '1000'], + ['1', 'Kilograms (kg)', 'Pounds (lb)', '2.204623'], + ['1', 'Pounds (lb)', 'Grams (g)', '453.592'], + ['1', 'Kilograms (kg)', 'Ounces (oz)', '35.27396'], + ])('%s %s → %s %s', async (value, inputLabel, outputLabel, expected) => { + const screen = await render(); + await screen.getByLabelText(inputLabel).fill(value); + await expect.element(screen.getByLabelText(outputLabel)).toHaveValue(expected); + }); + }); + + describe('invalid input', () => { + test('ignores letters', async () => { + const screen = await render(); + const input = screen.getByLabelText('Kilograms (kg)'); + await input.fill('abc'); + await expect.element(input).toHaveValue(''); + }); + }); + + describe('clearing', () => { + test('clearing the active field clears all others', async () => { + const screen = await render(); + await screen.getByLabelText('Kilograms (kg)').fill('1'); + await screen.getByLabelText('Kilograms (kg)').fill(''); + await expect.element(screen.getByLabelText('Grams (g)')).toHaveValue(''); + }); + }); +}); diff --git a/tests/browser/components/converters/speed.browser.test.tsx b/tests/browser/components/converters/speed.browser.test.tsx new file mode 100644 index 0000000..df87a37 --- /dev/null +++ b/tests/browser/components/converters/speed.browser.test.tsx @@ -0,0 +1,52 @@ +import { describe, expect, test } from 'vitest'; +import { render } from 'vitest-browser-react'; +import Speed from '~/components/pages/converters/speed'; + +describe('Speed', () => { + describe('rendering', () => { + test('shows all unit labels', async () => { + const screen = await render(); + for (const label of [ + 'Kilometers per hour (km/h)', + 'Miles per hour (mph)', + 'Meters per second (m/s)', + 'Feet per second (ft/s)', + 'Knots (kn)', + 'Mach (Ma)', + ]) { + await expect.element(screen.getByLabelText(label)).toBeInTheDocument(); + } + }); + }); + + describe('conversion', () => { + test.each([ + ['3.6', 'Meters per second (m/s)', 'Kilometers per hour (km/h)', '12.96'], + ['1', 'Kilometers per hour (km/h)', 'Meters per second (m/s)', '0.277778'], + ['1', 'Miles per hour (mph)', 'Kilometers per hour (km/h)', '1.609'], + ['1', 'Knots (kn)', 'Kilometers per hour (km/h)', '1.852'], + ])('%s %s → %s %s', async (value, inputLabel, outputLabel, expected) => { + const screen = await render(); + await screen.getByLabelText(inputLabel).fill(value); + await expect.element(screen.getByLabelText(outputLabel)).toHaveValue(expected); + }); + }); + + describe('invalid input', () => { + test('ignores letters', async () => { + const screen = await render(); + const input = screen.getByLabelText('Kilometers per hour (km/h)'); + await input.fill('fast'); + await expect.element(input).toHaveValue(''); + }); + }); + + describe('clearing', () => { + test('clearing the active field clears all others', async () => { + const screen = await render(); + await screen.getByLabelText('Kilometers per hour (km/h)').fill('100'); + await screen.getByLabelText('Kilometers per hour (km/h)').fill(''); + await expect.element(screen.getByLabelText('Miles per hour (mph)')).toHaveValue(''); + }); + }); +}); diff --git a/tests/browser/components/converters/temperature.browser.test.tsx b/tests/browser/components/converters/temperature.browser.test.tsx new file mode 100644 index 0000000..04a29d0 --- /dev/null +++ b/tests/browser/components/converters/temperature.browser.test.tsx @@ -0,0 +1,72 @@ +import { describe, expect, test } from 'vitest'; +import { render } from 'vitest-browser-react'; +import Temperature from '~/components/pages/converters/temperature'; + +describe('Temperature', () => { + describe('rendering', () => { + test('shows fahrenheit, celsius, and kelvin inputs', async () => { + const screen = await render(); + await expect.element(screen.getByPlaceholder('32')).toBeInTheDocument(); + await expect.element(screen.getByPlaceholder('0')).toBeInTheDocument(); + await expect.element(screen.getByPlaceholder('273.15')).toBeInTheDocument(); + }); + }); + + describe('from Fahrenheit', () => { + test.each([ + ['32', '0.00', '273.15'], + ['212', '100.00', '373.15'], + ['0', '-17.78', '255.37'], + ])('%s°F → %s°C, %sK', async (f, expectedC, expectedK) => { + const screen = await render(); + await screen.getByPlaceholder('32').fill(f); + await expect.element(screen.getByPlaceholder('0')).toHaveValue(expectedC); + await expect.element(screen.getByPlaceholder('273.15')).toHaveValue(expectedK); + }); + }); + + describe('from Celsius', () => { + test.each([ + ['0', '32.00', '273.15'], + ['100', '212.00', '373.15'], + ['-40', '-40.00', '233.15'], + ])('%s°C → %s°F, %sK', async (c, expectedF, expectedK) => { + const screen = await render(); + await screen.getByPlaceholder('0').fill(c); + await expect.element(screen.getByPlaceholder('32')).toHaveValue(expectedF); + await expect.element(screen.getByPlaceholder('273.15')).toHaveValue(expectedK); + }); + }); + + describe('from Kelvin', () => { + test.each([ + ['273.15', '32.00', '0.00'], + ['373.15', '212.00', '100.00'], + ['0', '-459.67', '-273.15'], + ])('%sK → %s°F, %s°C', async (k, expectedF, expectedC) => { + const screen = await render(); + await screen.getByPlaceholder('273.15').fill(k); + await expect.element(screen.getByPlaceholder('32')).toHaveValue(expectedF); + await expect.element(screen.getByPlaceholder('0')).toHaveValue(expectedC); + }); + }); + + describe('invalid input', () => { + test('ignores letters', async () => { + const screen = await render(); + const input = screen.getByPlaceholder('32'); + await input.fill('abc'); + await expect.element(input).toHaveValue(''); + }); + }); + + describe('clearing', () => { + test('clearing a field clears the others', async () => { + const screen = await render(); + await screen.getByPlaceholder('32').fill('212'); + await screen.getByPlaceholder('32').fill(''); + await expect.element(screen.getByPlaceholder('0')).toHaveValue(''); + await expect.element(screen.getByPlaceholder('273.15')).toHaveValue(''); + }); + }); +}); diff --git a/tests/browser/components/converters/time.browser.test.tsx b/tests/browser/components/converters/time.browser.test.tsx new file mode 100644 index 0000000..a8a028e --- /dev/null +++ b/tests/browser/components/converters/time.browser.test.tsx @@ -0,0 +1,56 @@ +import { describe, expect, test } from 'vitest'; +import { render } from 'vitest-browser-react'; +import Time from '~/components/pages/converters/time'; + +describe('Time', () => { + describe('rendering', () => { + test('shows all unit labels', async () => { + const screen = await render(