test: add formula integration test (#4019)

This commit is contained in:
Wenzhao Hu
2024-11-13 12:03:03 +08:00
committed by GitHub
parent 0e5bd855f3
commit 27eb2d4304
18 changed files with 537 additions and 8 deletions
+5 -1
View File
@@ -1,9 +1,13 @@
{
"name": "univer-examples-node",
"name": "examples-node",
"private": true,
"description": "Examples run on Node.js",
"author": "DreamNum <developer@univer.ai>",
"license": "Apache-2.0",
"exports": {
".": "./src/index.ts",
"./*": "./src/*"
},
"scripts": {
"build:demo": "node ./esbuild.config.mjs",
"lint:types": "node ./scripts/generate-locales.mjs && tsc --noEmit"
-2
View File
@@ -18,8 +18,6 @@ import process from 'node:process';
import { awaitTime, FUniver } from '@univerjs/core';
import { createUniverOnNode } from '../sdk';
import '../sdk/facade';
// From now on, Univer is a full-stack SDK.
async function run(): Promise<void> {
+17
View File
@@ -0,0 +1,17 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* 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.
*/
export { createUniverOnNode, type ICreateUniverOnNodeOptions } from './sdk';
+16 -5
View File
@@ -32,12 +32,23 @@ import { UniverSheetsHyperLinkPlugin } from '@univerjs/sheets-hyper-link';
import { UniverSheetsSortPlugin } from '@univerjs/sheets-sort';
import { UniverThreadCommentPlugin } from '@univerjs/thread-comment';
export function createUniverOnNode(): Univer {
import './facade';
export interface ICreateUniverOnNodeOptions {
useComputingWorker?: boolean;
}
export function createUniverOnNode(options: ICreateUniverOnNodeOptions = {}): Univer {
const { useComputingWorker = false } = options;
const univer = new Univer();
registerBasicPlugins(univer);
registerBasicPlugins(univer, useComputingWorker);
registerSharedPlugins(univer);
registerRPCPlugin(univer);
if (useComputingWorker) {
registerRPCPlugin(univer);
}
registerDocPlugins(univer);
registerSheetPlugins(univer);
@@ -45,8 +56,8 @@ export function createUniverOnNode(): Univer {
return univer;
}
function registerBasicPlugins(univer: Univer): void {
univer.registerPlugin(UniverFormulaEnginePlugin, { notExecuteFormula: true });
function registerBasicPlugins(univer: Univer, useComputingWorker: boolean): void {
univer.registerPlugin(UniverFormulaEnginePlugin, { notExecuteFormula: useComputingWorker });
}
function registerSharedPlugins(univer: Univer): void {
+49
View File
@@ -3456,6 +3456,55 @@ importers:
specifier: ^2.1.4
version: 2.1.4(@types/node@22.9.0)(happy-dom@15.0.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.5)(terser@5.31.6)
tests/formula-integration:
dependencies:
'@univerjs/core':
specifier: workspace:*
version: link:../../packages/core
'@univerjs/data-validation':
specifier: workspace:*
version: link:../../packages/data-validation
'@univerjs/docs':
specifier: workspace:*
version: link:../../packages/docs
'@univerjs/engine-formula':
specifier: workspace:*
version: link:../../packages/engine-formula
'@univerjs/mockdata':
specifier: workspace:*
version: link:../../mockdata
'@univerjs/rpc':
specifier: workspace:*
version: link:../../packages/rpc
'@univerjs/sheets':
specifier: workspace:*
version: link:../../packages/sheets
'@univerjs/sheets-conditional-formatting':
specifier: workspace:*
version: link:../../packages/sheets-conditional-formatting
'@univerjs/sheets-data-validation':
specifier: workspace:*
version: link:../../packages/sheets-data-validation
'@univerjs/sheets-formula':
specifier: workspace:*
version: link:../../packages/sheets-formula
'@univerjs/sheets-numfmt':
specifier: workspace:*
version: link:../../packages/sheets-numfmt
examples-node:
specifier: workspace:*
version: link:../../examples-node
devDependencies:
'@univerjs-infra/shared':
specifier: workspace:*
version: link:../../common/shared
typescript:
specifier: ^5.6.3
version: 5.6.3
vitest:
specifier: ^2.1.4
version: 2.1.4(@types/node@22.9.0)(happy-dom@15.0.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.5)(terser@5.31.6)
packages:
'@adobe/css-tools@4.4.0':
+1
View File
@@ -5,3 +5,4 @@ packages:
- mockdata
- packages-experimental/*
- packages/*
- tests/*
+3
View File
@@ -0,0 +1,3 @@
# formula-integration-test
This is a test repository for the formula integration feature. It also exports some util functions that can be used in the advanced formula engine integration test.
+19
View File
@@ -0,0 +1,19 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* 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 { build } from '@univerjs-infra/shared/vite';
build();
+31
View File
@@ -0,0 +1,31 @@
{
"name": "formula-integration-test",
"private": true,
"author": "DreamNum <developer@univer.ai>",
"license": "Apache-2.0",
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"coverage": "vitest run --coverage",
"lint:types": "tsc --noEmit"
},
"dependencies": {
"@univerjs/core": "workspace:*",
"@univerjs/data-validation": "workspace:*",
"@univerjs/docs": "workspace:*",
"@univerjs/engine-formula": "workspace:*",
"@univerjs/mockdata": "workspace:*",
"@univerjs/rpc": "workspace:*",
"@univerjs/sheets": "workspace:*",
"@univerjs/sheets-conditional-formatting": "workspace:*",
"@univerjs/sheets-data-validation": "workspace:*",
"@univerjs/sheets-formula": "workspace:*",
"@univerjs/sheets-numfmt": "workspace:*",
"examples-node": "workspace:*"
},
"devDependencies": {
"@univerjs-infra/shared": "workspace:*",
"typescript": "^5.6.3",
"vitest": "^2.1.4"
}
}
@@ -0,0 +1,120 @@
{
"id": "-23yFfY3SZ2pr9nPYERZXg",
"sheetOrder": [
"4FDtSTxrsa_03719b8_jm"
],
"name": "New Sheet",
"appVersion": "1",
"locale": "enUS",
"styles": {
"1l4gGD": {
"ff": "Arial",
"fs": 11
}
},
"sheets": {
"4FDtSTxrsa_03719b8_jm": {
"id": "4FDtSTxrsa_03719b8_jm",
"name": "Sheet1",
"rowCount": 1000,
"columnCount": 20,
"freeze": {
"xSplit": 0,
"ySplit": 0,
"startRow": -1,
"startColumn": -1
},
"hidden": 0,
"rowData": {
"0": {
"ah": 24
},
"1": {
"ah": 24
}
},
"tabColor": "",
"mergeData": [],
"rowHeader": {
"width": 46,
"hidden": 0
},
"scrollTop": 200,
"zoomRatio": 1,
"columnData": {},
"scrollLeft": 100,
"rightToLeft": 0,
"columnHeader": {
"height": 20,
"hidden": 0
},
"showGridlines": 1,
"defaultRowHeight": 24,
"defaultColumnWidth": 88,
"cellData": {
"0": {
"0": {
"v": 1,
"t": 2,
"s": "1l4gGD"
},
"1": {
"f": "=SUM(A1:A2)",
"t": 2,
"v": 3
}
},
"1": {
"0": {
"v": 2,
"t": 2,
"s": "1l4gGD"
}
}
}
}
},
"resources": [
{
"name": "SHEET_UNIVER_THREAD_COMMENT_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_RANGE_PROTECTION_PLUGIN",
"data": ""
},
{
"name": "SHEET_WORKSHEET_PROTECTION_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_WORKSHEET_PROTECTION_POINT_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_CONDITIONAL_FORMATTING_PLUGIN",
"data": ""
},
{
"name": "SHEET_HYPER_LINK_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_DRAWING_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_DEFINED_NAME_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_DATA_VALIDATION_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_FILTER_PLUGIN",
"data": "{}"
}
],
"rev": 4
}
@@ -0,0 +1,123 @@
{
"id": "-23yFfY3SZ2pr9nPYERZXg",
"sheetOrder": [
"4FDtSTxrsa_03719b8_jm"
],
"name": "New Sheet",
"appVersion": "1",
"locale": "enUS",
"styles": {
"1l4gGD": {
"ff": "Arial",
"fs": 11
}
},
"sheets": {
"4FDtSTxrsa_03719b8_jm": {
"id": "4FDtSTxrsa_03719b8_jm",
"name": "Sheet1",
"rowCount": 1000,
"columnCount": 20,
"freeze": {
"xSplit": 0,
"ySplit": 0,
"startRow": -1,
"startColumn": -1
},
"hidden": 0,
"rowData": {
"0": {
"ah": 24
},
"1": {
"ah": 24
}
},
"tabColor": "",
"mergeData": [],
"rowHeader": {
"width": 46,
"hidden": 0
},
"scrollTop": 200,
"zoomRatio": 1,
"columnData": {},
"scrollLeft": 100,
"rightToLeft": 0,
"columnHeader": {
"height": 20,
"hidden": 0
},
"showGridlines": 1,
"defaultRowHeight": 24,
"defaultColumnWidth": 88,
"cellData": {
"0": {
"0": {
"v": 1,
"t": 2,
"s": "1l4gGD"
},
"1": {
"f": "=SUM(A1:A2)",
"t": 2
}
},
"1": {
"0": {
"v": 2,
"t": 2,
"s": "1l4gGD"
}
}
}
}
},
"resources": [
{
"name": "SHEET_UNIVER_THREAD_COMMENT_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_RANGE_PROTECTION_PLUGIN",
"data": ""
},
{
"name": "SHEET_WORKSHEET_PROTECTION_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_WORKSHEET_PROTECTION_POINT_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_CONDITIONAL_FORMATTING_PLUGIN",
"data": ""
},
{
"name": "SHEET_DRAWING_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_CHART_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_DEFINED_NAME_PLUGIN",
"data": ""
},
{
"name": "SHEET_DATA_VALIDATION_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_FILTER_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_HYPER_LINK_PLUGIN",
"data": "{\"4FDtSTxrsa_03719b8_jm\":[]}"
}
],
"rev": 4
}
@@ -0,0 +1,29 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* 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 { FUniver } from '@univerjs/core';
import { createUniverOnNode } from 'examples-node';
export function createFormulaTestBed() {
const univer = createUniverOnNode();
const injector = univer.__getInjector();
return {
univer,
get: injector.get.bind(injector),
api: FUniver.newAPI(univer),
};
}
@@ -0,0 +1,67 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* 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 type { IWorkbookData } from '@univerjs/core';
import fs from 'node:fs';
import path from 'node:path';
import { expect } from 'vitest';
import { createFormulaTestBed } from './univer';
function getTestName(): string {
const testName = expect.getState().currentTestName;
if (!testName) {
throw new Error('Cannot get test name. Maybe you call the method outside a test case?');
}
return testName;
}
export function getTestFilePath() {
const name = getTestName();
return name.replace(/[ >]/g, '-').toLowerCase();
}
/**
*
*/
export async function expectCalculationResultMatchesSnapshot() {
const testBed = createFormulaTestBed();
const snapshotRootDir = path.join(import.meta.dirname, '../__snapshots__');
const testSnapshotPath = path.resolve(snapshotRootDir, `${getTestFilePath()}.json`);
if (!fs.existsSync(testSnapshotPath)) {
throw new Error(`Cannot find snapshot file for test "${getTestName()}".`);
}
const testSnapshotRaw = fs.readFileSync(testSnapshotPath, 'utf-8');
const testSnapshot = JSON.parse(testSnapshotRaw) as IWorkbookData;
const workbook = testBed.api.createUniverSheet(testSnapshot);
const formula = testBed.api.getFormula();
await formula.onCalculationEnd();
const resultSnapshot = workbook.save();
const snapshotFilePath = path.resolve(snapshotRootDir, `${getTestFilePath()}-result.json`);
if (fs.existsSync(snapshotFilePath)) {
const resultSnapshotFileString = fs.readFileSync(snapshotFilePath, 'utf-8');
expect(resultSnapshot).toMatchObject(JSON.parse(resultSnapshotFileString));
} else {
fs.writeFileSync(snapshotFilePath, JSON.stringify(resultSnapshot, null, 4));
// eslint-disable-next-line no-console
console.log(`Snapshot file created at: ${snapshotFilePath}`);
}
}
@@ -0,0 +1,24 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* 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 { describe, it } from 'vitest';
import { expectCalculationResultMatchesSnapshot } from '../__testing__/util';
describe('Test formula correctness', () => {
it('basic sum', () => {
expectCalculationResultMatchesSnapshot();
});
});
+17
View File
@@ -0,0 +1,17 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* 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.
*/
export { expectCalculationResultMatchesSnapshot } from './__testing__/util';
+9
View File
@@ -0,0 +1,9 @@
{
"extends": "@univerjs-infra/shared/tsconfigs/base",
"compilerOptions": {
"rootDir": "src",
"outDir": "lib/types"
},
"references": [{ "path": "./tsconfig.node.json" }],
"include": ["src"]
}
@@ -0,0 +1,4 @@
{
"extends": "@univerjs-infra/shared/tsconfigs/node",
"include": ["vitest.config.ts", "build.ts"]
}
@@ -0,0 +1,3 @@
import createConfig from '@univerjs-infra/shared/vitest';
export default createConfig();