diff --git a/apps/docs/e2e/expects.ts b/apps/docs/e2e/expects.ts index 559dd16..90fd435 100644 --- a/apps/docs/e2e/expects.ts +++ b/apps/docs/e2e/expects.ts @@ -1,8 +1,5 @@ import {expect, type Page, type Locator} from '@playwright/test'; -const _dragSteps = 10; -const _dragAmplitude = 40.0; - const _calculateElementCenter = async (element: Locator) => { const bounds = await element.evaluate((el) => el.getBoundingClientRect()); const x = bounds.x + bounds.width / 2; @@ -10,20 +7,13 @@ const _calculateElementCenter = async (element: Locator) => { return {x, y}; }; -type KnobDragAssertionArgs = [Locator, {valueNow: number; page: Page}]; - +type KnobDragAssertionProps = {knob: Locator; valueNow: number; page: Page}; const _knobDragsCorrectly = (direction: 'up' | 'down' | 'left' | 'right') => - async ( - knob: Locator, - { - valueNow, - page, - }: { - valueNow: number; - page: Page; - }, - ) => { + async ({knob, valueNow, page}: KnobDragAssertionProps) => { + const dragSteps = 10; + const dragAmplitude = 40.0; + // It's necessary to hover over the knob and scroll it into view, // so then we can calculate its bounds in the viewport properly await knob.hover(); @@ -32,72 +22,86 @@ const _knobDragsCorrectly = x = direction === 'right' - ? x + _dragAmplitude + ? x + dragAmplitude : direction === 'left' - ? x - _dragAmplitude + ? x - dragAmplitude : x; y = direction === 'down' - ? y + _dragAmplitude + ? y + dragAmplitude : direction === 'up' - ? y - _dragAmplitude + ? y - dragAmplitude : y; await page.mouse.down(); - await page.mouse.move(x, y, {steps: _dragSteps}); + await page.mouse.move(x, y, {steps: dragSteps}); await page.mouse.up(); if (direction === 'up' || direction === 'right') { - await knobValueIsMoreThan(knob, {value: valueNow}); + await knobValueIsMoreThan({knob, value: valueNow}); } else { - await knobValueIsLessThan(knob, {value: valueNow}); + await knobValueIsLessThan({knob, value: valueNow}); } }; -export const knobValueTextIs = async ( - knob: Locator, - {knobOutput, valueText}: {knobOutput?: Locator; valueText: string}, -) => { +export const knobValueTextIs = async ({ + knob, + knobOutput, + valueText, +}: { + knob: Locator; + knobOutput?: Locator; + valueText: string; +}) => { expect(await knob.getAttribute('aria-valuetext')).toBe(valueText); if (knobOutput) { await expect(knobOutput).toHaveText(valueText); } }; -export const knobValueIsEqualTo = async ( - knob: Locator, - {valueNow}: {valueNow: number}, -) => { +export const knobValueIsEqualTo = async ({ + knob, + valueNow, +}: { + knob: Locator; + valueNow: number; +}) => { expect(await knob.getAttribute('aria-valuenow')).toBe(`${valueNow}`); }; -export const knobValueIsLessThan = async ( - knob: Locator, - {value}: {value: number}, -) => { +export const knobValueIsLessThan = async ({ + knob, + value, +}: { + knob: Locator; + value: number; +}) => { expect(Number(await knob.getAttribute('aria-valuenow'))).toBeLessThan(value); }; -export const knobValueIsMoreThan = async ( - knob: Locator, - {value}: {value: number}, -) => { +export const knobValueIsMoreThan = async ({ + knob, + value, +}: { + knob: Locator; + value: number; +}) => { expect(Number(await knob.getAttribute('aria-valuenow'))).toBeGreaterThan( value, ); }; -export const knobDragsDownCorrectly = async (...args: KnobDragAssertionArgs) => - _knobDragsCorrectly('down')(...args); +export const knobDragsDownCorrectly = async (props: KnobDragAssertionProps) => + _knobDragsCorrectly('down')(props); -export const knobDragsUpCorrectly = async (...args: KnobDragAssertionArgs) => - _knobDragsCorrectly('up')(...args); +export const knobDragsUpCorrectly = async (props: KnobDragAssertionProps) => + _knobDragsCorrectly('up')(props); -export const knobDragsLeftCorrectly = async (...args: KnobDragAssertionArgs) => - _knobDragsCorrectly('left')(...args); +export const knobDragsLeftCorrectly = async (props: KnobDragAssertionProps) => + _knobDragsCorrectly('left')(props); -export const knobDragsRightCorrectly = async (...args: KnobDragAssertionArgs) => - _knobDragsCorrectly('right')(...args); +export const knobDragsRightCorrectly = async (props: KnobDragAssertionProps) => + _knobDragsCorrectly('right')(props); export const sourceCodeLinkIsValid = async ({ link, diff --git a/apps/docs/e2e/index.spec.ts b/apps/docs/e2e/index.spec.ts index 729ef23..8a0be7c 100644 --- a/apps/docs/e2e/index.spec.ts +++ b/apps/docs/e2e/index.spec.ts @@ -14,7 +14,7 @@ test.describe('Page title', () => { test.describe('Repository link', () => { test('has correct reference', async ({page}) => { - const repositoryLink = locators.repositoryLink(page); + const repositoryLink = locators.repositoryLink({page}); await expect(repositoryLink).toBeVisible(); await expect(repositoryLink).toHaveAttribute( 'href', @@ -23,7 +23,7 @@ test.describe('Repository link', () => { }); test('opens GitHub repository page', async ({page}) => { - const repositoryLink = locators.repositoryLink(page); + const repositoryLink = locators.repositoryLink({page}); await repositoryLink.click(); const repositoryPage = await page.waitForEvent('popup'); @@ -35,26 +35,26 @@ test.describe('Repository link', () => { test.describe('Decorative knobs', () => { test('have correct default values and drag behaviour', async ({page}) => { - const knobStone = locators.decorativeKnobStone(page); - const knobPink = locators.decorativeKnobPink(page); - const knobGreen = locators.decorativeKnobGreen(page); - const knobSky = locators.decorativeKnobSky(page); - - await expects.knobValueIsEqualTo(knobStone, {valueNow: 0}); - await expects.knobValueTextIs(knobStone, {valueText: '0 units'}); - await expects.knobDragsUpCorrectly(knobStone, {valueNow: 0, page}); - - await expects.knobValueIsEqualTo(knobPink, {valueNow: 40}); - await expects.knobValueTextIs(knobPink, {valueText: '40 units'}); - await expects.knobDragsDownCorrectly(knobPink, {valueNow: 40, page}); - - await expects.knobValueIsEqualTo(knobGreen, {valueNow: 80}); - await expects.knobValueTextIs(knobGreen, {valueText: '80 units'}); - await expects.knobDragsUpCorrectly(knobGreen, {valueNow: 80, page}); - - await expects.knobValueIsEqualTo(knobSky, {valueNow: 100}); - await expects.knobValueTextIs(knobSky, {valueText: '100 units'}); - await expects.knobDragsDownCorrectly(knobSky, {valueNow: 100, page}); + const knobStone = locators.decorativeKnobStone({page}); + const knobPink = locators.decorativeKnobPink({page}); + const knobGreen = locators.decorativeKnobGreen({page}); + const knobSky = locators.decorativeKnobSky({page}); + + await expects.knobValueIsEqualTo({knob: knobStone, valueNow: 0}); + await expects.knobValueTextIs({knob: knobStone, valueText: '0 units'}); + await expects.knobDragsUpCorrectly({knob: knobStone, valueNow: 0, page}); + + await expects.knobValueIsEqualTo({knob: knobPink, valueNow: 40}); + await expects.knobValueTextIs({knob: knobPink, valueText: '40 units'}); + await expects.knobDragsDownCorrectly({knob: knobPink, valueNow: 40, page}); + + await expects.knobValueIsEqualTo({knob: knobGreen, valueNow: 80}); + await expects.knobValueTextIs({knob: knobGreen, valueText: '80 units'}); + await expects.knobDragsUpCorrectly({knob: knobGreen, valueNow: 80, page}); + + await expects.knobValueIsEqualTo({knob: knobSky, valueNow: 100}); + await expects.knobValueTextIs({knob: knobSky, valueText: '100 units'}); + await expects.knobDragsDownCorrectly({knob: knobSky, valueNow: 100, page}); }); }); @@ -62,13 +62,13 @@ test.describe('"Simple linear knob" example', () => { let container: Locator; test.beforeEach(({page}) => { - container = locators.exampleContainer(page, 'Simple linear knob'); + container = locators.exampleContainer({page, name: 'Simple linear knob'}); }); test('has "View source" link leading to "KnobPercentage.tsx" source code file', async ({ page, }) => { - const viewSourceLink = locators.exampleViewSourceLink(container); + const viewSourceLink = locators.exampleViewSourceLink({container}); await expects.sourceCodeLinkIsValid({ link: viewSourceLink, page, @@ -80,21 +80,21 @@ test.describe('"Simple linear knob" example', () => { let knob: Locator; test.beforeEach(() => { - knob = locators.exampleKnob(container, 'Dry/Wet'); + knob = locators.exampleKnob({container, name: 'Dry/Wet'}); }); test('has correct default value', async () => { - const knobOutput = locators.exampleKnobOutput(container); - await expects.knobValueIsEqualTo(knob, {valueNow: 50}); - await expects.knobValueTextIs(knob, {knobOutput, valueText: '50%'}); + const knobOutput = locators.exampleKnobOutput({container}); + await expects.knobValueIsEqualTo({knob, valueNow: 50}); + await expects.knobValueTextIs({knob, knobOutput, valueText: '50%'}); }); test('has correct drag down behaviour', async ({page}) => { - await expects.knobDragsDownCorrectly(knob, {valueNow: 50, page}); + await expects.knobDragsDownCorrectly({knob, valueNow: 50, page}); }); test('has correct drag up behaviour', async ({page}) => { - await expects.knobDragsUpCorrectly(knob, {valueNow: 50, page}); + await expects.knobDragsUpCorrectly({knob, valueNow: 50, page}); }); }); }); @@ -103,13 +103,13 @@ test.describe('"Interpolated knob" example', () => { let container: Locator; test.beforeEach(({page}) => { - container = locators.exampleContainer(page, 'Interpolated knob'); + container = locators.exampleContainer({page, name: 'Interpolated knob'}); }); test('has "View source" link leading to "KnobFrequency.tsx" source code file', async ({ page, }) => { - const viewSourceLink = locators.exampleViewSourceLink(container); + const viewSourceLink = locators.exampleViewSourceLink({container}); await expects.sourceCodeLinkIsValid({ link: viewSourceLink, page, @@ -121,21 +121,21 @@ test.describe('"Interpolated knob" example', () => { let knob: Locator; test.beforeEach(() => { - knob = locators.exampleKnob(container, 'Frequency'); + knob = locators.exampleKnob({container, name: 'Frequency'}); }); test('has correct default value', async () => { - const knobOutput = locators.exampleKnobOutput(container); - await expects.knobValueIsEqualTo(knob, {valueNow: 440}); - await expects.knobValueTextIs(knob, {knobOutput, valueText: '440 Hz'}); + const knobOutput = locators.exampleKnobOutput({container}); + await expects.knobValueIsEqualTo({knob, valueNow: 440}); + await expects.knobValueTextIs({knob, knobOutput, valueText: '440 Hz'}); }); test('has correct drag down behaviour', async ({page}) => { - await expects.knobDragsDownCorrectly(knob, {valueNow: 440, page}); + await expects.knobDragsDownCorrectly({knob, valueNow: 440, page}); }); test('has correct drag up behaviour', async ({page}) => { - await expects.knobDragsUpCorrectly(knob, {valueNow: 440, page}); + await expects.knobDragsUpCorrectly({knob, valueNow: 440, page}); }); }); }); @@ -144,13 +144,16 @@ test.describe('"Horizontal orientation" example', () => { let container: Locator; test.beforeEach(({page}) => { - container = locators.exampleContainer(page, 'Horizontal orientation'); + container = locators.exampleContainer({ + page, + name: 'Horizontal orientation', + }); }); test('has "View source" link leading to "KnobPercentageHorizontal.tsx" source code file', async ({ page, }) => { - const viewSourceLink = locators.exampleViewSourceLink(container); + const viewSourceLink = locators.exampleViewSourceLink({container}); await expects.sourceCodeLinkIsValid({ link: viewSourceLink, page, @@ -162,21 +165,21 @@ test.describe('"Horizontal orientation" example', () => { let knob: Locator; test.beforeEach(() => { - knob = locators.exampleKnob(container, 'X'); + knob = locators.exampleKnob({container, name: 'X'}); }); test('has correct default value', async () => { - const knobOutput = locators.exampleKnobOutput(container); - await expects.knobValueIsEqualTo(knob, {valueNow: 50}); - await expects.knobValueTextIs(knob, {knobOutput, valueText: '50%'}); + const knobOutput = locators.exampleKnobOutput({container}); + await expects.knobValueIsEqualTo({knob, valueNow: 50}); + await expects.knobValueTextIs({knob, knobOutput, valueText: '50%'}); }); test('has correct drag left behaviour', async ({page}) => { - await expects.knobDragsLeftCorrectly(knob, {valueNow: 50, page}); + await expects.knobDragsLeftCorrectly({knob, valueNow: 50, page}); }); test('has correct drag right behaviour', async ({page}) => { - await expects.knobDragsRightCorrectly(knob, {valueNow: 50, page}); + await expects.knobDragsRightCorrectly({knob, valueNow: 50, page}); }); }); }); diff --git a/apps/docs/e2e/locators.ts b/apps/docs/e2e/locators.ts index eb541e3..58af899 100644 --- a/apps/docs/e2e/locators.ts +++ b/apps/docs/e2e/locators.ts @@ -1,40 +1,41 @@ import {type Locator, type Page} from '@playwright/test'; -const repositoryLink = (page: Page) => +const repositoryLink = ({page}: {page: Page}) => page.getByRole('link', { name: 'GitHub repository satelllte/react-knob-headless', }); -const decorativeKnobStone = (page: Page) => +const decorativeKnobStone = ({page}: {page: Page}) => page.getByRole('slider', { name: "Decorative knob with 'stone' theme", }); -const decorativeKnobPink = (page: Page) => +const decorativeKnobPink = ({page}: {page: Page}) => page.getByRole('slider', { name: "Decorative knob with 'pink' theme", }); -const decorativeKnobGreen = (page: Page) => +const decorativeKnobGreen = ({page}: {page: Page}) => page.getByRole('slider', { name: "Decorative knob with 'green' theme", }); -const decorativeKnobSky = (page: Page) => +const decorativeKnobSky = ({page}: {page: Page}) => page.getByRole('slider', { name: "Decorative knob with 'sky' theme", }); -const exampleContainer = (page: Page, name: string) => +const exampleContainer = ({page, name}: {page: Page; name: string}) => page.getByRole('heading', {name}).locator('..'); -const exampleViewSourceLink = (container: Locator) => +const exampleViewSourceLink = ({container}: {container: Locator}) => container.getByRole('link', {name: 'View source'}); -const exampleKnob = (container: Locator, name: string) => +const exampleKnob = ({container, name}: {container: Locator; name: string}) => container.getByRole('slider', {name}); -const exampleKnobOutput = (container: Locator) => container.getByRole('status'); +const exampleKnobOutput = ({container}: {container: Locator}) => + container.getByRole('status'); export const locators = { repositoryLink,