Full document, spreadsheet, slideshow, and diagram tooling
1import { test, expect } from '@playwright/test';
2import { createNewSheet, clickCell, typeInCell, getCellText } from './helpers';
3
4test.describe('Sheets - Clipboard', () => {
5 test.beforeEach(async ({ page, context }) => {
6 // Grant clipboard permissions
7 await context.grantPermissions(['clipboard-read', 'clipboard-write']);
8 await createNewSheet(page);
9 });
10
11 test('copy cell and paste to another cell', async ({ page }) => {
12 await typeInCell(page, 'A1', 'CopyMe');
13
14 // Select A1 and copy
15 await clickCell(page, 'A1');
16 await page.keyboard.press('Meta+c');
17
18 // Select B1 and paste
19 await clickCell(page, 'B1');
20 await page.keyboard.press('Meta+v');
21
22 // B1 should now have the same value
23 await expect(page.locator('td[data-id="B1"] .cell-display')).toContainText('CopyMe', { timeout: 5000 });
24
25 // A1 should still have its value (copy, not cut)
26 expect(await getCellText(page, 'A1')).toBe('CopyMe');
27 });
28
29 test('cut cell clears original', async ({ page }) => {
30 await typeInCell(page, 'A1', 'CutMe');
31
32 // Select A1 and cut
33 await clickCell(page, 'A1');
34 await page.keyboard.press('Meta+x');
35
36 // Select B1 and paste
37 await clickCell(page, 'B1');
38 await page.keyboard.press('Meta+v');
39
40 // B1 should have the value
41 await expect(page.locator('td[data-id="B1"] .cell-display')).toContainText('CutMe', { timeout: 5000 });
42
43 // A1 should be empty (it was cut)
44 const a1Text = await getCellText(page, 'A1');
45 expect(a1Text).toBe('');
46 });
47
48 test('copy multiple cells and paste', async ({ page }) => {
49 await typeInCell(page, 'A1', 'One');
50 await typeInCell(page, 'A2', 'Two');
51 await typeInCell(page, 'A3', 'Three');
52
53 // Select range A1:A3
54 await clickCell(page, 'A1');
55 await page.keyboard.down('Shift');
56 await clickCell(page, 'A3');
57 await page.keyboard.up('Shift');
58
59 // Copy
60 await page.keyboard.press('Meta+c');
61
62 // Paste to B1
63 await clickCell(page, 'B1');
64 await page.keyboard.press('Meta+v');
65
66 // Verify all values pasted
67 await expect(page.locator('td[data-id="B1"] .cell-display')).toContainText('One', { timeout: 5000 });
68 expect(await getCellText(page, 'B2')).toBe('Two');
69 expect(await getCellText(page, 'B3')).toBe('Three');
70 });
71
72 test('copy cell with formula pastes computed value or adjusted formula', async ({ page }) => {
73 await typeInCell(page, 'A1', '10');
74 await typeInCell(page, 'A2', '=A1*2');
75
76 // A2 should show 20
77 expect(await getCellText(page, 'A2')).toBe('20');
78
79 // Copy A2
80 await clickCell(page, 'A2');
81 await page.keyboard.press('Meta+c');
82
83 // Paste to B2
84 await clickCell(page, 'B2');
85 await page.keyboard.press('Meta+v');
86
87 // B2 should have a value (either the formula adjusted or the value pasted)
88 const b2Text = await getCellText(page, 'B2');
89 expect(b2Text).toBeTruthy();
90 });
91
92 test('delete key clears selected cell', async ({ page }) => {
93 await typeInCell(page, 'A1', 'DeleteMe');
94 expect(await getCellText(page, 'A1')).toBe('DeleteMe');
95
96 await clickCell(page, 'A1');
97 await page.keyboard.press('Delete');
98
99 // Cell should be empty
100 const text = await getCellText(page, 'A1');
101 expect(text).toBe('');
102 });
103
104 test('backspace clears selected cell', async ({ page }) => {
105 await typeInCell(page, 'A1', 'ClearMe');
106 await clickCell(page, 'A1');
107 await page.keyboard.press('Backspace');
108
109 // Should start editing with empty content (Backspace enters edit mode)
110 // Press Escape or Enter to confirm
111 await page.keyboard.press('Escape');
112
113 // Cell may still have content if Backspace enters edit mode
114 // Just verify the action doesn't crash
115 });
116});