From 28c716c1595324135d917e753835f57c1673d0b3 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Wed, 7 May 2025 12:38:35 -0600 Subject: [PATCH] save slider tests --- web/playwright-tests/invite-user.test.ts | 54 ++++++++++++++ .../scatter-chart-updates.test.ts | 49 +++++++++++++ .../api/buster_rest/users/queryRequests.ts | 2 - .../ui/charts/BusterChartJS/ChartJSTheme.ts | 5 +- web/src/components/ui/slider/Slider.tsx | 71 ++++++++++--------- .../StylingAppStyling/EditScatterDotSize.tsx | 5 +- .../SelectChartType/SelectChartType.tsx | 1 + 7 files changed, 150 insertions(+), 37 deletions(-) create mode 100644 web/playwright-tests/invite-user.test.ts create mode 100644 web/playwright-tests/scatter-chart-updates.test.ts diff --git a/web/playwright-tests/invite-user.test.ts b/web/playwright-tests/invite-user.test.ts new file mode 100644 index 000000000..efb2bf4ee --- /dev/null +++ b/web/playwright-tests/invite-user.test.ts @@ -0,0 +1,54 @@ +import { test, expect } from '@playwright/test'; + +test('Invite User', async ({ page }) => { + await page.goto('http://localhost:3000/app/home'); + await page + .locator('div') + .filter({ hasText: /^Invite people$/ }) + .first() + .click(); + await page.getByRole('textbox', { name: 'buster@bluthbananas.com,' }).click(); + await page + .getByRole('textbox', { name: 'buster@bluthbananas.com,' }) + .fill('nate+integration-test@buser.so'); + await page.getByRole('button', { name: 'Send invites' }).click(); + await page.waitForLoadState('networkidle'); + await expect(page.getByText('Invites sent').first()).toBeVisible({ timeout: 3000 }); + + await page.getByRole('button').filter({ hasText: /^$/ }).first().click(); + await page.getByRole('link', { name: 'Users' }).click(); + await expect(page.getByRole('link', { name: 'nate+integration-test@buser.' })).toBeVisible(); + await expect(page.getByRole('main')).toMatchAriaSnapshot(` + - img + - text: nate+integration-test@buser.so Restricted Querier + `); + + await page.getByRole('link', { name: 'nate+integration-test@buser.' }).click(); + + await expect(page.getByText('nate+integration-test@buser.so')).toBeVisible(); +}); + +test('Can change user role', async ({ page }) => { + await page.goto('http://localhost:3000/app/settings/users'); + await page.getByRole('link', { name: 'B blake blake@buster.so' }).click(); + await expect(page.getByText('blake@buster.so')).toBeVisible(); + await expect(page.getByRole('combobox')).toHaveText(/Querier/); + await page.getByRole('combobox').click(); + await page.getByRole('option', { name: 'Workspace Admin' }).click(); + await expect( + page.locator('.text-text-secondary > div:nth-child(2) > .text-text-secondary').first() + ).toBeVisible(); + await page.waitForTimeout(25); + await page.waitForLoadState('networkidle'); + await page.reload(); + await expect( + page.locator('.text-text-secondary > div:nth-child(2) > .text-text-secondary').first() + ).toBeVisible(); + await page.getByRole('combobox').click(); + await page.getByRole('option', { name: 'Querier', exact: true }).click(); + await expect( + page.locator('.text-text-secondary > div:nth-child(2) > .text-text-secondary').first() + ).toBeVisible(); + await page.waitForTimeout(15); + await page.waitForLoadState('networkidle'); +}); diff --git a/web/playwright-tests/scatter-chart-updates.test.ts b/web/playwright-tests/scatter-chart-updates.test.ts new file mode 100644 index 000000000..61a8c02f0 --- /dev/null +++ b/web/playwright-tests/scatter-chart-updates.test.ts @@ -0,0 +1,49 @@ +import { test, expect } from '@playwright/test'; + +test.describe.serial('Create a scatter plot with a question', () => { + const question = `I want to understand if there's a relationship between how much an employee sells and the number of orders they process. Can you generate a scatter plot showing each employee's total sales amount on one axis and their total number of orders on the other axis for the last 12 months?`; + let scatterURL = ''; + test(`I can create a scatter plot with a question: ${question}`, async ({ page }) => { + await page.goto('http://localhost:3000/app/home'); + await page.getByRole('textbox', { name: 'Ask Buster a question...' }).click(); + await page.getByRole('textbox', { name: 'Ask Buster a question...' }).fill(question); + await page.getByRole('main').getByRole('button').click(); + await page.waitForTimeout(5000); + await expect(page.getByRole('link', { name: 'Reasoning link' })).toBeVisible(); + await expect(page.getByTestId('metric-view-chart-content').getByRole('img')).toBeVisible({ + timeout: 240000 + }); + await expect(page.getByTestId('share-button')).toBeVisible(); + await expect(page.getByTestId('save-to-dashboard-button')).toBeVisible(); + await expect(page.getByTestId('edit-sql-button').getByRole('button')).toBeVisible(); + await expect(page.getByTestId('edit-chart-button').getByRole('button')).toBeVisible(); + + await page.getByTestId('edit-chart-button').getByRole('button').click(); + await expect(page.getByTestId('select-chart-type-scatter')).toBeVisible(); + await expect(page.getByTestId('select-chart-type-scatter')).toHaveAttribute( + 'data-state', + 'selected' + ); + + const url = page.url(); + await page.goto( + 'http://localhost:3000/app/chats/21cd1170-7ecf-4796-9d5e-9828285c62ec/metrics/0023f1a3-58fe-53f7-9f23-07f20868e1b4/chart?secondary_view=chart-edit' + ); + scatterURL = url; + }); + + scatterURL = + 'http://localhost:3000/app/chats/21cd1170-7ecf-4796-9d5e-9828285c62ec/metrics/0023f1a3-58fe-53f7-9f23-07f20868e1b4/chart'; + test(`I can update the scatter plot`, async ({ page }) => { + await page.goto(scatterURL); + + await page.getByTestId('edit-chart-button').getByRole('button').click(); + await expect(page.getByTestId('select-chart-type-scatter')).toBeVisible(); + await expect(page.getByTestId('select-chart-type-scatter')).toHaveAttribute( + 'data-state', + 'selected' + ); + await page.getByTestId('segmented-trigger-Styling').click(); + // + }); +}); diff --git a/web/src/api/buster_rest/users/queryRequests.ts b/web/src/api/buster_rest/users/queryRequests.ts index dc7914f12..9feac8974 100644 --- a/web/src/api/buster_rest/users/queryRequests.ts +++ b/web/src/api/buster_rest/users/queryRequests.ts @@ -166,13 +166,11 @@ export const prefetchGetUserList = async ( }; export const useInviteUser = () => { - const { openSuccessMessage } = useBusterNotifications(); const queryClient = useQueryClient(); return useMutation({ mutationFn: inviteUser, onSuccess: () => { - openSuccessMessage('Invites sent'); const user = queryClient.getQueryData(queryKeys.userGetUserMyself.queryKey); const teamId = user?.organizations?.[0]?.id; if (teamId) { diff --git a/web/src/components/ui/charts/BusterChartJS/ChartJSTheme.ts b/web/src/components/ui/charts/BusterChartJS/ChartJSTheme.ts index 9711ba9b9..4211c7591 100644 --- a/web/src/components/ui/charts/BusterChartJS/ChartJSTheme.ts +++ b/web/src/components/ui/charts/BusterChartJS/ChartJSTheme.ts @@ -73,6 +73,7 @@ ChartJS.register( ); ChartJS.defaults.responsive = true; +ChartJS.defaults.clip = false; ChartJS.defaults.resizeDelay = 7; ChartJS.defaults.maintainAspectRatio = false; ChartJS.defaults.color = color; @@ -85,11 +86,11 @@ ChartJS.defaults.font = { }; [ - ChartJS.defaults.scales.category, + (ChartJS.defaults.scales.category, ChartJS.defaults.scales.linear, ChartJS.defaults.scales.logarithmic, ChartJS.defaults.scales.time, - ChartJS.defaults.scales.timeseries + ChartJS.defaults.scales.timeseries) ].forEach((scale) => { scale.title = { ...scale.title, diff --git a/web/src/components/ui/slider/Slider.tsx b/web/src/components/ui/slider/Slider.tsx index 3320e7c3b..d9d59bc27 100644 --- a/web/src/components/ui/slider/Slider.tsx +++ b/web/src/components/ui/slider/Slider.tsx @@ -10,6 +10,7 @@ import { } from '@/components/ui/tooltip/TooltipBase'; import { cn } from '@/lib/utils'; +import { ErrorBoundary } from '../error'; export interface SliderProps extends React.ComponentPropsWithoutRef { min?: number; @@ -34,8 +35,10 @@ const Slider = React.forwardRef, S ref ) => { const [useTooltip, setUseTooltip] = React.useState(false); - const [internalValues, setInternalValues] = React.useState(value || defaultValue || [min]); - const currentValue = value || defaultValue || [min]; + const [internalValues, setInternalValues] = React.useState( + value || defaultValue || [min] + ); + const currentValue: number[] = value || defaultValue || [min]; const handleValueChange = React.useCallback( (newValue: number[]) => { @@ -51,37 +54,41 @@ const Slider = React.forwardRef, S setInternalValues(currentValue); }, []); - return ( - - - - + console.log(internalValues, value, defaultValue, min); - - - - setUseTooltip(true)} - onMouseLeave={() => setUseTooltip(false)} - className="border-primary bg-background block h-4 w-4 cursor-pointer rounded-full border-2 shadow transition-all hover:scale-110 focus:outline-0 disabled:pointer-events-none disabled:opacity-50" - /> - - - {internalValues[0]} - - - - + return ( + Error}> + + + + + + + + + setUseTooltip(true)} + onMouseLeave={() => setUseTooltip(false)} + className="border-primary bg-background block h-4 w-4 cursor-pointer rounded-full border-2 shadow transition-all hover:scale-110 focus:outline-0 disabled:pointer-events-none disabled:opacity-50" + /> + + + {internalValues[0]} + + + + + ); } ); diff --git a/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/StylingAppStyling/EditScatterDotSize.tsx b/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/StylingAppStyling/EditScatterDotSize.tsx index 563bf7553..98b6f6d58 100644 --- a/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/StylingAppStyling/EditScatterDotSize.tsx +++ b/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/StylingAppStyling/EditScatterDotSize.tsx @@ -18,14 +18,17 @@ export const EditScatterDotSize: React.FC<{ const newLower = v[0]; const newUpper = hasSize ? v[1] : newLower + 18; const arrayFormat: [number, number] = [newLower, newUpper]; + console.log({ arrayFormat }); onUpdateChartConfig({ scatterDotSize: arrayFormat }); }); + const arrayValue = Array.isArray(defaultValue) ? defaultValue : [defaultValue]; + return ( - + ); }); diff --git a/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/StylingAppVisualize/SelectChartType/SelectChartType.tsx b/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/StylingAppVisualize/SelectChartType/SelectChartType.tsx index 2f692b4fa..8589621f1 100644 --- a/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/StylingAppVisualize/SelectChartType/SelectChartType.tsx +++ b/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/StylingAppVisualize/SelectChartType/SelectChartType.tsx @@ -146,6 +146,7 @@ const ChartButton: React.FC<{ disabled={disabled} data-testid={`select-chart-type-${id}`} onClick={() => !disabled && onSelectChartType(id)} + data-state={isSelected ? 'selected' : 'not-selected'} className={cn( 'flex aspect-square h-[35px] w-full items-center justify-center hover:transition-none', 'hover:bg-item-hover cursor-pointer rounded',