donut chart tests

This commit is contained in:
Nate Kelley 2025-05-06 15:14:53 -06:00
parent 821b3c1b88
commit 5e788012c4
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
3 changed files with 463 additions and 1 deletions

View File

@ -78,3 +78,58 @@ test('Can open sql editor', async ({ page }) => {
await page.getByTestId('edit-chart-button').getByRole('button').click();
await expect(page.locator('div').filter({ hasText: /^Edit chart$/ })).toBeVisible();
});
test('Bar chart span clicking works', async ({ page }) => {
await page.goto('http://localhost:3000/app/metrics/45c17750-2b61-5683-ba8d-ff6c6fefacee/chart');
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.waitForTimeout(55);
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.waitForTimeout(55);
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.waitForTimeout(55);
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.waitForTimeout(55);
await page.getByTestId('segmented-trigger-results').click();
await page.waitForTimeout(55);
await page.getByTestId('edit-chart-button').getByRole('button').click();
await expect(page.getByTestId('metric-view-chart-content').getByRole('img')).toBeVisible();
await page.getByTestId('edit-sql-button').getByRole('button').click();
await page.waitForTimeout(55);
await expect(page.getByText('Copy SQLSaveRun')).toBeVisible();
await page.getByTestId('segmented-trigger-file').click();
await page.waitForTimeout(55);
await expect(
page.getByText('Yearly Sales Revenue - Signature Cycles Products (Last 3 Years + YTD)', {
exact: true
})
).toBeVisible();
await page.getByTestId('edit-chart-button').getByRole('button').click();
await expect(page.getByText('Edit chart')).toBeVisible({ timeout: 15000 });
await page
.locator('div')
.filter({ hasText: /^Edit chart$/ })
.getByRole('button')
.click();
await page.waitForTimeout(55);
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.waitForTimeout(55);
await page
.locator('div')
.filter({ hasText: /^Edit chart$/ })
.getByRole('button')
.click();
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.waitForTimeout(55);
await page
.locator('div')
.filter({ hasText: /^Edit chart$/ })
.getByRole('button')
.click();
await expect(page.locator('body')).toMatchAriaSnapshot(`
- textbox "New chart": Yearly Sales Revenue - Signature Cycles Products (Last 3 Years + YTD)
- text: /Jan 1, \\d+ - May 2, \\d+ • What is the total yearly sales revenue for products supplied by Signature Cycles from \\d+ to present\\? Total Sales Revenue/
- img
`);
});

View File

