import { test, expect } from '@playwright/test'; import { createNewSheet, clickCell, typeInCell, getCellText, mod } from './helpers'; test.describe('Sheets - Paste Special', () => { test.beforeEach(async ({ page }) => { await createNewSheet(page); }); // --- Dialog Opening --- test('Cmd+Shift+V opens Paste Special dialog', async ({ page }) => { // Copy something first so paste special has data await typeInCell(page, 'A1', 'Data'); await clickCell(page, 'A1'); await page.keyboard.press(`${mod(page)}+c`); await page.waitForTimeout(300); // Select destination await clickCell(page, 'A3'); // Open Paste Special await page.keyboard.press(`${mod(page)}+Shift+v`); const dialog = page.locator('.paste-special-dialog'); await expect(dialog).toBeVisible({ timeout: 3000 }); }); test('Paste Special dialog has all five mode options', async ({ page }) => { await typeInCell(page, 'A1', 'Data'); await clickCell(page, 'A1'); await page.keyboard.press(`${mod(page)}+c`); await page.waitForTimeout(300); await clickCell(page, 'A3'); await page.keyboard.press(`${mod(page)}+Shift+v`); const dialog = page.locator('.paste-special-dialog'); await expect(dialog).toBeVisible({ timeout: 3000 }); await expect(dialog).toContainText('All'); await expect(dialog).toContainText('Values Only'); await expect(dialog).toContainText('Formulas Only'); await expect(dialog).toContainText('Formatting Only'); await expect(dialog).toContainText('Transpose'); }); test('Cancel button closes Paste Special dialog', async ({ page }) => { await typeInCell(page, 'A1', 'Data'); await clickCell(page, 'A1'); await page.keyboard.press(`${mod(page)}+c`); await page.waitForTimeout(300); await clickCell(page, 'A3'); await page.keyboard.press(`${mod(page)}+Shift+v`); const dialog = page.locator('.paste-special-dialog'); await expect(dialog).toBeVisible({ timeout: 3000 }); await page.click('.paste-special-cancel'); await expect(dialog).not.toBeVisible({ timeout: 3000 }); }); // --- Values Only --- test('Values Only pastes computed values without formulas', async ({ page }) => { await typeInCell(page, 'A1', '10'); await typeInCell(page, 'A2', '=A1*2'); // Verify formula works expect(await getCellText(page, 'A2')).toBe('20'); // Copy A2 (has formula) await clickCell(page, 'A2'); await page.keyboard.press(`${mod(page)}+c`); await page.waitForTimeout(300); // Paste Special → Values Only into A4 await clickCell(page, 'A4'); await page.keyboard.press(`${mod(page)}+Shift+v`); const dialog = page.locator('.paste-special-dialog'); await expect(dialog).toBeVisible({ timeout: 3000 }); await dialog.locator('input[value="values_only"]').click(); await page.click('.paste-special-submit'); // A4 should have value "20" but not the formula expect(await getCellText(page, 'A4')).toBe('20'); // Check formula bar — should not show a formula await clickCell(page, 'A4'); const barValue = await page.inputValue('#formula-input'); expect(barValue).toBe('20'); // plain value, not "=A1*2" }); // --- Formatting Only --- test('Formatting Only pastes style without values', async ({ page }) => { // Create a bold cell await typeInCell(page, 'A1', 'Bold'); await clickCell(page, 'A1'); await page.click('#tb-bold'); // Copy A1 await page.keyboard.press(`${mod(page)}+c`); await page.waitForTimeout(300); // Type something in B1 without formatting await typeInCell(page, 'B1', 'Plain'); // Paste Special → Formatting Only into B1 await clickCell(page, 'B1'); await page.keyboard.press(`${mod(page)}+Shift+v`); const dialog = page.locator('.paste-special-dialog'); await expect(dialog).toBeVisible({ timeout: 3000 }); await dialog.locator('input[value="formatting_only"]').click(); await page.click('.paste-special-submit'); // B1 should keep its value but gain bold formatting expect(await getCellText(page, 'B1')).toBe('Plain'); const cellDisplay = page.locator('td[data-id="B1"] .cell-display'); await expect(cellDisplay).toHaveCSS('font-weight', '600'); }); // --- Transpose --- test('Transpose paste rotates rows to columns', async ({ page }) => { // Create a row of data: A1=X, B1=Y, C1=Z await typeInCell(page, 'A1', 'X'); await typeInCell(page, 'B1', 'Y'); await typeInCell(page, 'C1', 'Z'); // Select A1:C1 and copy await clickCell(page, 'A1'); await page.keyboard.down('Shift'); await clickCell(page, 'C1'); await page.keyboard.up('Shift'); await page.keyboard.press(`${mod(page)}+c`); await page.waitForTimeout(300); // Paste Special → Transpose into A3 await clickCell(page, 'A3'); await page.keyboard.press(`${mod(page)}+Shift+v`); const dialog = page.locator('.paste-special-dialog'); await expect(dialog).toBeVisible({ timeout: 3000 }); await dialog.locator('input[value="transpose"]').click(); await page.click('.paste-special-submit'); // Row should be transposed to column: A3=X, A4=Y, A5=Z expect(await getCellText(page, 'A3')).toBe('X'); expect(await getCellText(page, 'A4')).toBe('Y'); expect(await getCellText(page, 'A5')).toBe('Z'); }); // --- All (Default) --- test('All mode pastes both values and formatting', async ({ page }) => { await typeInCell(page, 'A1', 'Styled'); await clickCell(page, 'A1'); await page.click('#tb-bold'); await page.keyboard.press(`${mod(page)}+c`); await page.waitForTimeout(300); await clickCell(page, 'A3'); await page.keyboard.press(`${mod(page)}+Shift+v`); const dialog = page.locator('.paste-special-dialog'); await expect(dialog).toBeVisible({ timeout: 3000 }); // "All" should be selected by default const allRadio = dialog.locator('input[value="all"]'); await expect(allRadio).toBeChecked(); await page.click('.paste-special-submit'); expect(await getCellText(page, 'A3')).toBe('Styled'); const cellDisplay = page.locator('td[data-id="A3"] .cell-display'); await expect(cellDisplay).toHaveCSS('font-weight', '600'); }); });