Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
302 changes: 301 additions & 1 deletion tests/base.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,304 @@ test.describe('base tests', () => {
});
});

// TODO: add tests for each of the possible parameters
test.describe('component parameters', () => {
test.beforeEach(async ({ page }) => {
await page.goto(fileUrl);
});

test.describe('prefix and suffix', () => {
test('renders with default prefix $ and suffix USD', async ({ page }) => {
const currencyInput = await page.locator('#currency-input');

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent use of await with page.locator(). On line 31, currencyInput is declared with await, but locators are synchronous and don't need await. Compare with line 36 where the same pattern is used without await. Remove the await keyword for consistency with other locator declarations in the file.

Suggested change
const currencyInput = await page.locator('#currency-input');
const currencyInput = page.locator('#currency-input');

Copilot uses AI. Check for mistakes.
await expect(currencyInput).toHaveValue('$0.00 USD');
});
Comment on lines +30 to +33

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test duplicates the sanity check on line 13-16. Both tests verify that the currency input has the default value '$0.00 USD' without any additional setup or configuration. Consider removing this duplicate test.

Suggested change
test('renders with default prefix $ and suffix USD', async ({ page }) => {
const currencyInput = await page.locator('#currency-input');
await expect(currencyInput).toHaveValue('$0.00 USD');
});

Copilot uses AI. Check for mistakes.

test('renders with custom prefix', async ({ page }) => {
const prefixInput = page.locator('[name=prefix]');
const suffixInput = page.locator('[name=suffix]');
const applyBtn = page.locator('[name=apply]');

await prefixInput.fill('£');
await suffixInput.fill('');
await applyBtn.click();

const currencyInput = page.locator('#currency-input');
await expect(currencyInput).toHaveValue('£0.00');
});

test('renders with custom suffix', async ({ page }) => {
const prefixInput = page.locator('[name=prefix]');
const suffixInput = page.locator('[name=suffix]');
const applyBtn = page.locator('[name=apply]');

await prefixInput.fill('');
await suffixInput.fill(' EUR');
await applyBtn.click();

const currencyInput = page.locator('#currency-input');
await expect(currencyInput).toHaveValue('0.00 EUR');
});

test('renders with both custom prefix and suffix', async ({ page }) => {
const prefixInput = page.locator('[name=prefix]');
const suffixInput = page.locator('[name=suffix]');
const applyBtn = page.locator('[name=apply]');

await prefixInput.fill('¥');
await suffixInput.fill(' JPY');
await applyBtn.click();

const currencyInput = page.locator('#currency-input');
await expect(currencyInput).toHaveValue('¥0.00 JPY');
});
});

test.describe('separators and precision', () => {
test('default separators are comma thousand and period decimal', async ({ page }) => {
const currencyInput = page.locator('#currency-input');

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable currencyInput.

Suggested change
const currencyInput = page.locator('#currency-input');

Copilot uses AI. Check for mistakes.

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable currencyInput.

Copilot uses AI. Check for mistakes.
const decimalInput = page.locator('[name=decimalSeparator]');
const thousandInput = page.locator('[name=thousandSeparator]');

// Verify defaults
const decimalValue = await decimalInput.inputValue();
const thousandValue = await thousandInput.inputValue();
expect(decimalValue).toBe('.');
expect(thousandValue).toBe(',');
});

test('custom decimal separator', async ({ page }) => {
const decimalInput = page.locator('[name=decimalSeparator]');
const prefixInput = page.locator('[name=prefix]');
const suffixInput = page.locator('[name=suffix]');
const applyBtn = page.locator('[name=apply]');

await prefixInput.fill('');
await suffixInput.fill('');
await decimalInput.fill(',');
await applyBtn.click();

await page.waitForTimeout(100);

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded timeout of 100ms is used here and in multiple other tests throughout this file (lines 123, 148, 170, 238). These arbitrary timeouts can lead to flaky tests and don't follow Playwright best practices. Consider using Playwright's auto-waiting capabilities or explicit wait conditions instead of fixed timeouts.

Copilot uses AI. Check for mistakes.

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using page.waitForTimeout is an anti-pattern in Playwright tests and can lead to flaky tests. Instead of arbitrary timeouts, use explicit waits for specific conditions, such as waiting for the input to have a certain attribute or value after clicking the apply button. Consider using expect with auto-retrying assertions or page.waitForFunction to wait for the state to update.

Suggested change
await page.waitForTimeout(100);
await expect(decimalInput).toHaveValue(',');

Copilot uses AI. Check for mistakes.
const currencyInput = page.locator('#currency-input');
await currencyInput.focus();
await currencyInput.fill('');
await currencyInput.type('12345');

await expect(currencyInput).toHaveValue('123,45');
});

test('custom thousand separator', async ({ page }) => {
const thousandInput = page.locator('[name=thousandSeparator]');
const precisionInput = page.locator('[name=precision]');
const prefixInput = page.locator('[name=prefix]');
const suffixInput = page.locator('[name=suffix]');
const decimalInput = page.locator('[name=decimalSeparator]');
const applyBtn = page.locator('[name=apply]');

await prefixInput.fill('');
await suffixInput.fill('');
await decimalInput.fill(',');
await thousandInput.fill('.');
await precisionInput.fill('2');
await applyBtn.click();

await page.waitForTimeout(100);

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded timeout of 100ms is used here and in multiple other tests throughout this file (lines 148, 170, 238). These arbitrary timeouts can lead to flaky tests and don't follow Playwright best practices. Consider using Playwright's auto-waiting capabilities or explicit wait conditions instead of fixed timeouts.

Copilot uses AI. Check for mistakes.
const currencyInput = page.locator('#currency-input');
await currencyInput.focus();
await currencyInput.fill('');
await currencyInput.type('1234567');

// With custom separators, should format as 1.234.567,00
const value = await currencyInput.inputValue();
expect(value).toContain('.');
expect(value).toContain(',');
});

test('precision 0', async ({ page }) => {
const precisionInput = page.locator('[name=precision]');
const prefixInput = page.locator('[name=prefix]');
const suffixInput = page.locator('[name=suffix]');
const decimalInput = page.locator('[name=decimalSeparator]');
const applyBtn = page.locator('[name=apply]');

await prefixInput.fill('');
await suffixInput.fill('');
await decimalInput.fill('.');
await precisionInput.fill('0');
await applyBtn.click();

await page.waitForTimeout(100);
const currencyInput = page.locator('#currency-input');

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded timeout of 100ms is used here and in multiple other tests throughout this file (lines 170, 238). These arbitrary timeouts can lead to flaky tests and don't follow Playwright best practices. Consider using Playwright's auto-waiting capabilities or explicit wait conditions instead of fixed timeouts.

Suggested change
await page.waitForTimeout(100);
const currencyInput = page.locator('#currency-input');
const currencyInput = page.locator('#currency-input');
await expect(currencyInput).toHaveValue('');

Copilot uses AI. Check for mistakes.
await currencyInput.focus();
await currencyInput.fill('');
await currencyInput.type('12345');

await expect(currencyInput).toHaveValue('12,345');
});

test('precision 3', async ({ page }) => {
const precisionInput = page.locator('[name=precision]');
const prefixInput = page.locator('[name=prefix]');
const suffixInput = page.locator('[name=suffix]');
const decimalInput = page.locator('[name=decimalSeparator]');
const applyBtn = page.locator('[name=apply]');

await prefixInput.fill('');
await suffixInput.fill('');
await decimalInput.fill('.');
await precisionInput.fill('3');
await applyBtn.click();

await page.waitForTimeout(100);

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded timeout of 100ms is used here and in another test (line 238). These arbitrary timeouts can lead to flaky tests and don't follow Playwright best practices. Consider using Playwright's auto-waiting capabilities or explicit wait conditions instead of fixed timeouts.

Copilot uses AI. Check for mistakes.
const currencyInput = page.locator('#currency-input');

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using page.waitForTimeout is an anti-pattern in Playwright tests and can lead to flaky tests. Instead of arbitrary timeouts, use explicit waits for specific conditions, such as waiting for the input to have a certain attribute or value after clicking the apply button. Consider using expect with auto-retrying assertions or page.waitForFunction to wait for the state to update.

Suggested change
await page.waitForTimeout(100);
const currencyInput = page.locator('#currency-input');
const currencyInput = page.locator('#currency-input');
await expect(currencyInput).toBeEnabled();

Copilot uses AI. Check for mistakes.
await currencyInput.focus();
await currencyInput.fill('');
await currencyInput.type('12345');

await expect(currencyInput).toHaveValue('12.345');
});
});

test.describe('allowNegative', () => {
test('rejects negative input when allowNegative is false', async ({ page }) => {
const currencyInput = page.locator('#currency-input');
await currencyInput.focus();
await currencyInput.fill('');
await currencyInput.type('100');

// Should not contain minus sign since allowNegative is false by default
const value = await currencyInput.inputValue();
expect(value).not.toContain('-');
});
Comment thread
ericblade marked this conversation as resolved.

test('allows typing when allowNegative is false', async ({ page }) => {
const currencyInput = page.locator('#currency-input');
await currencyInput.focus();
await currencyInput.fill('');
await currencyInput.type('100');

// Should have numeric content
const value = await currencyInput.inputValue();
expect(value).toMatch(/\d/);
});
});
Comment thread
ericblade marked this conversation as resolved.
Outdated

test.describe('allowEmpty', () => {
test('does not allow empty value when allowEmpty is false', async ({ page }) => {
const currencyInput = page.locator('#currency-input');
await currencyInput.focus();
await currencyInput.fill('');

// Should default to 0.00 when allowEmpty is false
await expect(currencyInput).toHaveValue('$0.00 USD');
});

test('maintains default value after clearing', async ({ page }) => {
const currencyInput = page.locator('#currency-input');
await currencyInput.focus();
await currencyInput.fill('');
await currencyInput.type('100');

// Type something first
const valueBefore = await currencyInput.inputValue();
expect(valueBefore).toContain('1');

// Clear and it should go back to 0
await currencyInput.fill('');
await expect(currencyInput).toHaveValue('$0.00 USD');
});
});

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests don't actually verify the allowEmpty functionality because they never enable allowEmpty=true. Both tests verify default behavior where allowEmpty is false. To properly test allowEmpty, add tests that enable the setting and verify that the input can remain empty without defaulting to "$0.00 USD".

Copilot uses AI. Check for mistakes.

test.describe('selectAllOnFocus', () => {
test('caret position is managed at end of input content', async ({ page }) => {
const selectAllCheckbox = page.locator('[name=selectAllOnFocus]');
const applyBtn = page.locator('[name=apply]');

await selectAllCheckbox.check();
await applyBtn.click();

await page.waitForTimeout(100);

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded timeout of 100ms is used here. These arbitrary timeouts can lead to flaky tests and don't follow Playwright best practices. Consider using Playwright's auto-waiting capabilities or explicit wait conditions instead of fixed timeouts.

Suggested change
await page.waitForTimeout(100);

Copilot uses AI. Check for mistakes.
const currencyInput = page.locator('#currency-input');

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using page.waitForTimeout is an anti-pattern in Playwright tests and can lead to flaky tests. Instead of arbitrary timeouts, use explicit waits for specific conditions, such as waiting for the input to have a certain attribute or value after clicking the apply button. Consider using expect with auto-retrying assertions or page.waitForFunction to wait for the state to update.

Suggested change
await page.waitForTimeout(100);
const currencyInput = page.locator('#currency-input');
// Wait for the currency input to be enabled and visible after applying settings
const currencyInput = page.locator('#currency-input');
await expect(currencyInput).toBeVisible();
await expect(currencyInput).toBeEnabled();

Copilot uses AI. Check for mistakes.
await currencyInput.focus();

// With selectAllOnFocus, all text should be selected
// The selection should encompass the content
const inputValue = await currencyInput.inputValue();

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable inputValue.

Suggested change
const inputValue = await currencyInput.inputValue();

Copilot uses AI. Check for mistakes.

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable inputValue.

Suggested change
const inputValue = await currencyInput.inputValue();

Copilot uses AI. Check for mistakes.
const selectionStart = await currencyInput.evaluate((el: HTMLInputElement) => el.selectionStart);
const selectionEnd = await currencyInput.evaluate((el: HTMLInputElement) => el.selectionEnd);

// Should have selected content
expect(selectionEnd - selectionStart).toBeGreaterThan(0);
});
Comment on lines +299 to +314

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test name "caret position is managed at end of input content" doesn't accurately describe what the test verifies. The test actually checks that text is selected when selectAllOnFocus is enabled. Consider renaming to something like "selects all text on focus when selectAllOnFocus is enabled" to better reflect the actual test behavior.

Copilot uses AI. Check for mistakes.
});
Comment on lines +298 to +315

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test doesn't verify that selectAllOnFocus actually causes all text to be selected on focus. The test checks the checkbox and applies, then focuses the input, but only verifies that there's some selection (selectionEnd - selectionStart > 0). It doesn't verify that ALL text is selected by comparing the selection length to the total input value length. Consider checking that selectionStart === 0 and selectionEnd === inputValue.length to properly verify the selectAllOnFocus behavior.

Copilot uses AI. Check for mistakes.

test.describe('input type', () => {
test('can set input type to email', async ({ page }) => {
const inputTypeField = page.locator('[name=inputType]');
const applyBtn = page.locator('[name=apply]');

await inputTypeField.fill('email');
await applyBtn.click();

const currencyInput = page.locator('#currency-input');
const type = await currencyInput.getAttribute('type');

expect(type).toBe('email');
});

test('can set input type back to text', async ({ page }) => {
const currencyInput = page.locator('#currency-input');
const type = await currencyInput.getAttribute('type');

expect(type).toBe('text');
});
});

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These input type tests duplicate functionality already covered in the new tests/input-type.spec.ts file. The dedicated input-type test file provides more comprehensive coverage of input type variations including tel, number, email, and formatting verification. Consider removing these tests from base.spec.ts to avoid duplication and reduce maintenance burden.

Suggested change
test.describe('input type', () => {
test('can set input type to email', async ({ page }) => {
const inputTypeField = page.locator('[name=inputType]');
const applyBtn = page.locator('[name=apply]');
await inputTypeField.fill('email');
await applyBtn.click();
const currencyInput = page.locator('#currency-input');
const type = await currencyInput.getAttribute('type');
expect(type).toBe('email');
});
test('can set input type back to text', async ({ page }) => {
const currencyInput = page.locator('#currency-input');
const type = await currencyInput.getAttribute('type');
expect(type).toBe('text');
});
});

Copilot uses AI. Check for mistakes.
Comment thread
ericblade marked this conversation as resolved.
Outdated
test.describe('basic input and formatting', () => {
test('typing numbers formats correctly', async ({ page }) => {
const currencyInput = page.locator('#currency-input');
await currencyInput.focus();
await currencyInput.fill('');
await currencyInput.type('100');

// With precision 2, "100" becomes $1.00
await expect(currencyInput).toHaveValue('$1.00 USD');
});

test('backspace removes digits correctly', async ({ page }) => {
const currencyInput = page.locator('#currency-input');
await currencyInput.focus();
await currencyInput.fill('');
await currencyInput.type('100');

await expect(currencyInput).toHaveValue('$1.00 USD');

await currencyInput.press('Backspace');
await expect(currencyInput).toHaveValue('$0.10 USD');
});

test('decimal point insertion respects precision', async ({ page }) => {
const currencyInput = page.locator('#currency-input');
await currencyInput.focus();
await currencyInput.fill('');
await currencyInput.type('123');

// With precision 2, 123 should be $1.23
await expect(currencyInput).toHaveValue('$1.23 USD');
});
});

test.describe('element attributes', () => {
test('has correct id attribute', async ({ page }) => {
const currencyInput = page.locator('#currency-input');
const id = await currencyInput.getAttribute('id');

expect(id).toBe('currency-input');
});

test('null-input-test element has correct id', async ({ page }) => {
const nullInputTest = page.locator('#null-input-test');
const id = await nullInputTest.getAttribute('id');

expect(id).toBe('null-input-test');
});
});
Comment on lines +351 to +365

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests verify that elements have the expected ID by selecting them with that ID and then checking the ID attribute. This is circular logic - if the locator '#currency-input' finds an element, that element by definition has id="currency-input". These tests don't add value and should be removed or replaced with tests that verify meaningful behavior or properties.

Suggested change
test.describe('element attributes', () => {
test('has correct id attribute', async ({ page }) => {
const currencyInput = page.locator('#currency-input');
const id = await currencyInput.getAttribute('id');
expect(id).toBe('currency-input');
});
test('null-input-test element has correct id', async ({ page }) => {
const nullInputTest = page.locator('#null-input-test');
const id = await nullInputTest.getAttribute('id');
expect(id).toBe('null-input-test');
});
});

Copilot uses AI. Check for mistakes.
});
64 changes: 64 additions & 0 deletions tests/input-type.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { test, expect } from '@playwright/test';
import * as path from 'path';

