mirror of https://github.com/grafana/grafana
Table: Update e2e tests to support tableNextGen (#108184)
* Table: Force tableNextGen to be true for Playwright and false for Cypress * RDG query for body text contains the headers too * add some simple tests for row height * dial in the row height test a little more * more updates * filters, pagination * try this on CI * more updates to the tests * more tests * wait for some sort stuff to flush * replace class selectors for rdg * target the click to the anchor in the headerpull/108316/head^2
parent
4e6730fee6
commit
7626508842
@ -0,0 +1,465 @@ |
||||
{ |
||||
"annotations": { |
||||
"list": [ |
||||
{ |
||||
"builtIn": 1, |
||||
"datasource": { |
||||
"type": "grafana", |
||||
"uid": "-- Grafana --" |
||||
}, |
||||
"enable": true, |
||||
"hide": true, |
||||
"iconColor": "rgba(0, 211, 255, 1)", |
||||
"name": "Annotations & Alerts", |
||||
"type": "dashboard" |
||||
} |
||||
] |
||||
}, |
||||
"editable": true, |
||||
"fiscalYearStartMonth": 0, |
||||
"graphTooltip": 0, |
||||
"id": 138, |
||||
"links": [], |
||||
"panels": [ |
||||
{ |
||||
"datasource": { |
||||
"type": "grafana-testdata-datasource", |
||||
"uid": "PD8C576611E62080A" |
||||
}, |
||||
"fieldConfig": { |
||||
"defaults": { |
||||
"color": { |
||||
"mode": "thresholds" |
||||
}, |
||||
"custom": { |
||||
"align": "auto", |
||||
"cellOptions": { |
||||
"type": "auto", |
||||
"wrapText": false |
||||
}, |
||||
"filterable": true, |
||||
"inspect": false, |
||||
"wrapHeaderText": false |
||||
}, |
||||
"fieldMinMax": true, |
||||
"links": [], |
||||
"mappings": [], |
||||
"thresholds": { |
||||
"mode": "absolute", |
||||
"steps": [ |
||||
{ |
||||
"color": "green", |
||||
"value": 0 |
||||
}, |
||||
{ |
||||
"color": "red", |
||||
"value": 80 |
||||
} |
||||
] |
||||
} |
||||
}, |
||||
"overrides": [ |
||||
{ |
||||
"matcher": { |
||||
"id": "byName", |
||||
"options": "A" |
||||
}, |
||||
"properties": [ |
||||
{ |
||||
"id": "custom.cellOptions", |
||||
"value": { |
||||
"mode": "lcd", |
||||
"type": "gauge" |
||||
} |
||||
}, |
||||
{ |
||||
"id": "min", |
||||
"value": 0 |
||||
}, |
||||
{ |
||||
"id": "max", |
||||
"value": 100 |
||||
}, |
||||
{ |
||||
"id": "custom.width", |
||||
"value": 300 |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"matcher": { |
||||
"id": "byName", |
||||
"options": "Info" |
||||
}, |
||||
"properties": [ |
||||
{ |
||||
"id": "links", |
||||
"value": [ |
||||
{ |
||||
"targetBlank": true, |
||||
"title": "Google this term", |
||||
"url": "https://google.com/search?q=${__value:percentencode}" |
||||
} |
||||
] |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"matcher": { |
||||
"id": "byName", |
||||
"options": "Min" |
||||
}, |
||||
"properties": [] |
||||
}, |
||||
{ |
||||
"matcher": { |
||||
"id": "byName", |
||||
"options": "Max" |
||||
}, |
||||
"properties": [] |
||||
}, |
||||
{ |
||||
"matcher": { |
||||
"id": "byName", |
||||
"options": "State" |
||||
}, |
||||
"properties": [] |
||||
}, |
||||
{ |
||||
"matcher": { |
||||
"id": "byName", |
||||
"options": "Time" |
||||
}, |
||||
"properties": [ |
||||
{ |
||||
"id": "custom.cellOptions", |
||||
"value": { |
||||
"type": "auto" |
||||
} |
||||
}, |
||||
{ |
||||
"id": "unit", |
||||
"value": "dateTimeFromNow" |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"matcher": { |
||||
"id": "byName", |
||||
"options": "Image" |
||||
}, |
||||
"properties": [ |
||||
{ |
||||
"id": "custom.cellOptions", |
||||
"value": { |
||||
"alt": "${__value}", |
||||
"type": "image" |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"matcher": { |
||||
"id": "byRegexp", |
||||
"options": "/(Time|Min|Max|Info|State|Image)/" |
||||
}, |
||||
"properties": [ |
||||
{ |
||||
"id": "custom.width", |
||||
"value": 110 |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"matcher": { |
||||
"id": "byName", |
||||
"options": "Info" |
||||
}, |
||||
"properties": [ |
||||
{ |
||||
"id": "custom.cellOptions", |
||||
"value": { |
||||
"type": "color-text" |
||||
} |
||||
}, |
||||
{ |
||||
"id": "mappings", |
||||
"value": [ |
||||
{ |
||||
"options": { |
||||
"pattern": "up", |
||||
"result": { |
||||
"color": "green", |
||||
"index": 0 |
||||
} |
||||
}, |
||||
"type": "regex" |
||||
}, |
||||
{ |
||||
"options": { |
||||
"pattern": "down", |
||||
"result": { |
||||
"color": "red", |
||||
"index": 1 |
||||
} |
||||
}, |
||||
"type": "regex" |
||||
} |
||||
] |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"matcher": { |
||||
"id": "byName", |
||||
"options": "Min" |
||||
}, |
||||
"properties": [ |
||||
{ |
||||
"id": "custom.cellOptions", |
||||
"value": { |
||||
"mode": "basic", |
||||
"type": "color-background" |
||||
} |
||||
}, |
||||
{ |
||||
"id": "color", |
||||
"value": { |
||||
"fixedColor": "blue", |
||||
"mode": "continuous-YlRd" |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"matcher": { |
||||
"id": "byName", |
||||
"options": "Max" |
||||
}, |
||||
"properties": [ |
||||
{ |
||||
"id": "custom.cellOptions", |
||||
"value": { |
||||
"mode": "gradient", |
||||
"type": "color-background" |
||||
} |
||||
}, |
||||
{ |
||||
"id": "color", |
||||
"value": { |
||||
"mode": "continuous-purples" |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"matcher": { |
||||
"id": "byName", |
||||
"options": "State" |
||||
}, |
||||
"properties": [ |
||||
{ |
||||
"id": "displayName", |
||||
"value": "State" |
||||
}, |
||||
{ |
||||
"id": "custom.hidden", |
||||
"value": true |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"matcher": { |
||||
"id": "byName", |
||||
"options": "Long Text" |
||||
}, |
||||
"properties": [ |
||||
{ |
||||
"id": "custom.cellOptions", |
||||
"value": { |
||||
"type": "auto", |
||||
"wrapText": true |
||||
} |
||||
} |
||||
] |
||||
} |
||||
] |
||||
}, |
||||
"gridPos": { |
||||
"h": 18, |
||||
"w": 24, |
||||
"x": 0, |
||||
"y": 0 |
||||
}, |
||||
"id": 1, |
||||
"options": { |
||||
"cellHeight": "sm", |
||||
"footer": { |
||||
"countRows": false, |
||||
"enablePagination": false, |
||||
"fields": "", |
||||
"reducer": [ |
||||
"max" |
||||
], |
||||
"show": true |
||||
}, |
||||
"frameIndex": 0, |
||||
"showHeader": true, |
||||
"sortBy": [] |
||||
}, |
||||
"pluginVersion": "12.1.0-pre", |
||||
"targets": [ |
||||
{ |
||||
"datasource": { |
||||
"type": "grafana-testdata-datasource", |
||||
"uid": "PD8C576611E62080A" |
||||
}, |
||||
"refId": "A", |
||||
"scenarioId": "random_walk_table" |
||||
}, |
||||
{ |
||||
"csvContent": "Info,Image,Long Text\ndown,https://placecats.com/millie/300/300,\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse tempus et augue et lacinia. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec eu pretium tortor. Cras venenatis sapien sed mauris gravida, ut scelerisque est fringilla. Cras lorem diam, facilisis nec malesuada in, vulputate vel enim. Etiam fringilla nisi quis felis blandit tincidunt. Cras id lacus ornare, ullamcorper nisl eget, bibendum odio. Pellentesque imperdiet, leo a imperdiet venenatis, ligula risus venenatis quam, vel euismod magna nisi sit amet leo.\"\nup,https://placecats.com/neo/300/300,\"Sed imperdiet eget diam sit amet fringilla. Curabitur quis lacus blandit, mollis diam non, accumsan tortor. Aliquam ac tellus eget dui facilisis tempor eu id nulla. Maecenas ultrices turpis eu elementum imperdiet. Fusce eget rhoncus mi, et egestas lectus. Mauris facilisis auctor enim sed malesuada. Maecenas placerat ultricies metus vitae viverra. In hac habitasse platea dictumst. Mauris ipsum nisl, dictum eu aliquam eleifend, rutrum id orci. Nullam eget dui et odio eleifend porttitor.\"\nup fast,https://placecats.com/bella/300/300,\"Proin ac libero vulputate ex vulputate pharetra ut vel lacus. Phasellus quis dolor sed leo finibus scelerisque. Ut vel finibus leo, sed viverra ipsum. Suspendisse vitae rutrum arcu. Donec sed tellus vel lectus bibendum vestibulum. Sed eu felis non velit dictum pulvinar eu et leo. Aenean et dignissim arcu. Nam luctus at neque quis efficitur. Fusce tempus at nibh a imperdiet. Nullam malesuada ac magna at facilisis. Duis pretium aliquam eros. Donec pharetra dignissim dolor non bibendum. Ut gravida mi id urna tempus, at ullamcorper felis vulputate. Duis congue augue ex, sed finibus leo ornare ut. Mauris non quam sodales, dignissim lorem eget, tincidunt mauris. Aliquam ut velit auctor, vestibulum metus sed, mollis massa.\"\ndown fast,https://placecats.com/neo_2/300/300,\"Nullam in pulvinar justo. Nunc dictum arcu ac pellentesque bibendum. Sed in erat turpis. Vestibulum eu orci ac ligula lobortis tempus. Fusce consectetur feugiat magna, eu tempor nibh vestibulum ac. Aliquam erat volutpat. Vivamus sit amet viverra enim. Quisque mollis odio nulla, nec vulputate sem placerat in. Etiam dolor sapien, pulvinar in accumsan at, consequat eget nisi. Nunc condimentum neque magna, congue consectetur dui efficitur interdum. Nam lobortis fringilla maximus. Vestibulum eu dui a velit condimentum eleifend consequat nec lectus.\"", |
||||
"datasource": { |
||||
"type": "grafana-testdata-datasource", |
||||
"uid": "PD8C576611E62080A" |
||||
}, |
||||
"refId": "B", |
||||
"scenarioId": "csv_content" |
||||
} |
||||
], |
||||
"title": "Table - Kitchen Sink", |
||||
"transformations": [ |
||||
{ |
||||
"id": "joinByField", |
||||
"options": { |
||||
"byField": "Info", |
||||
"mode": "outerTabular" |
||||
} |
||||
}, |
||||
{ |
||||
"id": "organize", |
||||
"options": { |
||||
"excludeByName": { |
||||
"A": false |
||||
}, |
||||
"includeByName": {}, |
||||
"indexByName": { |
||||
"A": 7, |
||||
"Image": 5, |
||||
"Info": 1, |
||||
"Long Text": 6, |
||||
"Max A": 3, |
||||
"Min A": 2, |
||||
"State A": 4, |
||||
"Time A": 0 |
||||
}, |
||||
"orderBy": [], |
||||
"orderByMode": "manual", |
||||
"renameByName": { |
||||
"A": "Gauge", |
||||
"Info": "", |
||||
"Max A": "Max", |
||||
"Min A": "Min", |
||||
"State A": "State", |
||||
"Time": "Some really long title that requires wrapping", |
||||
"Time A": "Time", |
||||
"img_url": "Cat" |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"type": "table" |
||||
}, |
||||
{ |
||||
"id": 2, |
||||
"type": "table", |
||||
"title": "Empty Table Panel", |
||||
"gridPos": { |
||||
"x": 0, |
||||
"y": 0, |
||||
"h": 6, |
||||
"w": 24 |
||||
}, |
||||
"fieldConfig": { |
||||
"defaults": { |
||||
"custom": { |
||||
"align": "auto", |
||||
"cellOptions": { |
||||
"type": "auto" |
||||
}, |
||||
"inspect": false, |
||||
"wrapHeaderText": false |
||||
}, |
||||
"mappings": [], |
||||
"thresholds": { |
||||
"mode": "absolute", |
||||
"steps": [ |
||||
{ |
||||
"value": null, |
||||
"color": "green" |
||||
}, |
||||
{ |
||||
"value": 80, |
||||
"color": "red" |
||||
} |
||||
] |
||||
}, |
||||
"color": { |
||||
"mode": "thresholds" |
||||
} |
||||
}, |
||||
"overrides": [] |
||||
}, |
||||
"pluginVersion": "12.1.0-pre", |
||||
"targets": [ |
||||
{ |
||||
"scenarioId": "csv_content", |
||||
"refId": "A", |
||||
"csvContent": "a,b,c" |
||||
} |
||||
], |
||||
"datasource": { |
||||
"uid": "PD8C576611E62080A", |
||||
"type": "grafana-testdata-datasource" |
||||
}, |
||||
"options": { |
||||
"showHeader": true, |
||||
"cellHeight": "sm", |
||||
"footer": { |
||||
"show": false, |
||||
"reducer": [ |
||||
"sum" |
||||
], |
||||
"countRows": false, |
||||
"fields": "" |
||||
} |
||||
} |
||||
} |
||||
], |
||||
"preload": false, |
||||
"schemaVersion": 41, |
||||
"tags": [], |
||||
"templating": { |
||||
"list": [ |
||||
{ |
||||
"baseFilters": [], |
||||
"datasource": { |
||||
"type": "grafana-testdata-datasource", |
||||
"uid": "PD8C576611E62080A" |
||||
}, |
||||
"filters": [], |
||||
"name": "Filters", |
||||
"type": "adhoc" |
||||
} |
||||
] |
||||
}, |
||||
"time": { |
||||
"from": "now-6h", |
||||
"to": "now" |
||||
}, |
||||
"timepicker": {}, |
||||
"timezone": "", |
||||
"title": "Panel Tests - Table - Kitchen Sink", |
||||
"uid": "dcb9f5e9-8066-4397-889e-864b99555dbb", |
||||
"version": 1 |
||||
} |
@ -0,0 +1,331 @@ |
||||
import { Page, Locator } from '@playwright/test'; |
||||
|
||||
import { test, expect } from '@grafana/plugin-e2e'; |
||||
|
||||
test.use({ |
||||
viewport: { width: 1600, height: 1080 }, |
||||
featureToggles: { |
||||
tableNextGen: true, |
||||
}, |
||||
}); |
||||
|
||||
// helper utils
|
||||
const getCell = async (loc: Page | Locator, rowIdx: number, colIdx: number) => |
||||
loc |
||||
.getByRole('row') |
||||
.nth(rowIdx) |
||||
.getByRole(rowIdx === 0 ? 'columnheader' : 'gridcell') |
||||
.nth(colIdx); |
||||
|
||||
const getCellHeight = async (loc: Page | Locator, rowIdx: number, colIdx: number) => { |
||||
const cell = await getCell(loc, rowIdx, colIdx); |
||||
return (await cell.boundingBox())?.height ?? 0; |
||||
}; |
||||
|
||||
test.describe( |
||||
'Panels test: Table - Kitchen Sink', |
||||
{ |
||||
tag: ['@panels'], |
||||
}, |
||||
() => { |
||||
test('Tests word wrap, hover overflow, and cell inspect', async ({ gotoDashboardPage, selectors, page }) => { |
||||
const dashboardPage = await gotoDashboardPage({ |
||||
uid: 'dcb9f5e9-8066-4397-889e-864b99555dbb', |
||||
queryParams: new URLSearchParams({ editPanel: '1' }), |
||||
}); |
||||
|
||||
await expect( |
||||
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) |
||||
).toBeVisible(); |
||||
|
||||
// text wrapping is enabled by default on this panel.
|
||||
await expect(getCellHeight(page, 1, 5)).resolves.toBeGreaterThan(100); |
||||
|
||||
// toggle the lorem ipsum column's wrap text toggle and confirm that the height shrinks.
|
||||
await dashboardPage |
||||
.getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Wrap text')) |
||||
.last() |
||||
.click(); |
||||
await expect(getCellHeight(page, 1, 5)).resolves.toBeLessThan(100); |
||||
|
||||
// test that hover overflow works.
|
||||
const loremIpsumCell = await getCell(page, 1, 5); |
||||
await loremIpsumCell.hover(); |
||||
await expect(getCellHeight(page, 1, 5)).resolves.toBeGreaterThan(100); |
||||
await (await getCell(page, 1, 6)).hover(); |
||||
await expect(getCellHeight(page, 1, 5)).resolves.toBeLessThan(100); |
||||
|
||||
// enable cell inspect, confirm that hover no longer triggers.
|
||||
await dashboardPage |
||||
.getByGrafanaSelector( |
||||
selectors.components.PanelEditor.OptionsPane.fieldLabel('Cell options Cell value inspect') |
||||
) |
||||
.first() |
||||
.locator('label[for="custom.inspect"]') |
||||
.click(); |
||||
await loremIpsumCell.hover(); |
||||
await expect(getCellHeight(page, 1, 5)).resolves.toBeLessThan(100); |
||||
|
||||
// click cell inspect, check that cell inspection pops open in the side as we'd expect.
|
||||
await loremIpsumCell.getByLabel('Inspect value').click(); |
||||
const loremIpsumText = await loremIpsumCell.textContent(); |
||||
expect(loremIpsumText).toBeDefined(); |
||||
await expect(page.getByRole('dialog').getByText(loremIpsumText!)).toBeVisible(); |
||||
}); |
||||
|
||||
test('Tests visibility and display name via overrides', async ({ gotoDashboardPage, selectors, page }) => { |
||||
const dashboardPage = await gotoDashboardPage({ |
||||
uid: 'dcb9f5e9-8066-4397-889e-864b99555dbb', |
||||
queryParams: new URLSearchParams({ editPanel: '1' }), |
||||
}); |
||||
|
||||
await expect( |
||||
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) |
||||
).toBeVisible(); |
||||
|
||||
// confirm that "State" column is hidden by default.
|
||||
expect(page.getByRole('row').nth(0)).not.toContainText('State'); |
||||
|
||||
// toggle the "State" column visibility and test that it appears before re-hiding it.
|
||||
// FIXME this selector is utterly godawful, but there's no way to give testIds or aria-labels or anything to
|
||||
// the panel editor builder. we should fix that to make e2e's easier to write for our team.
|
||||
const hideStateColumnSwitch = page.locator('[id="Override 12"]').locator('label').last(); |
||||
await hideStateColumnSwitch.click(); |
||||
expect(page.getByRole('row').nth(0)).toContainText('State'); |
||||
|
||||
// now change the display name of the "State" column.
|
||||
// FIXME it would be good to have a better selector here too.
|
||||
const displayNameInput = page.locator('[id="Override 12"]').locator('input[value="State"]').last(); |
||||
await displayNameInput.fill('State (renamed)'); |
||||
await displayNameInput.press('Enter'); |
||||
expect(page.getByRole('row').nth(0)).toContainText('State (renamed)'); |
||||
}); |
||||
|
||||
// we test niche cases for sorting, filtering, pagination, etc. in a unit tests already.
|
||||
// we mainly want to test the happiest paths for these in e2es as well to check for integration
|
||||
// issues, but the unit tests can confirm that the internal logic works as expected much more quickly and thoroughly.
|
||||
// hashtag testing pyramid.
|
||||
test('Tests sorting by column', async ({ gotoDashboardPage, selectors, page }) => { |
||||
const dashboardPage = await gotoDashboardPage({ |
||||
uid: 'dcb9f5e9-8066-4397-889e-864b99555dbb', |
||||
queryParams: new URLSearchParams({ editPanel: '1' }), |
||||
}); |
||||
|
||||
await expect( |
||||
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) |
||||
).toBeVisible(); |
||||
|
||||
// click the "State" column header to sort it.
|
||||
const stateColumnHeader = await getCell(page, 0, 1); |
||||
|
||||
await stateColumnHeader.getByText('Info').click(); |
||||
await expect(stateColumnHeader).toHaveAttribute('aria-sort', 'ascending'); |
||||
expect(getCell(page, 1, 1)).resolves.toContainText('down'); // down or down fast
|
||||
|
||||
await stateColumnHeader.getByText('Info').click(); |
||||
await expect(stateColumnHeader).toHaveAttribute('aria-sort', 'descending'); |
||||
expect(getCell(page, 1, 1)).resolves.toContainText('up'); // up or up fast
|
||||
|
||||
await stateColumnHeader.getByText('Info').click(); |
||||
await expect(stateColumnHeader).not.toHaveAttribute('aria-sort'); |
||||
}); |
||||
|
||||
test('Tests filtering within a column', async ({ gotoDashboardPage, selectors, page }) => { |
||||
const dashboardPage = await gotoDashboardPage({ |
||||
uid: 'dcb9f5e9-8066-4397-889e-864b99555dbb', |
||||
queryParams: new URLSearchParams({ editPanel: '1' }), |
||||
}); |
||||
|
||||
await expect( |
||||
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) |
||||
).toBeVisible(); |
||||
|
||||
const stateColumnHeader = page.getByRole('columnheader').filter({ hasText: 'Info' }); |
||||
|
||||
// get the first value in the "State" column, filter it out, then check that it went away.
|
||||
const firstStateValue = (await (await getCell(page, 1, 1)).textContent())!; |
||||
await stateColumnHeader |
||||
.getByTestId(selectors.components.Panels.Visualization.TableNG.Filters.HeaderButton) |
||||
.click(); |
||||
const filterContainer = dashboardPage.getByGrafanaSelector( |
||||
selectors.components.Panels.Visualization.TableNG.Filters.Container |
||||
); |
||||
|
||||
await expect(filterContainer).toBeVisible(); |
||||
|
||||
// select all, then click the first value to unselect it, filtering it out.
|
||||
await filterContainer.getByTestId(selectors.components.Panels.Visualization.TableNG.Filters.SelectAll).click(); |
||||
await filterContainer.getByTitle(firstStateValue, { exact: true }).locator('label').click(); |
||||
await filterContainer.getByRole('button', { name: 'Ok' }).click(); |
||||
|
||||
// make sure the filter container closed when we clicked "Ok".
|
||||
await expect(filterContainer).not.toBeVisible(); |
||||
|
||||
// did it actually filter out our value?
|
||||
await expect(getCell(page, 1, 1)).resolves.not.toHaveText(firstStateValue); |
||||
}); |
||||
|
||||
test('Tests pagination, row height adjustment', async ({ gotoDashboardPage, selectors, page }) => { |
||||
const rowRe = /([\d]+) - ([\d]+) of ([\d]+) rows/; |
||||
const getRowStatus = async (page: Page | Locator) => { |
||||
const text = (await page.getByText(rowRe).textContent()) ?? ''; |
||||
const match = text.match(rowRe); |
||||
return { |
||||
start: parseInt(match?.[1] ?? '0', 10), |
||||
end: parseInt(match?.[2] ?? '0', 10), |
||||
total: parseInt(match?.[3] ?? '0', 10), |
||||
}; |
||||
}; |
||||
|
||||
const dashboardPage = await gotoDashboardPage({ |
||||
uid: 'dcb9f5e9-8066-4397-889e-864b99555dbb', |
||||
queryParams: new URLSearchParams({ editPanel: '1' }), |
||||
}); |
||||
|
||||
await expect( |
||||
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) |
||||
).toBeVisible(); |
||||
|
||||
await page |
||||
.getByLabel(selectors.components.PanelEditor.OptionsPane.fieldLabel(`Enable pagination`), { exact: true }) |
||||
.click(); |
||||
|
||||
// because of text wrapping, we're guaranteed to only be showing a single row when we enable pagination.
|
||||
await expect(page.getByText(/([\d]+) - ([\d]+) of ([\d]+) rows/)).toBeVisible(); |
||||
|
||||
// disable text wrap and see the number of rows.
|
||||
await dashboardPage |
||||
.getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Wrap text')) |
||||
.last() |
||||
.click(); |
||||
|
||||
// any number of rows that is not "1" is allowed here, we don't want to police the exact number of rows that
|
||||
// are rendered since there are tons of factors which could effect this. we do want to grab this number for comparison
|
||||
// in a second, though.
|
||||
const smallRowStatus = await getRowStatus(page); |
||||
expect(smallRowStatus.end).toBeGreaterThan(1); |
||||
expect(page.getByRole('grid').getByRole('row')).toHaveCount(smallRowStatus.end + 1); |
||||
|
||||
// change cell height to Large
|
||||
await dashboardPage |
||||
.getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Table Cell height')) |
||||
.locator('input') |
||||
.last() |
||||
.click(); |
||||
const largeRowStatus = await getRowStatus(page); |
||||
expect(largeRowStatus.end).toBeLessThan(smallRowStatus.end); |
||||
expect(page.getByRole('grid').getByRole('row')).toHaveCount(largeRowStatus.end + 1); |
||||
|
||||
// click a page over with the directional nav
|
||||
await page.getByLabel('next page').click(); |
||||
const nextPageStatus = await getRowStatus(page); |
||||
expect(nextPageStatus.start).toBe(largeRowStatus.end + 1); |
||||
expect(nextPageStatus.end).toBe(largeRowStatus.end * 2); |
||||
expect(nextPageStatus.total).toBe(largeRowStatus.total); |
||||
|
||||
// click a page number
|
||||
await page |
||||
.getByTestId('data-testid panel content') |
||||
.getByRole('navigation') |
||||
.getByText('4', { exact: true }) |
||||
.click(); |
||||
const fourthPageStatus = await getRowStatus(page); |
||||
expect(fourthPageStatus.start).toBe(largeRowStatus.end * 3 + 1); |
||||
expect(fourthPageStatus.end).toBe(largeRowStatus.end * 4); |
||||
expect(fourthPageStatus.total).toBe(largeRowStatus.total); |
||||
}); |
||||
|
||||
test('Tests DataLinks (single and multi) and actions', async ({ gotoDashboardPage, selectors, page }) => { |
||||
const addDataLink = async (title: string, url: string) => { |
||||
await dashboardPage |
||||
.getByGrafanaSelector( |
||||
selectors.components.PanelEditor.OptionsPane.fieldLabel('Data links and actions Data links') |
||||
) |
||||
.locator('button') |
||||
.filter({ hasText: 'Add link' }) |
||||
.click(); |
||||
|
||||
// DataLinks dialog has popped open - fill it in and add a global datalink.
|
||||
await expect(page.getByRole('dialog')).toBeVisible(); |
||||
await page.getByRole('dialog').locator('#link-title').fill(title); |
||||
await page.getByRole('dialog').locator('#data-link-input [contenteditable="true"]').focus(); |
||||
await page.getByRole('dialog').locator('#data-link-input [contenteditable="true"]').fill(url); |
||||
await page.getByRole('dialog').locator('#data-link-input [contenteditable="true"]').blur(); |
||||
await page.getByRole('dialog').getByRole('button', { name: 'Save' }).click(); |
||||
await expect(page.getByRole('dialog')).not.toBeVisible(); |
||||
}; |
||||
|
||||
const dashboardPage = await gotoDashboardPage({ |
||||
uid: 'dcb9f5e9-8066-4397-889e-864b99555dbb', |
||||
queryParams: new URLSearchParams({ editPanel: '1' }), |
||||
}); |
||||
|
||||
await expect( |
||||
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) |
||||
).toBeVisible(); |
||||
|
||||
// disable text wrapping for this test to make it easier to click the links, the long lorem ipsum
|
||||
// can push the links off the screen.
|
||||
await dashboardPage |
||||
.getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Wrap text')) |
||||
.last() |
||||
.click(); |
||||
|
||||
// Info column has a single DataLink by default.
|
||||
const infoCell = await getCell(page, 1, 1); |
||||
await expect(infoCell.locator('a')).toBeVisible(); |
||||
expect(infoCell.locator('a')).toHaveAttribute('href'); |
||||
expect(infoCell.locator('a')).not.toHaveAttribute('aria-haspopup'); |
||||
|
||||
// now, add a DataLink to the whole table
|
||||
await addDataLink('Test link', 'https://grafana.com'); |
||||
|
||||
// add a DataLink to the whole table, all cells will now have a single link.
|
||||
const colCount = await page.getByRole('row').nth(1).getByRole('gridcell').count(); |
||||
for (let colIdx = 0; colIdx < colCount; colIdx++) { |
||||
const cell = await getCell(page, 1, colIdx); |
||||
await expect(cell.locator('a')).toBeVisible(); |
||||
expect(cell.locator('a')).toHaveAttribute('href'); |
||||
expect(cell.locator('a')).not.toHaveAttribute('aria-haspopup', 'menu'); |
||||
} |
||||
|
||||
const headerContainer = dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer); |
||||
|
||||
// add another data link. now we'll check that the multi-link popups work.
|
||||
await addDataLink('Another test link', 'https://grafana.com/foo'); |
||||
|
||||
// loop thru the columns, click the links, observe that the tooltip appears, and close the tooltip.
|
||||
for (let colIdx = 0; colIdx < colCount; colIdx++) { |
||||
const cell = await getCell(page, 1, colIdx); |
||||
if (colIdx === 1) { |
||||
// the Info column should still have its single link.
|
||||
expect(cell.locator('a')).not.toHaveAttribute('aria-haspopup', 'menu'); |
||||
continue; |
||||
} |
||||
|
||||
await cell.locator('a').click({ force: true }); |
||||
await expect(page.getByTestId(selectors.components.DataLinksActionsTooltip.tooltipWrapper)).toBeVisible(); |
||||
|
||||
await headerContainer.click(); // convenient just to click the header to close the tooltip.
|
||||
await expect(page.getByTestId(selectors.components.DataLinksActionsTooltip.tooltipWrapper)).not.toBeVisible(); |
||||
} |
||||
|
||||
// add an Action to the whole table and check that the action button is added to the tooltip.
|
||||
// TODO -- saving for another day.
|
||||
}); |
||||
|
||||
test('Empty Table panel', async ({ gotoDashboardPage, selectors }) => { |
||||
const dashboardPage = await gotoDashboardPage({ |
||||
uid: 'dcb9f5e9-8066-4397-889e-864b99555dbb', |
||||
queryParams: new URLSearchParams({ editPanel: '2' }), |
||||
}); |
||||
|
||||
await expect( |
||||
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.PanelDataErrorMessage) |
||||
).toBeVisible(); |
||||
await expect( |
||||
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('Table - Kitchen Sink')) |
||||
).not.toBeVisible(); |
||||
}); |
||||
} |
||||
); |
@ -0,0 +1,29 @@ |
||||
import { test, expect } from '@grafana/plugin-e2e'; |
||||
|
||||
test.use({ |
||||
viewport: { width: 1280, height: 1080 }, |
||||
featureToggles: { |
||||
tableNextGen: true, |
||||
}, |
||||
}); |
||||
|
||||
test.describe( |
||||
'Panels test: Table - Sparkline', |
||||
{ |
||||
tag: ['@panels'], |
||||
}, |
||||
() => { |
||||
test('Tests sparkline tables are successfully rendered', async ({ gotoDashboardPage, selectors, page }) => { |
||||
await gotoDashboardPage({ |
||||
uid: 'd6373b49-1957-4f00-9218-ee2120d3ecd9', |
||||
queryParams: new URLSearchParams({ editPanel: '2' }), |
||||
}); |
||||
|
||||
await expect(page.getByRole('grid')).toBeVisible(); |
||||
|
||||
const uplotCount = await page.locator('.uplot').count(); |
||||
const rowCount = await page.getByRole('row').count(); |
||||
expect(uplotCount).toBe(rowCount - 1); |
||||
}); |
||||
} |
||||
); |
Loading…
Reference in new issue