test(frontend): Migrate from describe/it to flat test() pattern (#35305)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Evan Rusackas
2025-09-28 11:45:33 -07:00
committed by GitHub
parent ff102aadb3
commit d62249d13f
255 changed files with 2017 additions and 1554 deletions

View File

@@ -19,14 +19,15 @@
import DebouncedMessageQueue from './DebouncedMessageQueue';
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('DebouncedMessageQueue', () => {
it('should create a queue with default options', () => {
test('should create a queue with default options', () => {
const queue = new DebouncedMessageQueue();
expect(queue).toBeDefined();
expect(queue.trigger).toBeInstanceOf(Function);
});
it('should accept custom configuration options', () => {
test('should accept custom configuration options', () => {
const mockCallback = jest.fn();
const queue = new DebouncedMessageQueue({
callback: mockCallback,
@@ -36,7 +37,7 @@ describe('DebouncedMessageQueue', () => {
expect(queue).toBeDefined();
});
it('should append items to the queue', () => {
test('should append items to the queue', () => {
const mockCallback = jest.fn();
const queue = new DebouncedMessageQueue({ callback: mockCallback });
@@ -47,7 +48,7 @@ describe('DebouncedMessageQueue', () => {
expect(() => queue.append(testEvent)).not.toThrow();
});
it('should handle generic types properly', () => {
test('should handle generic types properly', () => {
interface TestEvent {
id: number;
data: string;

View File

@@ -18,6 +18,7 @@
*/
import { cacheWrapper } from 'src/utils/cacheWrapper';
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('cacheWrapper', () => {
const fnResult = 'fnResult';
const fn = jest.fn<string, [number, number]>().mockReturnValue(fnResult);
@@ -33,7 +34,7 @@ describe('cacheWrapper', () => {
jest.clearAllMocks();
});
it('calls fn with its arguments once when the key is not found', () => {
test('calls fn with its arguments once when the key is not found', () => {
const returnedValue = wrappedFn(1, 2);
expect(returnedValue).toEqual(fnResult);
@@ -41,8 +42,9 @@ describe('cacheWrapper', () => {
expect(fn).toHaveBeenCalledWith(1, 2);
});
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('subsequent calls', () => {
it('returns the correct value without fn being called multiple times', () => {
test('returns the correct value without fn being called multiple times', () => {
const returnedValue1 = wrappedFn(1, 2);
const returnedValue2 = wrappedFn(1, 2);
@@ -51,7 +53,7 @@ describe('cacheWrapper', () => {
expect(fn).toHaveBeenCalledTimes(1);
});
it('fn is called multiple times for different arguments', () => {
test('fn is called multiple times for different arguments', () => {
wrappedFn(1, 2);
wrappedFn(1, 3);
@@ -59,6 +61,7 @@ describe('cacheWrapper', () => {
});
});
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('with custom keyFn', () => {
let cache: Map<string, any>;
@@ -67,12 +70,12 @@ describe('cacheWrapper', () => {
wrappedFn = cacheWrapper(fn, cache, (...args) => `key-${args[0]}`);
});
it('saves fn result in cache under generated key', () => {
test('saves fn result in cache under generated key', () => {
wrappedFn(1, 2);
expect(cache.get('key-1')).toEqual(fnResult);
});
it('subsequent calls with same generated key calls fn once, even if other arguments have changed', () => {
test('subsequent calls with same generated key calls fn once, even if other arguments have changed', () => {
wrappedFn(1, 1);
wrappedFn(1, 2);
wrappedFn(1, 3);

View File

@@ -28,7 +28,9 @@ import { nativeFilterGate } from 'src/dashboard/components/nativeFilters/utils';
* This tests the pure functions used in ChartList for filtering chart types.
*/
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('Chart Registry Utils', () => {
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('Type filter option generation', () => {
let registry: ReturnType<typeof getChartMetadataRegistry>;
@@ -37,7 +39,7 @@ describe('Chart Registry Utils', () => {
registry.clear();
});
it('generates correct options from chart metadata registry', () => {
test('generates correct options from chart metadata registry', () => {
// Register test chart types
registry
.registerValue(
@@ -88,7 +90,7 @@ describe('Chart Registry Utils', () => {
).toBeUndefined();
});
it('handles empty registry gracefully', () => {
test('handles empty registry gracefully', () => {
const options = registry
.keys()
.filter(k => nativeFilterGate(registry.get(k)?.behaviors || []))
@@ -97,7 +99,7 @@ describe('Chart Registry Utils', () => {
expect(options).toEqual([]);
});
it('falls back to chart key when name is missing', () => {
test('falls back to chart key when name is missing', () => {
registry.registerValue(
'custom_chart',
new ChartMetadata({
@@ -117,7 +119,7 @@ describe('Chart Registry Utils', () => {
]);
});
it('sorts options alphabetically by label', () => {
test('sorts options alphabetically by label', () => {
registry
.registerValue(
'zebra',
@@ -162,7 +164,7 @@ describe('Chart Registry Utils', () => {
]);
});
it('handles mixed chart behaviors correctly', () => {
test('handles mixed chart behaviors correctly', () => {
registry
.registerValue(
'regular',

View File

@@ -25,9 +25,11 @@ import {
FALSE_STRING,
} from 'src/utils/common';
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('utils/common', () => {
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('optionFromValue', () => {
it('converts values as expected', () => {
test('converts values as expected', () => {
expect(optionFromValue(false)).toEqual({
value: false,
label: FALSE_STRING,
@@ -48,13 +50,14 @@ describe('utils/common', () => {
expect(optionFromValue(5)).toEqual({ value: 5, label: '5' });
});
});
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('prepareCopyToClipboardTabularData', () => {
it('converts empty array', () => {
test('converts empty array', () => {
const data = [];
const columns = [];
expect(prepareCopyToClipboardTabularData(data, columns)).toEqual('');
});
it('converts non empty array', () => {
test('converts non empty array', () => {
const data = [
{ column1: 'lorem', column2: 'ipsum' },
{ column1: 'dolor', column2: 'sit', column3: 'amet' },
@@ -64,7 +67,7 @@ describe('utils/common', () => {
'column1\tcolumn2\tcolumn3\nlorem\tipsum\t\ndolor\tsit\tamet\n',
);
});
it('includes 0 values and handle column objects', () => {
test('includes 0 values and handle column objects', () => {
const data = [
{ column1: 0, column2: 0 },
{ column1: 1, column2: -1, 0: 0 },
@@ -75,19 +78,20 @@ describe('utils/common', () => {
);
});
});
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('applyFormattingToTabularData', () => {
it('does not mutate empty array', () => {
test('does not mutate empty array', () => {
const data = [];
expect(applyFormattingToTabularData(data, [])).toEqual(data);
});
it('does not mutate array without temporal column', () => {
test('does not mutate array without temporal column', () => {
const data = [
{ column1: 'lorem', column2: 'ipsum' },
{ column1: 'dolor', column2: 'sit', column3: 'amet' },
];
expect(applyFormattingToTabularData(data, [])).toEqual(data);
});
it('changes formatting of columns selected for formatting', () => {
test('changes formatting of columns selected for formatting', () => {
const originalData = [
{
__timestamp: null,

View File

@@ -84,6 +84,7 @@ const mockQueryEditor: QueryEditor = {
templateParams: '{"param1": "value1"}',
};
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('getDatasourceAsSaveableDataset', () => {
test('should convert Datasource object correctly', () => {
const result = getDatasourceAsSaveableDataset(mockDatasource);

View File

@@ -19,14 +19,16 @@
import { DEFAULT_BOOTSTRAP_DATA } from '../constants';
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('getBootstrapData and helpers', () => {
afterEach(() => {
// Clean up the DOM
document.body.innerHTML = '';
});
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('getBootstrapData()', () => {
it('should return DEFAULT_BOOTSTRAP_DATA when #app element does not exist', async () => {
test('should return DEFAULT_BOOTSTRAP_DATA when #app element does not exist', async () => {
// Ensure no #app element exists.
document.body.innerHTML = '';
@@ -37,7 +39,7 @@ describe('getBootstrapData and helpers', () => {
expect(bootstrapData).toEqual(DEFAULT_BOOTSTRAP_DATA);
});
it('should return parsed bootstrap data when #app element has valid data attribute', async () => {
test('should return parsed bootstrap data when #app element has valid data attribute', async () => {
// Set up the fake #app element
const customData = {
common: {
@@ -55,8 +57,9 @@ describe('getBootstrapData and helpers', () => {
});
});
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('Helper functions applicationRoot and staticAssetsPrefix', () => {
it('should return values without trailing slashes', async () => {
test('should return values without trailing slashes', async () => {
// Setup a fake #app element with data-bootstrap attribute.
const customData = {
common: {
@@ -82,7 +85,7 @@ describe('getBootstrapData and helpers', () => {
expect(staticAssetsPrefix()).toEqual('/custom-static');
});
it('should return defaults without trailing slashes when #app element is missing', async () => {
test('should return defaults without trailing slashes when #app element is missing', async () => {
// Ensure no #app element exists.
document.body.innerHTML = '';
@@ -107,7 +110,7 @@ describe('getBootstrapData and helpers', () => {
expect(staticAssetsPrefix()).toEqual(expectedStaticPrefix);
});
it('should defaults without trailing slashes when #app element does not include application_root or static_assets_prefix', async () => {
test('should defaults without trailing slashes when #app element does not include application_root or static_assets_prefix', async () => {
// Set up the fake #app element
const customData = {
common: {

View File

@@ -26,8 +26,9 @@ jest.mock('../sanitizeFormData', () => ({
}),
}));
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('alterForComparison', () => {
it.each([
test.each([
[null, null],
['', null],
[[], null],
@@ -43,23 +44,25 @@ describe('alterForComparison', () => {
});
});
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('isEqualish', () => {
it('returns true for semantically equal values with different formats', () => {
test('returns true for semantically equal values with different formats', () => {
expect(isEqualish('', null)).toBe(true);
expect(isEqualish([], null)).toBe(true);
expect(isEqualish({}, null)).toBe(true);
expect(isEqualish([1], [1])).toBe(true);
});
it('returns false for clearly different values', () => {
test('returns false for clearly different values', () => {
expect(isEqualish([1], [2])).toBe(false);
expect(isEqualish({ a: 1 }, { a: 2 })).toBe(false);
expect(isEqualish('foo', 'bar')).toBe(false);
});
});
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('getChartFormDiffs', () => {
it('returns diffs for changed values', () => {
test('returns diffs for changed values', () => {
const original = { metric: 'count', adhoc_filters: [] };
const current = { metric: 'sum__num', adhoc_filters: [] };
@@ -72,7 +75,7 @@ describe('getChartFormDiffs', () => {
});
});
it('ignores noisy keys', () => {
test('ignores noisy keys', () => {
const original = { where: 'a = 1', metric: 'count' };
const current = { where: 'a = 2', metric: 'sum__num' };
@@ -82,7 +85,7 @@ describe('getChartFormDiffs', () => {
expect(diffs).toHaveProperty('metric');
});
it('does not include values that are equalish', () => {
test('does not include values that are equalish', () => {
const original = { filters: [], metric: 'count' };
const current = { filters: null, metric: 'count' };
@@ -91,7 +94,7 @@ describe('getChartFormDiffs', () => {
expect(diffs).toEqual({});
});
it('handles missing keys in original or current gracefully', () => {
test('handles missing keys in original or current gracefully', () => {
const original = { metric: 'count' };
const current = { metric: 'count', new_field: 'value' };
@@ -104,7 +107,7 @@ describe('getChartFormDiffs', () => {
});
});
it('ignores keys that are missing in current and not explicitly changed', () => {
test('ignores keys that are missing in current and not explicitly changed', () => {
const original = { metric: 'count', removed_field: 'gone' };
const current = { metric: 'count' };

View File

@@ -67,6 +67,7 @@ const fakePluginControls = {
],
};
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('getControlsForVizType', () => {
beforeEach(() => {
getChartControlPanelRegistry().registerValue(
@@ -75,7 +76,7 @@ describe('getControlsForVizType', () => {
);
});
it('returns a map of the controls', () => {
test('returns a map of the controls', () => {
expect(
JSON.stringify(getControlsForVizType('chart_controls_inventory_fake')),
).toEqual(

View File

@@ -67,6 +67,7 @@ const fakePluginControls: JsonObject = {
],
};
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('getControlsForVizType', () => {
beforeEach(() => {
getChartControlPanelRegistry().registerValue(
@@ -75,7 +76,7 @@ describe('getControlsForVizType', () => {
);
});
it('returns a map of the controls', () => {
test('returns a map of the controls', () => {
expect(
JSON.stringify(getControlsForVizType('chart_controls_inventory_fake')),
).toEqual(

View File

@@ -19,6 +19,7 @@
import { availableDomains, allowCrossDomain } from './hostNamesConfig';
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('hostNamesConfig', () => {
beforeEach(() => {
// Reset DOM

View File

@@ -22,6 +22,7 @@ import {
LocalStorageKeys,
} from 'src/utils/localStorageHelpers';
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('localStorageHelpers', () => {
beforeEach(() => {
localStorage.clear();
@@ -31,13 +32,13 @@ describe('localStorageHelpers', () => {
localStorage.clear();
});
it('gets a value that was set', () => {
test('gets a value that was set', () => {
setItem(LocalStorageKeys.IsDatapanelOpen, false);
expect(getItem(LocalStorageKeys.IsDatapanelOpen, true)).toBe(false);
});
it('returns the default value for an unset value', () => {
test('returns the default value for an unset value', () => {
expect(getItem(LocalStorageKeys.IsDatapanelOpen, true)).toBe(true);
});
});

View File

@@ -18,22 +18,23 @@
*/
import parseCookie from 'src/utils/parseCookie';
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('parseCookie', () => {
let cookieVal = '';
Object.defineProperty(document, 'cookie', {
get: jest.fn().mockImplementation(() => cookieVal),
});
it('parses cookie strings', () => {
test('parses cookie strings', () => {
cookieVal = 'val1=foo; val2=bar';
expect(parseCookie()).toEqual({ val1: 'foo', val2: 'bar' });
});
it('parses empty cookie strings', () => {
test('parses empty cookie strings', () => {
cookieVal = '';
expect(parseCookie()).toEqual({});
});
it('accepts an arg', () => {
test('accepts an arg', () => {
expect(parseCookie('val=foo')).toEqual({ val: 'foo' });
});
});

View File

@@ -22,8 +22,9 @@ class Noise {
public next?: Noise;
}
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('Stringify utility testing', () => {
it('correctly parses a simple object just like JSON', () => {
test('correctly parses a simple object just like JSON', () => {
const noncircular = {
b: 'foo',
c: 'bar',
@@ -45,7 +46,7 @@ describe('Stringify utility testing', () => {
);
});
it('handles simple circular json as expected', () => {
test('handles simple circular json as expected', () => {
const ping = new Noise();
const pong = new Noise();
const pang = new Noise();
@@ -61,7 +62,7 @@ describe('Stringify utility testing', () => {
expect(safeString).toEqual(ordinaryString);
});
it('creates a parseable object even when the input is circular', () => {
test('creates a parseable object even when the input is circular', () => {
const ping = new Noise();
const pong = new Noise();
ping.next = pong;
@@ -72,7 +73,7 @@ describe('Stringify utility testing', () => {
expect(newNoise.next).toEqual({});
});
it('does not remove noncircular duplicates', () => {
test('does not remove noncircular duplicates', () => {
const a = {
foo: 'bar',
};
@@ -86,7 +87,7 @@ describe('Stringify utility testing', () => {
expect(safeStringify(repeating)).toEqual(JSON.stringify(repeating));
});
it('does not remove nodes with empty objects', () => {
test('does not remove nodes with empty objects', () => {
const emptyObjectValues = {
a: {},
b: 'foo',
@@ -100,7 +101,7 @@ describe('Stringify utility testing', () => {
);
});
it('does not remove nested same keys', () => {
test('does not remove nested same keys', () => {
const nestedKeys = {
a: 'b',
c: {

View File

@@ -19,36 +19,37 @@
import { testWithId } from './testUtils';
// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('testUtils', () => {
it('testWithId with prefix only', () => {
test('testWithId with prefix only', () => {
expect(testWithId('prefix')()).toEqual({ 'data-test': 'prefix' });
});
it('testWithId with prefix only and idOnly', () => {
test('testWithId with prefix only and idOnly', () => {
expect(testWithId('prefix', true)()).toEqual('prefix');
});
it('testWithId with id only', () => {
test('testWithId with id only', () => {
expect(testWithId()('id')).toEqual({ 'data-test': 'id' });
});
it('testWithId with id only and idOnly', () => {
test('testWithId with id only and idOnly', () => {
expect(testWithId(undefined, true)('id')).toEqual('id');
});
it('testWithId with prefix and id', () => {
test('testWithId with prefix and id', () => {
expect(testWithId('prefix')('id')).toEqual({ 'data-test': 'prefix__id' });
});
it('testWithId with prefix and id and idOnly', () => {
test('testWithId with prefix and id and idOnly', () => {
expect(testWithId('prefix', true)('id')).toEqual('prefix__id');
});
it('testWithId without prefix and id', () => {
test('testWithId without prefix and id', () => {
expect(testWithId()()).toEqual({ 'data-test': '' });
});
it('testWithId without prefix and id and idOnly', () => {
test('testWithId without prefix and id and idOnly', () => {
expect(testWithId(undefined, true)()).toEqual('');
});
});

View File

@@ -53,46 +53,45 @@ test('parseUrl', () => {
expect(parseUrl('#anchor')).toEqual('#anchor');
});
describe('toQueryString', () => {
it('should return an empty string if the input is an empty object', () => {
expect(toQueryString({})).toBe('');
});
it('should correctly convert a single key-value pair to a query string', () => {
expect(toQueryString({ key: 'value' })).toBe('?key=value');
});
it('should correctly convert multiple key-value pairs to a query string', () => {
expect(toQueryString({ key1: 'value1', key2: 'value2' })).toBe(
'?key1=value1&key2=value2',
);
});
it('should encode URI components', () => {
expect(
toQueryString({ 'a key': 'a value', email: 'test@example.com' }),
).toBe('?a%20key=a%20value&email=test%40example.com');
});
it('should omit keys with undefined values', () => {
expect(toQueryString({ key1: 'value1', key2: undefined })).toBe(
'?key1=value1',
);
});
it('should omit keys with null values', () => {
expect(toQueryString({ key1: 'value1', key2: null })).toBe('?key1=value1');
});
it('should handle numbers and boolean values as parameter values', () => {
expect(toQueryString({ number: 123, truth: true, lie: false })).toBe(
'?number=123&truth=true&lie=false',
);
});
it('should handle special characters in keys and values', () => {
expect(toQueryString({ 'user@domain': 'me&you' })).toBe(
'?user%40domain=me%26you',
);
});
// toQueryString
test('toQueryString should return an empty string if the input is an empty object', () => {
expect(toQueryString({})).toBe('');
});
test('toQueryString should correctly convert a single key-value pair to a query string', () => {
expect(toQueryString({ key: 'value' })).toBe('?key=value');
});
test('toQueryString should correctly convert multiple key-value pairs to a query string', () => {
expect(toQueryString({ key1: 'value1', key2: 'value2' })).toBe(
'?key1=value1&key2=value2',
);
});
test('toQueryString should encode URI components', () => {
expect(toQueryString({ 'a key': 'a value', email: 'test@example.com' })).toBe(
'?a%20key=a%20value&email=test%40example.com',
);
});
test('toQueryString should omit keys with undefined values', () => {
expect(toQueryString({ key1: 'value1', key2: undefined })).toBe(
'?key1=value1',
);
});
test('toQueryString should omit keys with null values', () => {
expect(toQueryString({ key1: 'value1', key2: null })).toBe('?key1=value1');
});
test('toQueryString should handle numbers and boolean values as parameter values', () => {
expect(toQueryString({ number: 123, truth: true, lie: false })).toBe(
'?number=123&truth=true&lie=false',
);
});
test('toQueryString should handle special characters in keys and values', () => {
expect(toQueryString({ 'user@domain': 'me&you' })).toBe(
'?user%40domain=me%26you',
);
});