blob: 83b6ca99870e531c81b4238f1f2c6559fe330751 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { tn } from '@superset-ui/core';
import { updateColumns } from './utils';
describe('updateColumns', () => {
let addSuccessToast: jest.Mock;
beforeEach(() => {
addSuccessToast = jest.fn();
});
it('adds new columns when prevCols is empty', () => {
interface Column {
column_name: string;
type: string;
is_dttm: boolean;
}
const prevCols: Column[] = [];
const newCols = [
{ column_name: 'col1', type: 'string', is_dttm: false },
{ column_name: 'col2', type: 'number', is_dttm: true },
];
const result = updateColumns(prevCols, newCols, addSuccessToast);
expect(result.added.sort()).toEqual(['col1', 'col2'].sort());
expect(result.modified).toEqual([]);
expect(result.removed).toEqual([]);
expect(result.finalColumns).toHaveLength(2);
// Only the added toast should be fired
expect(addSuccessToast).toHaveBeenCalledTimes(1);
expect(addSuccessToast).toHaveBeenCalledWith(
tn(
'Added 1 new column to the virtual dataset',
'Added %s new columns to the virtual dataset',
2,
2,
),
);
});
it('modifies columns when type or is_dttm changes', () => {
const prevCols = [
{ column_name: 'col1', type: 'string', is_dttm: false },
{ column_name: 'col2', type: 'number', is_dttm: false },
];
const newCols = [
// col1 unchanged
{ column_name: 'col1', type: 'string', is_dttm: false },
// col2 modified (type changed)
{ column_name: 'col2', type: 'float', is_dttm: false },
];
const result = updateColumns(prevCols, newCols, addSuccessToast);
expect(result.added).toEqual([]);
expect(result.modified).toEqual(['col2']);
// No columns removed
expect(result.removed).toEqual([]);
// Final columns: first is unchanged, second is updated
expect(result.finalColumns).toHaveLength(2);
const updatedCol2 = (
result.finalColumns as {
column_name: string;
type: string;
is_dttm: boolean;
}[]
).find(c => c.column_name === 'col2');
expect(updatedCol2?.type).toBe('float');
// Modified toast should be fired
expect(addSuccessToast).toHaveBeenCalledTimes(1);
expect(addSuccessToast).toHaveBeenCalledWith(
tn(
'Modified 1 column in the virtual dataset',
'Modified %s columns in the virtual dataset',
1,
1,
),
);
});
it('removes columns not present in newCols', () => {
const prevCols = [
{ column_name: 'col1', type: 'string', is_dttm: false },
{ column_name: 'col2', type: 'number', is_dttm: true },
];
const newCols = [
// Only col2 is present
{ column_name: 'col2', type: 'number', is_dttm: true },
];
const result = updateColumns(prevCols, newCols, addSuccessToast);
// col1 should be marked as removed
expect(result.removed).toEqual(['col1']);
expect(result.added).toEqual([]);
expect(result.modified).toEqual([]);
expect(result.finalColumns).toHaveLength(1);
// Removed toast should be fired
expect(addSuccessToast).toHaveBeenCalledTimes(1);
expect(addSuccessToast).toHaveBeenCalledWith(
tn(
'Removed 1 column from the virtual dataset',
'Removed %s columns from the virtual dataset',
1,
1,
),
);
});
it('handles combined additions, modifications, and removals', () => {
const prevCols = [
{ column_name: 'col1', type: 'string', is_dttm: false },
{ column_name: 'col2', type: 'number', is_dttm: false },
{ column_name: 'col3', type: 'number', is_dttm: false },
];
const newCols = [
// col1 modified
{ column_name: 'col1', type: 'string', is_dttm: true },
// col2 unchanged
{ column_name: 'col2', type: 'number', is_dttm: false },
// col4 is a new column
{ column_name: 'col4', type: 'boolean', is_dttm: false },
];
const result = updateColumns(prevCols, newCols, addSuccessToast);
expect(result.added).toEqual(['col4']);
expect(result.modified).toEqual(['col1']);
// col3 is removed since it is missing in newCols and has no expression
expect(result.removed).toEqual(['col3']);
expect(result.finalColumns).toHaveLength(3);
// Three types of changes should fire three separate toasts
expect(addSuccessToast).toHaveBeenCalledTimes(3);
expect(addSuccessToast.mock.calls).toEqual([
[
tn(
'Modified 1 column in the virtual dataset',
'Modified %s columns in the virtual dataset',
1,
1,
),
],
[
tn(
'Removed 1 column from the virtual dataset',
'Removed %s columns from the virtual dataset',
1,
1,
),
],
[
tn(
'Added 1 new column to the virtual dataset',
'Added %s new columns to the virtual dataset',
1,
1,
),
],
]);
});
it('should not remove columns with expressions', () => {
const prevCols = [
{ column_name: 'col1', type: 'string', is_dttm: false },
{ column_name: 'col2', type: 'number', is_dttm: false },
{
column_name: 'col3',
type: 'number',
is_dttm: false,
expression: 'expr',
},
];
const newCols = [
// col1 modified
{ column_name: 'col1', type: 'string', is_dttm: true },
// col2 unchanged
{ column_name: 'col2', type: 'number', is_dttm: false },
];
const result = updateColumns(prevCols, newCols, addSuccessToast);
expect(result.added).toEqual([]);
expect(result.modified).toEqual(['col1']);
// col3 is not removed since it has an expression
expect(result.removed).toEqual([]);
expect(result.finalColumns).toHaveLength(3);
// Two types of changes should fire two separate toasts
expect(addSuccessToast).toHaveBeenCalledTimes(1);
expect(addSuccessToast.mock.calls).toEqual([
[
tn(
'Modified 1 column in the virtual dataset',
'Modified %s columns in the virtual dataset',
1,
1,
),
],
]);
});
});