fix(Chart Annotation modal): Table and Superset annotation options will paginate, exceeding previous max limit 100 (#27022)

This commit is contained in:
Ross Mabbett
2024-03-26 09:54:03 -07:00
committed by GitHub
parent cf010b63e3
commit ce210eebde
2 changed files with 329 additions and 146 deletions
@@ -31,21 +31,37 @@ const defaultProps = {
annotationType: ANNOTATION_TYPES_METADATA.FORMULA.value,
};
const nativeLayerApiRoute = 'glob:*/api/v1/annotation_layer/*';
const chartApiRoute = /\/api\/v1\/chart\/\?q=.+/;
const chartApiWithIdRoute = /\/api\/v1\/chart\/\w+\?q=.+/;
const withIdResult = {
result: {
slice_name: 'Mocked Slice',
query_context: JSON.stringify({
form_data: {
groupby: ['country'],
},
}),
viz_type: 'line',
},
};
beforeAll(() => {
const supportedAnnotationTypes = Object.values(ANNOTATION_TYPES_METADATA).map(
value => value.value,
);
fetchMock.get('glob:*/api/v1/annotation_layer/*', {
result: [{ label: 'Chart A', value: 'a' }],
fetchMock.get(nativeLayerApiRoute, {
result: [{ name: 'Chart A', id: 'a' }],
});
fetchMock.get('glob:*/api/v1/chart/*', {
result: [
{ id: 'a', slice_name: 'Chart A', viz_type: 'table', form_data: {} },
],
fetchMock.get(chartApiRoute, {
result: [{ id: 'a', slice_name: 'Chart A', viz_type: 'table' }],
});
fetchMock.get(chartApiWithIdRoute, withIdResult);
setupColors();
getChartMetadataRegistry().registerValue(
@@ -144,7 +160,7 @@ test('triggers removeAnnotationLayer and close when remove button is clicked', a
expect(close).toHaveBeenCalled();
});
test('renders chart options', async () => {
test('fetches Superset annotation layer options', async () => {
await waitForRender({
annotationType: ANNOTATION_TYPES_METADATA.EVENT.value,
});
@@ -153,12 +169,37 @@ test('renders chart options', async () => {
);
userEvent.click(screen.getByText('Superset annotation'));
expect(await screen.findByText('Annotation layer')).toBeInTheDocument();
userEvent.click(
screen.getByRole('combobox', { name: 'Annotation layer value' }),
);
expect(await screen.findByText('Chart A')).toBeInTheDocument();
expect(fetchMock.calls(nativeLayerApiRoute).length).toBe(1);
});
test('fetches chart options', async () => {
await waitForRender({
annotationType: ANNOTATION_TYPES_METADATA.EVENT.value,
});
userEvent.click(
screen.getByRole('combobox', { name: 'Annotation source type' }),
);
userEvent.click(screen.getByText('Table'));
expect(await screen.findByText('Chart')).toBeInTheDocument();
userEvent.click(
screen.getByRole('combobox', { name: 'Annotation layer value' }),
);
expect(await screen.findByText('Chart A')).toBeInTheDocument();
expect(fetchMock.calls(chartApiRoute).length).toBe(1);
});
test('fetches chart on mount if value present', async () => {
await waitForRender({
name: 'Test',
value: 'a',
annotationType: ANNOTATION_TYPES_METADATA.EVENT.value,
sourceType: 'Table',
});
expect(fetchMock.calls(chartApiWithIdRoute).length).toBe(1);
});
test('keeps apply disabled when missing required fields', async () => {
@@ -171,7 +212,7 @@ test('keeps apply disabled when missing required fields', async () => {
);
expect(await screen.findByText('Chart A')).toBeInTheDocument();
userEvent.click(screen.getByText('Chart A'));
await screen.findByText(/title column/i);
userEvent.click(screen.getByRole('button', { name: 'Automatic Color' }));
userEvent.click(
screen.getByRole('combobox', { name: 'Annotation layer title column' }),
@@ -197,47 +238,61 @@ test('keeps apply disabled when missing required fields', async () => {
expect(screen.getByRole('button', { name: 'Apply' })).toBeDisabled();
});
test.skip('Disable apply button if formula is incorrect', async () => {
// TODO: fix flaky test that passes locally but fails on CI
test('Disable apply button if formula is incorrect', async () => {
await waitForRender({ name: 'test' });
userEvent.clear(screen.getByLabelText('Formula'));
userEvent.type(screen.getByLabelText('Formula'), 'x+1');
const formulaInput = screen.getByRole('textbox', { name: 'Formula' });
const applyButton = screen.getByRole('button', { name: 'Apply' });
const okButton = screen.getByRole('button', { name: 'OK' });
userEvent.type(formulaInput, 'x+1');
expect(formulaInput).toHaveValue('x+1');
await waitFor(() => {
expect(screen.getByLabelText('Formula')).toHaveValue('x+1');
expect(screen.getByRole('button', { name: 'OK' })).toBeEnabled();
expect(screen.getByRole('button', { name: 'Apply' })).toBeEnabled();
expect(okButton).toBeEnabled();
expect(applyButton).toBeEnabled();
});
userEvent.clear(screen.getByLabelText('Formula'));
userEvent.type(screen.getByLabelText('Formula'), 'y = x*2+1');
userEvent.clear(formulaInput);
await waitFor(() => {
expect(screen.getByLabelText('Formula')).toHaveValue('y = x*2+1');
expect(screen.getByRole('button', { name: 'OK' })).toBeEnabled();
expect(screen.getByRole('button', { name: 'Apply' })).toBeEnabled();
expect(formulaInput).toHaveValue('');
});
userEvent.type(formulaInput, 'y = x*2+1');
expect(formulaInput).toHaveValue('y = x*2+1');
await waitFor(() => {
expect(okButton).toBeEnabled();
expect(applyButton).toBeEnabled();
});
userEvent.clear(screen.getByLabelText('Formula'));
userEvent.type(screen.getByLabelText('Formula'), 'y+1');
userEvent.clear(formulaInput);
await waitFor(() => {
expect(screen.getByLabelText('Formula')).toHaveValue('y+1');
expect(screen.getByRole('button', { name: 'OK' })).toBeDisabled();
expect(screen.getByRole('button', { name: 'Apply' })).toBeDisabled();
expect(formulaInput).toHaveValue('');
});
userEvent.type(formulaInput, 'y+1');
expect(formulaInput).toHaveValue('y+1');
await waitFor(() => {
expect(okButton).toBeDisabled();
expect(applyButton).toBeDisabled();
});
userEvent.clear(screen.getByLabelText('Formula'));
userEvent.type(screen.getByLabelText('Formula'), 'x+');
userEvent.clear(formulaInput);
await waitFor(() => {
expect(screen.getByLabelText('Formula')).toHaveValue('x+');
expect(screen.getByRole('button', { name: 'OK' })).toBeDisabled();
expect(screen.getByRole('button', { name: 'Apply' })).toBeDisabled();
expect(formulaInput).toHaveValue('');
});
userEvent.type(formulaInput, 'x+');
expect(formulaInput).toHaveValue('x+');
await waitFor(() => {
expect(okButton).toBeDisabled();
expect(applyButton).toBeDisabled();
});
userEvent.clear(screen.getByLabelText('Formula'));
userEvent.type(screen.getByLabelText('Formula'), 'y = z+1');
userEvent.clear(formulaInput);
await waitFor(() => {
expect(screen.getByLabelText('Formula')).toHaveValue('y = z+1');
expect(screen.getByRole('button', { name: 'OK' })).toBeDisabled();
expect(screen.getByRole('button', { name: 'Apply' })).toBeDisabled();
expect(formulaInput).toHaveValue('');
});
userEvent.type(formulaInput, 'y = z+1');
expect(formulaInput).toHaveValue('y = z+1');
await waitFor(() => {
expect(okButton).toBeDisabled();
expect(applyButton).toBeDisabled();
});
});