Full document, spreadsheet, slideshow, and diagram tooling
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 236 lines 8.1 kB view raw
1import { test, expect } from '@playwright/test'; 2import { createNewSheet, clickCell, typeInCell, getCellText } from './helpers'; 3 4test.describe('Sheets - Advanced Features', () => { 5 test.beforeEach(async ({ page }) => { 6 await createNewSheet(page); 7 }); 8 9 test('multi-sheet tabs: create new sheet and switch between tabs', async ({ page }) => { 10 // Should start with "Sheet 1" tab 11 await expect(page.locator('.sheet-tab').first()).toContainText('Sheet 1'); 12 13 // Add a new sheet 14 await page.click('#add-sheet'); 15 16 // Should now have two tabs 17 const tabs = page.locator('.sheet-tab'); 18 await expect(tabs).toHaveCount(2); 19 await expect(tabs.last()).toContainText('Sheet 2'); 20 21 // Type something in Sheet 2 22 await typeInCell(page, 'A1', 'Sheet 2 Data'); 23 expect(await getCellText(page, 'A1')).toBe('Sheet 2 Data'); 24 25 // Switch back to Sheet 1 26 await tabs.first().click(); 27 28 // A1 should be empty on Sheet 1 29 const text = await getCellText(page, 'A1'); 30 expect(text).toBe(''); 31 32 // Switch back to Sheet 2 and verify data persisted 33 await tabs.last().click(); 34 expect(await getCellText(page, 'A1')).toBe('Sheet 2 Data'); 35 }); 36 37 test('column resize by dragging column border', async ({ page }) => { 38 // Get initial width of column A 39 const colHeader = page.locator('thead th[data-col="1"]'); 40 const initialBox = await colHeader.boundingBox(); 41 expect(initialBox).toBeTruthy(); 42 43 // Find the resize handle 44 const handle = page.locator('.col-resize-handle[data-resize-col="1"]'); 45 await expect(handle).toBeVisible(); 46 47 // Drag the handle to resize 48 const handleBox = await handle.boundingBox(); 49 expect(handleBox).toBeTruthy(); 50 51 await page.mouse.move(handleBox!.x + handleBox!.width / 2, handleBox!.y + handleBox!.height / 2); 52 await page.mouse.down(); 53 await page.mouse.move(handleBox!.x + 50, handleBox!.y + handleBox!.height / 2, { steps: 5 }); 54 await page.mouse.up(); 55 56 // Column should be wider now 57 const newBox = await colHeader.boundingBox(); 58 expect(newBox!.width).toBeGreaterThan(initialBox!.width); 59 }); 60 61 test('right-click context menu appears on cell', async ({ page }) => { 62 await clickCell(page, 'A1'); 63 await page.click('td[data-id="A1"]', { button: 'right' }); 64 65 // Context menu should appear 66 const contextMenu = page.locator('.context-menu'); 67 await expect(contextMenu).toBeVisible({ timeout: 5000 }); 68 69 // Should have menu items 70 await expect(contextMenu.locator('.context-menu-item, [role="menuitem"]').first()).toBeVisible(); 71 72 // Dismiss by clicking elsewhere 73 await page.keyboard.press('Escape'); 74 }); 75 76 test('cell merge via toolbar button', async ({ page }) => { 77 // Select a range A1:B2 78 await clickCell(page, 'A1'); 79 await page.keyboard.down('Shift'); 80 await clickCell(page, 'B2'); 81 await page.keyboard.up('Shift'); 82 83 // Click merge button 84 await page.click('#tb-merge'); 85 86 // The merged cell should have colspan/rowspan attributes 87 const mergedTd = page.locator('td[data-id="A1"]'); 88 const colspan = await mergedTd.getAttribute('colspan'); 89 const rowspan = await mergedTd.getAttribute('rowspan'); 90 expect(colspan).toBe('2'); 91 expect(rowspan).toBe('2'); 92 }); 93 94 test('freeze rows via overflow menu', async ({ page }) => { 95 // Select row 2 96 await clickCell(page, 'A2'); 97 98 // Open overflow menu 99 await page.click('#overflow-toggle'); 100 await expect(page.locator('.toolbar-overflow-menu')).toBeVisible(); 101 102 // Click freeze rows 103 await page.click('#tb-freeze-rows'); 104 105 // There should be frozen row styling on row 1 106 await expect(page.locator('td.frozen-row').first()).toBeVisible({ timeout: 5000 }); 107 }); 108 109 test('freeze columns via overflow menu', async ({ page }) => { 110 // Select column B (col 2) 111 await clickCell(page, 'B1'); 112 113 // Open overflow menu 114 await page.click('#overflow-toggle'); 115 await expect(page.locator('.toolbar-overflow-menu')).toBeVisible(); 116 117 // Click freeze cols 118 await page.click('#tb-freeze-cols'); 119 120 // Column A should be frozen 121 await expect(page.locator('td.frozen-col').first()).toBeVisible({ timeout: 5000 }); 122 }); 123 124 test('conditional formatting dialog opens', async ({ page }) => { 125 await clickCell(page, 'A1'); 126 127 // Open overflow menu 128 await page.click('#overflow-toggle'); 129 await expect(page.locator('.toolbar-overflow-menu')).toBeVisible(); 130 131 // Click conditional formatting 132 await page.click('#tb-cf'); 133 134 // A dialog/modal should appear 135 const cfDialog = page.locator('.cf-dialog, .modal, [class*="conditional"]'); 136 await expect(cfDialog.first()).toBeVisible({ timeout: 5000 }); 137 }); 138 139 test('data validation dialog opens', async ({ page }) => { 140 await clickCell(page, 'A1'); 141 142 // Open overflow menu 143 await page.click('#overflow-toggle'); 144 await expect(page.locator('.toolbar-overflow-menu')).toBeVisible(); 145 146 // Click data validation 147 await page.click('#tb-validation'); 148 149 // A dialog/modal should appear 150 const validationDialog = page.locator('.validation-dialog, .modal, [class*="validation"]'); 151 await expect(validationDialog.first()).toBeVisible({ timeout: 5000 }); 152 }); 153 154 test('chart button opens chart creation', async ({ page }) => { 155 // Fill some data for chart 156 await typeInCell(page, 'A1', 'Q1'); 157 await typeInCell(page, 'A2', 'Q2'); 158 await typeInCell(page, 'A3', 'Q3'); 159 await typeInCell(page, 'B1', '100'); 160 await typeInCell(page, 'B2', '200'); 161 await typeInCell(page, 'B3', '150'); 162 163 // Select the data range 164 await clickCell(page, 'A1'); 165 await page.keyboard.down('Shift'); 166 await clickCell(page, 'B3'); 167 await page.keyboard.up('Shift'); 168 169 // Click chart button 170 await page.click('#tb-chart'); 171 172 // Chart dialog or chart element should appear 173 const chartDialog = page.locator('.chart-dialog, .modal, [class*="chart"]'); 174 await expect(chartDialog.first()).toBeVisible({ timeout: 5000 }); 175 }); 176 177 test('sort ascending via toolbar button', async ({ page }) => { 178 await typeInCell(page, 'A1', 'Charlie'); 179 await typeInCell(page, 'A2', 'Alice'); 180 await typeInCell(page, 'A3', 'Bob'); 181 182 // Select column A 183 await clickCell(page, 'A1'); 184 185 // Click sort ascending 186 await page.click('#tb-sort-asc'); 187 188 // After sort, A1 should be Alice 189 expect(await getCellText(page, 'A1')).toBe('Alice'); 190 expect(await getCellText(page, 'A2')).toBe('Bob'); 191 expect(await getCellText(page, 'A3')).toBe('Charlie'); 192 }); 193 194 test('sort descending via toolbar button', async ({ page }) => { 195 await typeInCell(page, 'A1', 'Alice'); 196 await typeInCell(page, 'A2', 'Charlie'); 197 await typeInCell(page, 'A3', 'Bob'); 198 199 await clickCell(page, 'A1'); 200 await page.click('#tb-sort-desc'); 201 202 expect(await getCellText(page, 'A1')).toBe('Charlie'); 203 expect(await getCellText(page, 'A2')).toBe('Bob'); 204 expect(await getCellText(page, 'A3')).toBe('Alice'); 205 }); 206 207 test('striped rows toggle via overflow menu', async ({ page }) => { 208 // Open overflow menu 209 await page.click('#overflow-toggle'); 210 await expect(page.locator('.toolbar-overflow-menu')).toBeVisible(); 211 212 // Click striped rows 213 await page.click('#tb-striped'); 214 215 // Even rows should have striped class 216 await expect(page.locator('td.striped-row').first()).toBeVisible({ timeout: 5000 }); 217 }); 218 219 test('status bar shows selection stats', async ({ page }) => { 220 await typeInCell(page, 'A1', '10'); 221 await typeInCell(page, 'A2', '20'); 222 await typeInCell(page, 'A3', '30'); 223 224 // Select range A1:A3 225 await clickCell(page, 'A1'); 226 await page.keyboard.down('Shift'); 227 await clickCell(page, 'A3'); 228 await page.keyboard.up('Shift'); 229 230 // Status bar should show stats (sum, average, count) 231 const statusBar = page.locator('#status-bar'); 232 await expect(statusBar).toBeVisible({ timeout: 5000 }); 233 const statsText = await page.locator('#status-bar-stats').textContent(); 234 expect(statsText).toContain('60'); // sum 235 }); 236});