const projectDir = path.resolve(__dirname, '../');
const filePath = path.join(projectDir, 'examples/index.html');
const fileUrl = `file://${filePath}`;

test.describe('input type variations', () => {
test.beforeEach(async ({ page }) => {
await page.goto(fileUrl);
});

test('default input type is text', async ({ page }) => {
const currencyInput = page.locator('#currency-input');
await expect(currencyInput).toHaveAttribute('type', 'text');
});

test('set input type to tel for mobile keypad', async ({ page }) => {
const inputTypeField = page.locator('[name=inputType]');
const applyBtn = page.locator('[name=apply]');

await inputTypeField.fill('tel');
await applyBtn.click();

const currencyInput = page.locator('#currency-input');
await expect(currencyInput).toHaveAttribute('type', 'tel');

// Ensure formatting still works
await currencyInput.focus();
await currencyInput.fill('');
await currencyInput.type('123');

Copilot AI Dec 14, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using pressSequentially() instead of type() for consistency with other test files and to ensure React events are properly triggered. The comment in tests/controlled-value.spec.ts:22 notes that pressSequentially is preferred to properly trigger React events.

Copilot uses AI. Check for mistakes.
await expect(currencyInput).toHaveValue('$1.23 USD');
});

test('set input type to number (native numeric)', async ({ page }) => {
const inputTypeField = page.locator('[name=inputType]');
const applyBtn = page.locator('[name=apply]');

await inputTypeField.fill('number');
await applyBtn.click();

const currencyInput = page.locator('#currency-input');
await expect(currencyInput).toHaveAttribute('type', 'number');

// Many browsers disallow arbitrary characters and formatting in native number inputs.
// Just verify that switching to number does not throw, then switch back to text.
await inputTypeField.fill('text');
await applyBtn.click();
await expect(currencyInput).toHaveAttribute('type', 'text');
});
Comment on lines +35 to +50

Copilot AI Dec 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test comment on line 45 states "Many browsers disallow arbitrary characters and formatting in native number inputs" but the test doesn't verify this behavior or demonstrate that the component handles it gracefully. The test immediately switches back to 'text' type without attempting any input with type='number'. Consider either adding assertions to verify behavior with number input type, or update the comment to accurately reflect what the test does (simply verifying that switching to and from 'number' type doesn't throw an error).

Copilot uses AI. Check for mistakes.

test('set input type to email (stress case) then back to text', async ({ page }) => {
const inputTypeField = page.locator('[name=inputType]');
const applyBtn = page.locator('[name=apply]');

await inputTypeField.fill('email');
await applyBtn.click();
await expect(page.locator('#currency-input')).toHaveAttribute('type', 'email');

await inputTypeField.fill('text');
await applyBtn.click();
await expect(page.locator('#currency-input')).toHaveAttribute('type', 'text');
});
});