snapshot of https://github.com/dream-num/univer.git (dev, 2026-09-16; blobs > 131072B omitted)
Some checks failed
📦 Build / build (push) Has been cancelled
🧪 CI Test / test shard (1/4) (push) Has been cancelled
🧪 CI Test / test shard (2/4) (push) Has been cancelled
🧪 CI Test / test shard (3/4) (push) Has been cancelled
🧪 CI Test / test shard (4/4) (push) Has been cancelled
🧪 CI Test / test (push) Has been cancelled
🧪 CI Test / eslint (push) Has been cancelled
🧪 CI Test / typecheck (push) Has been cancelled
🔫 Sync to Pro / dispatch-sync (push) Has been cancelled
🔮 Sync Mirror / sync (push) Has been cancelled
Some checks failed
📦 Build / build (push) Has been cancelled
🧪 CI Test / test shard (1/4) (push) Has been cancelled
🧪 CI Test / test shard (2/4) (push) Has been cancelled
🧪 CI Test / test shard (3/4) (push) Has been cancelled
🧪 CI Test / test shard (4/4) (push) Has been cancelled
🧪 CI Test / test (push) Has been cancelled
🧪 CI Test / eslint (push) Has been cancelled
🧪 CI Test / typecheck (push) Has been cancelled
🔫 Sync to Pro / dispatch-sync (push) Has been cancelled
🔮 Sync Mirror / sync (push) Has been cancelled
This commit is contained in:
31
packages/sheets-numfmt/src/__tests__/date.test.ts
Normal file
31
packages/sheets-numfmt/src/__tests__/date.test.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Co., Ltd.
|
||||
*
|
||||
* Licensed 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 { numfmt } from '@univerjs/core';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
describe('test numfmt date', () => {
|
||||
it('date parse date', () => {
|
||||
expect(numfmt.parseDate('asdasdasd')).toBe(null);
|
||||
expect(numfmt.parseDate('1988/12/12 21:21:21')?.z).toBe('yyyy/mm/dd hh:mm:ss');
|
||||
expect(numfmt.parseDate('12/12 21:21:21')?.z).toBe('mm/dd hh:mm:ss');
|
||||
expect(numfmt.parseDate('2012/12 21:21:21')?.z).toBe('yyyy/m hh:mm:ss'); // TODO: is yyy/mm hh:mm:ss ?
|
||||
expect(numfmt.parseDate('2012/12 21:21')?.z).toBe('yyyy/m hh:mm'); // TODO: is yyy/mm hh:mm ?
|
||||
expect(numfmt.parseDate('2012/12')?.z).toBe('yyyy/m'); // TODO: is yyy/mm ?
|
||||
expect(numfmt.parseDate('2012/12/12')?.z).toBe('yyyy/mm/dd');
|
||||
expect(numfmt.parseDate('21:21')).toBe(null);
|
||||
});
|
||||
});
|
||||
304
packages/sheets-numfmt/src/__tests__/utils.test.ts
Normal file
304
packages/sheets-numfmt/src/__tests__/utils.test.ts
Normal file
@@ -0,0 +1,304 @@
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Co., Ltd.
|
||||
*
|
||||
* Licensed 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 { cellToRange, CellValueType, currencySymbols, DEFAULT_NUMBER_FORMAT, DEFAULT_TEXT_FORMAT_EXCEL, isPatternEqualWithoutDecimal, LocaleType } from '@univerjs/core';
|
||||
import { RemoveNumfmtMutation, SetNumfmtMutation } from '@univerjs/sheets';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { getCurrencyFormat, getCurrencySymbolByLocale, getCurrencySymbolIconByLocale } from '../base/const/currency-symbols';
|
||||
import { getCurrencyType } from '../utils/currency';
|
||||
import { getDecimalFromPattern, getDecimalString, isPatternHasDecimal, setPatternDecimal } from '../utils/decimal';
|
||||
import { mergeNumfmtMutations } from '../utils/mutation';
|
||||
import { getCurrencyFormatOptions, getCurrencyOptions, getDateFormatOptions, getNumberFormatOptions } from '../utils/options';
|
||||
import { getPatternPreview, getPatternPreviewIgnoreGeneral, getPatternType } from '../utils/pattern';
|
||||
import { getScientificNotationFormatFromCell, isAllowedPatternForScientificNotationNumber, isScientificNotationNumericCell } from '../utils/scientific-notation';
|
||||
|
||||
describe('test numfmt utils function', () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('getCurrencyType', () => {
|
||||
expect(getCurrencyType(`_(${currencySymbols[7]} 123123`)).toBe(currencySymbols[7]);
|
||||
expect(getCurrencyType('_(# 123123')).toBeUndefined();
|
||||
expect(getCurrencyType(`_(${currencySymbols[7]} 123123 ${currencySymbols[8]}`)).toBe(currencySymbols[7]);
|
||||
});
|
||||
it('getDecimalFromPattern', () => {
|
||||
expect(getDecimalFromPattern('_(###0.000);--###0.00')).toBe(3);
|
||||
expect(getDecimalFromPattern('_(###0);-###0.00')).toBe(0); // the function decimal just use positive,negative configuration ignored
|
||||
expect(getDecimalFromPattern('_(###0.0);--###0.00')).toBe(1);
|
||||
expect(getDecimalFromPattern('_(###0.);--###0.00')).toBe(0);
|
||||
});
|
||||
it('isPatternEqualWithoutDecimal', () => {
|
||||
expect(isPatternEqualWithoutDecimal('_(###0.000);-###0.00', '[red]_(###0.0000);-###0.00')).toBe(true); // the positive color ignored
|
||||
expect(isPatternEqualWithoutDecimal('_(###0;-###0.00', '_(###0;[red]-###0.00')).toBe(false);
|
||||
expect(isPatternEqualWithoutDecimal('_(###00.0;-###0.00', '_(###0;[red]-###0.00')).toBe(false);
|
||||
expect(isPatternEqualWithoutDecimal('_(###0;-###0.00', '_(###0.00;-###0.00')).toBe(true);
|
||||
});
|
||||
it('getDecimalString', () => {
|
||||
expect(getDecimalString(3)).toBe('000'); // the positive color ignored
|
||||
expect(getDecimalString(-1)).toBe(''); // the positive color ignored
|
||||
expect(getDecimalString(0)).toBe(''); // the positive color ignored
|
||||
});
|
||||
it('setPatternDecimal', () => {
|
||||
expect(setPatternDecimal('0.', 4)).toBe('0.0000'); // the positive color ignored
|
||||
expect(setPatternDecimal('.', 4)).toBe('.0000'); // the positive color ignored
|
||||
expect(setPatternDecimal('0.0', 4)).toBe('0.0000'); // the positive color ignored
|
||||
expect(setPatternDecimal('0.0', 0)).toBe('0'); // the positive color ignored
|
||||
});
|
||||
|
||||
it('isPatternHasDecimal', () => {
|
||||
expect(isPatternHasDecimal('0.00')).toBe(true);
|
||||
expect(isPatternHasDecimal('#,##0')).toBe(true);
|
||||
expect(isPatternHasDecimal('General')).toBe(false);
|
||||
});
|
||||
|
||||
it('currency symbol helpers', () => {
|
||||
expect(getCurrencySymbolByLocale(LocaleType.ZH_CN)).toBe('¥');
|
||||
expect(getCurrencySymbolByLocale(LocaleType.KO_KR)).toBe('₩');
|
||||
expect(getCurrencySymbolIconByLocale(LocaleType.FR_FR)).toEqual({
|
||||
icon: 'EuroIcon',
|
||||
symbol: '€',
|
||||
locale: LocaleType.FR_FR,
|
||||
});
|
||||
expect(getCurrencySymbolIconByLocale(LocaleType.KO_KR)).toEqual({
|
||||
icon: 'WonIcon',
|
||||
symbol: '₩',
|
||||
locale: LocaleType.KO_KR,
|
||||
});
|
||||
expect([
|
||||
LocaleType.VI_VN,
|
||||
LocaleType.FA_IR,
|
||||
LocaleType.AR_SA,
|
||||
LocaleType.ID_ID,
|
||||
LocaleType.PL_PL,
|
||||
].map((locale) => getCurrencySymbolIconByLocale(locale).icon)).toEqual([
|
||||
'DongIcon',
|
||||
'RialIcon',
|
||||
'RialIcon',
|
||||
'RupiahIcon',
|
||||
'ZlotyIcon',
|
||||
]);
|
||||
expect(getCurrencyFormat(LocaleType.ZH_CN, 3)).toContain('"¥"#,##0.000');
|
||||
expect(getCurrencyFormat(LocaleType.EN_US, 200)).toContain(`.${'0'.repeat(127)}`);
|
||||
});
|
||||
|
||||
it('option helpers expose formatted labels and values', () => {
|
||||
expect(getCurrencyOptions()[0]).toEqual({ label: 'Rp', value: 'Rp' });
|
||||
expect(getCurrencyFormatOptions('€')[0]).toMatchObject({
|
||||
label: expect.stringContaining('€'),
|
||||
value: expect.stringContaining('€'),
|
||||
});
|
||||
expect(getDateFormatOptions()[0]).toMatchObject({
|
||||
label: expect.any(String),
|
||||
value: expect.any(String),
|
||||
});
|
||||
expect(getNumberFormatOptions()[0]).toMatchObject({
|
||||
label: expect.any(String),
|
||||
value: expect.any(String),
|
||||
});
|
||||
});
|
||||
|
||||
it('pattern preview helpers return types and gracefully handle general or invalid formats', () => {
|
||||
vi.spyOn(console, 'warn').mockImplementation(() => undefined);
|
||||
|
||||
expect(getPatternType('0%')).toBe('percent');
|
||||
expect(getPatternPreview('0.00', 12.3)).toEqual({ result: '12.30' });
|
||||
expect(getPatternPreviewIgnoreGeneral(DEFAULT_NUMBER_FORMAT, 0.1 + 0.2)).toEqual({ result: '0.3' });
|
||||
expect(getPatternPreview('[invalid', 42)).toEqual({ result: '42' });
|
||||
});
|
||||
|
||||
it('scientific notation helpers detect numeric cells and derive display patterns from mantissa decimals', () => {
|
||||
expect(isScientificNotationNumericCell({ v: 1e21, t: CellValueType.NUMBER })).toBe(true);
|
||||
expect(isScientificNotationNumericCell({ v: 1.2345e31, t: CellValueType.NUMBER })).toBe(true);
|
||||
expect(isScientificNotationNumericCell({ v: '1e21', t: CellValueType.STRING })).toBe(false);
|
||||
expect(isScientificNotationNumericCell({ v: 123, t: CellValueType.NUMBER })).toBe(false);
|
||||
expect(isScientificNotationNumericCell(null)).toBe(false);
|
||||
|
||||
expect(getScientificNotationFormatFromCell({ v: 1e21, t: CellValueType.NUMBER })).toBe('0.00E+00');
|
||||
expect(getScientificNotationFormatFromCell({ v: 1.2e21, t: CellValueType.NUMBER })).toBe('0.00E+00');
|
||||
expect(getScientificNotationFormatFromCell({ v: 1.2345e31, t: CellValueType.NUMBER })).toBe('0.0000E+00');
|
||||
expect(getScientificNotationFormatFromCell({ v: -1.2345e-31, t: CellValueType.NUMBER })).toBe('0.0000E+00');
|
||||
});
|
||||
|
||||
it('scientific notation format guard only allows general, text, and scientific patterns', () => {
|
||||
expect(isAllowedPatternForScientificNotationNumber(undefined)).toBe(true);
|
||||
expect(isAllowedPatternForScientificNotationNumber(DEFAULT_NUMBER_FORMAT)).toBe(true);
|
||||
expect(isAllowedPatternForScientificNotationNumber(DEFAULT_TEXT_FORMAT_EXCEL)).toBe(true);
|
||||
expect(isAllowedPatternForScientificNotationNumber('0.00E+00')).toBe(true);
|
||||
expect(isAllowedPatternForScientificNotationNumber('0.00')).toBe(false);
|
||||
expect(isAllowedPatternForScientificNotationNumber('0%')).toBe(false);
|
||||
});
|
||||
|
||||
it('mergeNumfmtMutations', () => {
|
||||
const result = mergeNumfmtMutations([
|
||||
{
|
||||
id: SetNumfmtMutation.id,
|
||||
params: {
|
||||
values: {
|
||||
a: { ranges: [cellToRange(2, 3), cellToRange(2, 4), cellToRange(4, 5)] },
|
||||
},
|
||||
refMap: { a: { pattern: '', type: '' } },
|
||||
},
|
||||
},
|
||||
{
|
||||
id: RemoveNumfmtMutation.id,
|
||||
params: {
|
||||
ranges: [cellToRange(2, 3), cellToRange(2, 4), cellToRange(4, 5)],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: SetNumfmtMutation.id,
|
||||
params: {
|
||||
values: {
|
||||
a: { ranges: [cellToRange(4, 6), cellToRange(4, 5)] },
|
||||
},
|
||||
refMap: { a: { pattern: '', type: '' } },
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const removeMutation = result[0] as { params: { ranges: unknown } };
|
||||
const setMutation = result[1] as { params: { values: Record<string, { ranges: unknown }> } };
|
||||
|
||||
expect(result[0].id === RemoveNumfmtMutation.id).toBeTruthy();
|
||||
expect(result[1].id === SetNumfmtMutation.id).toBeTruthy();
|
||||
expect(removeMutation.params.ranges).toEqual([
|
||||
{
|
||||
startRow: 2,
|
||||
endRow: 2,
|
||||
startColumn: 3,
|
||||
endColumn: 4,
|
||||
},
|
||||
{
|
||||
startRow: 4,
|
||||
endRow: 4,
|
||||
startColumn: 5,
|
||||
endColumn: 5,
|
||||
},
|
||||
]);
|
||||
expect(setMutation.params.values['1'].ranges).toEqual([
|
||||
{
|
||||
startRow: 2,
|
||||
endRow: 2,
|
||||
startColumn: 3,
|
||||
endColumn: 4,
|
||||
},
|
||||
{
|
||||
startRow: 4,
|
||||
endRow: 4,
|
||||
startColumn: 5,
|
||||
endColumn: 6,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('mergeNumfmtMutations multiple data formats of different types', () => {
|
||||
const result = mergeNumfmtMutations([
|
||||
{
|
||||
id: SetNumfmtMutation.id,
|
||||
params: {
|
||||
values: {
|
||||
a: { ranges: [cellToRange(2, 3), cellToRange(2, 4), cellToRange(4, 5)] },
|
||||
},
|
||||
refMap: { a: { pattern: 'a', type: '' } },
|
||||
},
|
||||
},
|
||||
{
|
||||
id: RemoveNumfmtMutation.id,
|
||||
params: {
|
||||
ranges: [cellToRange(2, 3), cellToRange(2, 4), cellToRange(4, 5)],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: SetNumfmtMutation.id,
|
||||
params: {
|
||||
values: {
|
||||
a: { ranges: [cellToRange(4, 6), cellToRange(4, 5)] },
|
||||
},
|
||||
refMap: { a: { pattern: 'b', type: '' } },
|
||||
},
|
||||
},
|
||||
]);
|
||||
expect(result).toEqual([
|
||||
{
|
||||
id: 'sheet.mutation.remove.numfmt',
|
||||
params: {
|
||||
ranges: [
|
||||
{
|
||||
startRow: 2,
|
||||
endRow: 2,
|
||||
startColumn: 3,
|
||||
endColumn: 4,
|
||||
},
|
||||
{
|
||||
startRow: 4,
|
||||
endRow: 4,
|
||||
startColumn: 5,
|
||||
endColumn: 5,
|
||||
},
|
||||
],
|
||||
unitId: undefined,
|
||||
subUnitId: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'sheet.mutation.set.numfmt',
|
||||
params: {
|
||||
values: {
|
||||
1: {
|
||||
ranges: [
|
||||
{
|
||||
startRow: 2,
|
||||
endRow: 2,
|
||||
startColumn: 3,
|
||||
endColumn: 4,
|
||||
},
|
||||
{
|
||||
startRow: 4,
|
||||
endRow: 4,
|
||||
startColumn: 5,
|
||||
endColumn: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
2: {
|
||||
ranges: [
|
||||
{
|
||||
startRow: 4,
|
||||
endRow: 4,
|
||||
startColumn: 5,
|
||||
endColumn: 6,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
refMap: {
|
||||
1: {
|
||||
pattern: 'a',
|
||||
type: '',
|
||||
},
|
||||
2: {
|
||||
pattern: 'b',
|
||||
type: '',
|
||||
},
|
||||
},
|
||||
unitId: undefined,
|
||||
subUnitId: undefined,
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user