# Search Sorting Template Tests sorting results by name, date, and price. ## Prerequisites - Search results for `{{searchQuery}}` with multiple items - App running at `{{baseUrl}}` --- ## TypeScript ```typescript import { test, expect } from '@playwright/test'; test.describe('Search Sorting', () => { test.beforeEach(async ({ page }) => { await page.goto('{{baseUrl}}/search?q={{searchQuery}}'); }); // Happy path: sort by name A-Z test('sorts results alphabetically A-Z', async ({ page }) => { await page.getByRole('combobox', { name: /sort by/i }).selectOption('name_asc'); await expect(page).toHaveURL(/sort=name_asc/); const names = page.getByTestId('result-name'); const first = await names.first().textContent(); const second = await names.nth(1).textContent(); expect(first!.localeCompare(second!)).toBeLessThanOrEqual(0); }); // Happy path: sort by name Z-A test('sorts results alphabetically Z-A', async ({ page }) => { await page.getByRole('combobox', { name: /sort by/i }).selectOption('name_desc'); const names = page.getByTestId('result-name'); const first = await names.first().textContent(); const second = await names.nth(1).textContent(); expect(first!.localeCompare(second!)).toBeGreaterThanOrEqual(0); }); // Happy path: sort by date newest test('sorts results by newest date first', async ({ page }) => { await page.getByRole('combobox', { name: /sort by/i }).selectOption('date_desc'); await expect(page).toHaveURL(/sort=date_desc/); const dates = page.getByTestId('result-date'); const firstDate = new Date(await dates.first().getAttribute('datetime') ?? ''); const secondDate = new Date(await dates.nth(1).getAttribute('datetime') ?? ''); expect(firstDate.getTime()).toBeGreaterThanOrEqual(secondDate.getTime()); }); // Happy path: sort by price low-high test('sorts by price low to high', async ({ page }) => { await page.getByRole('combobox', { name: /sort by/i }).selectOption('price_asc'); const prices = page.getByTestId('result-price'); const firstText = await prices.first().textContent() ?? ''; const secondText = await prices.nth(1).textContent() ?? ''; const first = parseFloat(firstText.replace(/[^0-9.]/g, '')); const second = parseFloat(secondText.replace(/[^0-9.]/g, '')); expect(first).toBeLessThanOrEqual(second); }); // Happy path: sort by price high-low test('sorts by price high to low', async ({ page }) => { await page.getByRole('combobox', { name: /sort by/i }).selectOption('price_desc'); const prices = page.getByTestId('result-price'); const firstText = await prices.first().textContent() ?? ''; const secondText = await prices.nth(1).textContent() ?? ''; const first = parseFloat(firstText.replace(/[^0-9.]/g, '')); const second = parseFloat(secondText.replace(/[^0-9.]/g, '')); expect(first).toBeGreaterThanOrEqual(second); }); // Happy path: sort persists with filters test('sort selection persists when filter applied', async ({ page }) => { await page.getByRole('combobox', { name: /sort by/i }).selectOption('price_asc'); await page.getByRole('checkbox', { name: '{{filterCategory}}' }).check(); await expect(page).toHaveURL(/sort=price_asc/); await expect(page.getByRole('combobox', { name: /sort by/i })).toHaveValue('price_asc'); }); // Edge case: default sort is relevance test('default sort is relevance', async ({ page }) => { await expect(page.getByRole('combobox', { name: /sort by/i })).toHaveValue('relevance'); }); }); ``` --- ## JavaScript ```javascript const { test, expect } = require('@playwright/test'); test.describe('Search Sorting', () => { test.beforeEach(async ({ page }) => { await page.goto('{{baseUrl}}/search?q={{searchQuery}}'); }); test('sorts alphabetically A-Z', async ({ page }) => { await page.getByRole('combobox', { name: /sort by/i }).selectOption('name_asc'); await expect(page).toHaveURL(/sort=name_asc/); const names = page.getByTestId('result-name'); const first = await names.first().textContent(); const second = await names.nth(1).textContent(); expect(first.localeCompare(second)).toBeLessThanOrEqual(0); }); test('sorts by price low to high', async ({ page }) => { await page.getByRole('combobox', { name: /sort by/i }).selectOption('price_asc'); const prices = page.getByTestId('result-price'); const a = parseFloat((await prices.first().textContent()).replace(/[^0-9.]/g, '')); const b = parseFloat((await prices.nth(1).textContent()).replace(/[^0-9.]/g, '')); expect(a).toBeLessThanOrEqual(b); }); test('default sort is relevance', async ({ page }) => { await expect(page.getByRole('combobox', { name: /sort by/i })).toHaveValue('relevance'); }); }); ``` ## Variants | Variant | Description | |---------|-------------| | Name A-Z | First result ≤ second alphabetically | | Name Z-A | First result ≥ second alphabetically | | Date newest | Dates in descending order | | Price low-high | Prices in ascending order | | Price high-low | Prices in descending order | | Sort + filter | Sort param persists when filter applied | | Default sort | Relevance selected by default |