mirror of
https://github.com/apache/superset.git
synced 2026-09-01 13:01:33 +00:00
fix(Chart Annotation modal): Table and Superset annotation options will paginate, exceeding previous max limit 100 (#27022)
This commit is contained in:
+90
-35
@@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user