@ -0,0 +1,407 @@
import { test, expect } from '@playwright/test';
test.describe.serial('Pie chart styling updates', async () => {
test('Pie chart - can put string column on x axis', async ({ page }) => {
await page.goto('http://localhost:3000/app/metrics/88f342bf-19f9-53a9-87c6-804399e69644/chart');
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.getByTestId('select-chart-type-pie').click();
await page.waitForTimeout(250);
const sourceElement = page
.getByTestId('select-axis-available-items-list')
.getByRole('button')
.first();
const targetElement = page
.getByTestId('select-axis-drop-zone-xAxis')
.locator('div')
.filter({ hasText: /^Drag column here$/ });
const sourceBoundingBox = await sourceElement.boundingBox();
const targetBoundingBox = await targetElement.boundingBox();
if (sourceBoundingBox && targetBoundingBox) {
// Start at the center of the source element
await page.mouse.move(
sourceBoundingBox.x + sourceBoundingBox.width / 2,
sourceBoundingBox.y + sourceBoundingBox.height / 2
);
await page.mouse.down();
// Move to target in small increments
const steps = 30;
const dx = (targetBoundingBox.x - sourceBoundingBox.x) / steps;
const dy = (targetBoundingBox.y - sourceBoundingBox.y) / steps;
for (let i = 0; i <= steps; i++) {
await page.mouse.move(
sourceBoundingBox.x + dx * i + sourceBoundingBox.width / 2,
sourceBoundingBox.y + dy * i + sourceBoundingBox.height / 2,
{ steps: 1 }
);
await page.waitForTimeout(1); // Add a small delay between each movement
}
await page.mouse.up();
}
await expect(page.getByRole('button', { name: 'Reset' })).toBeVisible();
await page.getByRole('button', { name: 'Save' }).click();
await page.waitForTimeout(25);
await page.waitForLoadState('networkidle');
await expect(page.getByRole('button', { name: 'Reset' })).toBeHidden();
});
test('Pie chart span clicking works', async ({ page }) => {
await page.goto('http://localhost:3000/app/metrics/88f342bf-19f9-53a9-87c6-804399e69644/chart');
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.waitForTimeout(55);
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.waitForTimeout(55);
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.waitForTimeout(55);
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.waitForTimeout(55);
await page.getByTestId('segmented-trigger-results').click();
await page.waitForTimeout(55);
await page.getByTestId('edit-chart-button').getByRole('button').click();
await expect(page.getByTestId('metric-view-chart-content').getByRole('img')).toBeVisible();
await page.getByTestId('edit-sql-button').getByRole('button').click();
await page.waitForTimeout(55);
await expect(page.getByText('Copy SQLSaveRun')).toBeVisible();
await page.getByTestId('segmented-trigger-file').click();
await page.waitForTimeout(55);
await expect(page.getByText('Top 10 Products by Revenue (').first()).toBeVisible();
await page.getByTestId('edit-chart-button').getByRole('button').click();
await expect(page.getByText('Edit chart')).toBeVisible();
await page
.locator('div')
.filter({ hasText: /^Edit chart$/ })
.getByRole('button')
.click();
await page.waitForTimeout(55);
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.waitForTimeout(55);
await page
.locator('div')
.filter({ hasText: /^Edit chart$/ })
.getByRole('button')
.click();
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.waitForTimeout(55);
await page
.locator('div')
.filter({ hasText: /^Edit chart$/ })
.getByRole('button')
.click();
await expect(page.locator('body')).toMatchAriaSnapshot(`
- textbox "New chart": /Top \\d+ Products by Revenue \\(Last 4 Quarters\\)/
- text: /Q2 \\d+ - Q1 \\d+ • Which were the top \\d+ products by revenue in the last four completed quarters\\? Touring-\\d+ Yellow, \\d+ Road-\\d+-W Yellow, \\d+ Touring-\\d+ Blue, \\d+ Road-\\d+-W Yellow, \\d+ Next 6/
- img
`);
});
test('Pie chart - legend clicks work', async ({ page }) => {
await page.goto('http://localhost:3000/app/metrics/88f342bf-19f9-53a9-87c6-804399e69644/chart');
await page.getByText('Touring-1000 Yellow,').click();
await page.getByText('Road-350-W Yellow, 40').click();
await page.getByText('Touring-1000 Blue,').click();
await page.getByText('Road-350-W Yellow, 48').click();
await expect(page.locator('.dot > .w-4\\.5').first()).toBeVisible();
await expect(page.locator('div:nth-child(2) > div > .dot > .w-4\\.5')).toBeVisible();
await page.locator('.dot > .w-4\\.5').first().click();
await page.getByText('Road-350-W Yellow, 40').click();
await page.getByText('Touring-1000 Blue,').click();
await page.getByText('Road-350-W Yellow, 48').click();
await page.getByText('Next').click();
await expect(
page
.locator('div')
.filter({ hasText: /^Mountain-200 Silver, 42$/ })
.nth(2)
).toBeVisible();
await expect(page.getByTestId('metric-view-chart-content')).toMatchAriaSnapshot(`
- text: /Touring-\\d+ Yellow, \\d+ Road-\\d+-W Yellow, \\d+ Touring-\\d+ Blue, \\d+ Road-\\d+-W Yellow, \\d+ Next 6/
- img
`);
});
test('Pie chart - can disable tooltip', async ({ page }) => {
await page.goto('http://localhost:3000/app/metrics/88f342bf-19f9-53a9-87c6-804399e69644/chart');
await page.getByTestId('edit-chart-button').getByRole('button').click();
await page.getByTestId('select-axis-drop-zone-tooltip').getByRole('button').click();
await expect(page.getByRole('switch')).toHaveAttribute('data-state', 'unchecked');
await page.getByRole('switch').click();
await expect(page.getByRole('switch')).toHaveAttribute('data-state', 'checked');
await expect(page.getByRole('button', { name: 'Save' })).toBeVisible();
await page.getByRole('button', { name: 'Save' }).click();
await page.waitForTimeout(25);
await page.waitForLoadState('networkidle');
await page.reload();
await page.getByTestId('select-axis-drop-zone-tooltip').getByRole('button').click();
await expect(page.getByRole('switch')).toHaveAttribute('data-state', 'checked');
await page.getByRole('switch').click();
await page.getByRole('button', { name: 'Save' }).click();
await page.waitForTimeout(25);
await page.waitForLoadState('networkidle');
});
test('Pie chart - styling updates - can change label as', async ({ page }) => {
await page.goto(
'http://localhost:3000/app/metrics/88f342bf-19f9-53a9-87c6-804399e69644/chart?secondary_view=chart-edit'
);
await page.getByTestId('segmented-trigger-Styling').click();
await expect(page.getByTestId('segmented-trigger-number')).toHaveAttribute(
'data-state',
'active'
);
await expect(
page
.locator('div')
.filter({ hasText: /^Show label$/ })
.getByRole('switch')
).toHaveAttribute('data-state', 'unchecked');
await page.getByTestId('segmented-trigger-percent').click();
await page
.locator('div')
.filter({ hasText: /^Show label$/ })
.getByRole('switch')
.click();
await expect(page.getByTestId('segmented-trigger-percent')).toHaveAttribute(
'data-state',
'active'
);
await page.getByRole('button', { name: 'Reset' }).click();
await expect(page.getByTestId('segmented-trigger-number')).toHaveAttribute(
'data-state',
'active'
);
await page.getByTestId('segmented-trigger-pie').click();
await expect(page.getByTestId('segmented-trigger-pie')).toBeVisible();
await page.getByTestId('segmented-trigger-donut').click();
await page.waitForTimeout(10);
await expect(page.getByTestId('segmented-trigger-donut')).toBeVisible();
await expect(page.getByText('Donut width')).toBeVisible();
await page.getByTestId('segmented-trigger-pie').click();
await expect(page.getByText('Donut width')).not.toBeVisible();
await page.getByRole('button', { name: 'Save' }).click();
await page.waitForTimeout(25);
await page.waitForLoadState('networkidle');
await page.reload();
await page.getByTestId('segmented-trigger-Styling').click();
await expect(page.getByText('Donut width')).not.toBeVisible();
await page.getByTestId('segmented-trigger-donut').click();
await expect(page.getByText('Donut width')).toBeVisible();
await page.getByRole('button', { name: 'Save' }).click();
await page.waitForTimeout(25);
await page.waitForLoadState('networkidle');
});
test('Donut chart - minimum slice percentage', async ({ page }) => {
await page.goto(
'http://localhost:3000/app/metrics/88f342bf-19f9-53a9-87c6-804399e69644/chart?secondary_view=chart-edit'
);
await page.getByTestId('segmented-trigger-Styling').click();
await page
.locator('div')
.filter({ hasText: /^Minimum slice %$/ })
.getByRole('spinbutton')
.click();
await page
.locator('div')
.filter({ hasText: /^Minimum slice %$/ })
.getByRole('spinbutton')
.press('ArrowLeft');
await page
.locator('div')
.filter({ hasText: /^Minimum slice %$/ })
.getByRole('spinbutton')
.fill('80');
await expect(page.getByText('Mountain-200 Black,')).toBeVisible();
await page
.locator('div')
.filter({ hasText: /^Minimum slice %$/ })
.getByRole('spinbutton')
.click();
await page
.locator('div')
.filter({ hasText: /^Minimum slice %$/ })
.getByRole('spinbutton')
.fill('10');
await expect(page.getByText('Mountain-200 Silver,')).toBeVisible();
await expect(page.getByText('Mountain-200 Black, 42')).toBeVisible();
await page.getByRole('button', { name: 'Reset' }).click();
await expect(
page.getByTestId('metric-view-chart-content').getByText('Touring-1000 Yellow,')
).toBeVisible();
});
test('Donut chart - inner label location', async ({ page }) => {
await page.goto(
'http://localhost:3000/app/metrics/88f342bf-19f9-53a9-87c6-804399e69644/chart?secondary_view=chart-edit'
);
await page.getByTestId('segmented-trigger-Styling').click();
await expect(page.getByText('Touring-1000 Yellow,')).toBeVisible();
await expect(page.locator('body')).toMatchAriaSnapshot(`
- textbox "New chart": /Top \\d+ Products by Revenue \\(Last 4 Quarters\\)/
- text: /Q2 \\d+ - Q1 \\d+ • Which were the top \\d+ products by revenue in the last four completed quarters\\? Touring-\\d+ Yellow, \\d+ Road-\\d+-W Yellow, \\d+ Touring-\\d+ Blue, \\d+ Next 7/
- img
`);
await expect(page.locator('body')).toContainText('Sum');
await page.locator('html').click();
await page.getByRole('combobox').filter({ hasText: 'Sum' }).click();
await page.getByRole('option', { name: 'Median' }).click();
await expect(
page
.locator('div')
.filter({ hasText: /^Title$/ })
.getByRole('textbox')
).toHaveValue('Median');
await page.getByRole('button', { name: 'Save' }).click();
await page.waitForTimeout(25);
await page.waitForLoadState('networkidle');
await page.reload();
await page.getByTestId('segmented-trigger-Styling').click();
await expect(
page
.locator('div')
.filter({ hasText: /^Title$/ })
.getByRole('textbox')
).toHaveValue('Median');
await expect(page.getByRole('combobox').filter({ hasText: 'Median' })).toBeVisible();
await page
.locator('div')
.filter({ hasText: /^Show inner label$/ })
.getByRole('switch')
.click();
await expect(page.getByRole('combobox').filter({ hasText: 'Median' })).not.toBeVisible();
await page.getByRole('switch').nth(2).click();
await expect(
page
.locator('div')
.filter({ hasText: /^Title$/ })
.getByRole('textbox')
).toHaveValue('Median');
await page.getByRole('combobox').filter({ hasText: 'Median' }).click();
await page.getByRole('option', { name: 'Sum' }).click();
await expect(
page
.locator('div')
.filter({ hasText: /^Title$/ })
.getByRole('textbox')
).toHaveValue('Sum');
await page.getByRole('button', { name: 'Reset' }).click();
await expect(
page
.locator('div')
.filter({ hasText: /^Title$/ })
.getByRole('textbox')
).toHaveValue('Median');
await page.getByRole('combobox').filter({ hasText: 'Median' }).click();
await page.getByRole('option', { name: 'Sum' }).click();
await page
.locator('div')
.filter({ hasText: /^Title$/ })
.getByRole('textbox')
.click();
await page
.locator('div')
.filter({ hasText: /^Title$/ })
.getByRole('textbox')
.press('ControlOrMeta+a');
await page
.locator('div')
.filter({ hasText: /^Title$/ })
.getByRole('textbox')
.fill('Total');
await page.getByRole('button', { name: 'Save' }).click();
await page.waitForTimeout(25);
await page.waitForLoadState('networkidle');
});
test('Donut chart - legend headers', async ({ page }) => {
await page.goto(
'http://localhost:3000/app/metrics/88f342bf-19f9-53a9-87c6-804399e69644/chart?secondary_view=chart-edit'
);
await page.getByTestId('segmented-trigger-Styling').click();
await page
.locator('div')
.filter({ hasText: /^Show legend$/ })
.getByRole('switch')
.click();
await expect(
page
.locator('div')
.filter({ hasText: /^Show legend$/ })
.getByRole('switch')
).toHaveAttribute('data-state', 'unchecked');
await page.getByRole('combobox').filter({ hasText: 'None' }).click();
await page.getByRole('option', { name: 'Current' }).click();
await expect(
page.locator('#metric-chart-container-88f342bf-19f9-53a9-87c6-804399e69644')
).toContainText('$1,357,446.78');
await page.getByRole('button', { name: 'Reset' }).click();
await expect(
page
.locator('div')
.filter({ hasText: /^Show legend$/ })
.getByRole('switch')
).toHaveAttribute('data-state', 'checked');
});
test('Donut chart - reset', async ({ page }) => {
await page.goto(
'http://localhost:3000/app/metrics/88f342bf-19f9-53a9-87c6-804399e69644/chart?secondary_view=chart-edit'
);
await expect(page.getByTestId('metric-view-chart-content').getByRole('img')).toBeVisible();
await page.getByTestId('select-axis-drop-zone-xAxis').getByRole('button').nth(1).click();
await expect(page.getByText('No valid axis selected')).toBeVisible();
await page.getByTestId('select-chart-type-column').click();
await page.waitForTimeout(55);
const sourceElement = page
.getByTestId('select-axis-available-items-list')
.getByRole('button')
.first();
const targetElement = page
.getByTestId('select-axis-drop-zone-xAxis')
.locator('div')
.filter({ hasText: /^Drag column here$/ });
const sourceBoundingBox = await sourceElement.boundingBox();
const targetBoundingBox = await targetElement.boundingBox();
if (sourceBoundingBox && targetBoundingBox) {
// Start at the center of the source element
await page.mouse.move(
sourceBoundingBox.x + sourceBoundingBox.width / 2,
sourceBoundingBox.y + sourceBoundingBox.height / 2
);
await page.mouse.down();
// Move to target in small increments
const steps = 30;
const dx = (targetBoundingBox.x - sourceBoundingBox.x) / steps;
const dy = (targetBoundingBox.y - sourceBoundingBox.y) / steps;
for (let i = 0; i <= steps; i++) {
await page.mouse.move(
sourceBoundingBox.x + dx * i + sourceBoundingBox.width / 2,
sourceBoundingBox.y + dy * i + sourceBoundingBox.height / 2,
{ steps: 1 }
);
await page.waitForTimeout(1); // Add a small delay between each movement
}
await page.mouse.up();
}
await page.waitForTimeout(55);
await expect(page.getByRole('button', { name: 'Reset' })).toBeVisible();
await page.getByRole('button', { name: 'Save' }).click();
await page.waitForTimeout(25);
await page.waitForLoadState('networkidle');
});
});

View File

@ -21,7 +21,7 @@ export const EditPieLabelLocation = React.memo(
const selectedLabelPosition = useMemo(() => {
return options.find((option) => option.value === pieLabelPosition)?.value || 'outside';
}, [pieLabelPosition]);
const hideLabel = pieLabelPosition === 'none';
const hideLabel = pieLabelPosition === 'none' || !pieLabelPosition;
const onChangeSelect = useMemoizedFn((value: IBusterMetricChartConfig['pieLabelPosition']) => {
onUpdateChartConfig({ pieLabelPosition: value });