diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md
index 14a0fcaa81..916dadda53 100644
--- a/.github/ISSUE_TEMPLATE/bug-report.md
+++ b/.github/ISSUE_TEMPLATE/bug-report.md
@@ -49,7 +49,7 @@ eg.
-
+
### 🔗 Reproduce Link
diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md
index bc72b546fd..518d3e947a 100644
--- a/.github/ISSUE_TEMPLATE/feature-request.md
+++ b/.github/ISSUE_TEMPLATE/feature-request.md
@@ -8,6 +8,39 @@ labels: 🙏feature request
+### 🏷 Version
+
+
+
+
+
+
+| Package | Version |
+| -------------- | ------- |
+| @antv/s2 | |
+| @antv/s2-react | |
+| @antv/s2-vue | |
+
+### Sheet Type
+
+
+
+
+- [ ] PivotSheet
+- [ ] TableSheet
+- [ ] GridAnalysisSheet
+- [ ] StrategySheet
+- [ ] EditableSheet
+
### 🖋 Description
diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml
index 6e3945cfa1..1f7d825c29 100644
--- a/.github/workflows/auto-release.yml
+++ b/.github/workflows/auto-release.yml
@@ -16,7 +16,7 @@ jobs:
node-version: [20] # semantic-release 需要 >= 16 的 Node.js 环境
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
# Python 3.11 和 node-gyp 有兼容问题, 导致无法安装依赖
# https://github.com/slint-ui/slint/commit/a9c48e33502fdebc36c5aa2f4f516c2218424679#diff-944291df2c9c06359d37cc8833d182d705c9e8c3108e7cfe132d61a06e9133dd
@@ -29,7 +29,7 @@ jobs:
version: 8
- name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
@@ -44,7 +44,7 @@ jobs:
{
"msgtype": "link",
"link": {
- "title": "🚀 开始自动发布 🚀",
+ "title": "🚑 开始自动发布 (${{ github.head_ref || github.ref_name }}) 🚑",
"text": "🔗 请点击链接查看详情",
"messageUrl": "https://github.com/antvis/S2/actions/workflows/auto-release.yml",
"picUrl": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gt5-RZDjt3IAAAAAAAAAAAAADmJ7AQ/original"
@@ -77,7 +77,7 @@ jobs:
{
"msgtype": "link",
"link": {
- "title": "🚨 自动发布失败 🚨",
+ "title": "🚨 自动发布失败 (${{ github.head_ref || github.ref_name }})",
"text": "🔗 请点击链接查看具体原因, 及时修复, 尝试点击右上角 [Re-run all jobs] 重试, 或手动发布 🚑",
"messageUrl": "https://github.com/antvis/S2/actions/workflows/auto-release.yml",
"picUrl": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PRSkSqsE_vYAAAAAAAAAAAAADmJ7AQ/original"
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 4a4f797a5a..ee18ab6b2b 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -9,17 +9,21 @@
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
-name: "CodeQL"
+name: 🏨 CodeQL
on:
push:
- branches: [ master ]
+ branches: [ master, alpha, beta, next ]
pull_request:
# The branches below must be a subset of the branches above
- branches: [ master ]
+ branches: [ master, alpha, beta, next ]
schedule:
- cron: '38 0 * * 2'
+concurrency:
+ group: ${{github.workflow}}-${{github.event_name}}-${{github.ref}}
+ cancel-in-progress: true
+
jobs:
analyze:
name: Analyze
diff --git a/.github/workflows/compressed-size.yml b/.github/workflows/compressed-size.yml
index 9092245ce9..c25c7f9a23 100644
--- a/.github/workflows/compressed-size.yml
+++ b/.github/workflows/compressed-size.yml
@@ -4,6 +4,10 @@ on:
pull_request:
types: [opened, synchronize]
+concurrency:
+ group: ${{github.workflow}}-${{github.event_name}}-${{github.ref}}
+ cancel-in-progress: true
+
jobs:
compressed-size:
@@ -11,7 +15,7 @@ jobs:
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
# Python 3.11 和 node-gyp 有兼容问题, 导致无法安装依赖
# https://github.com/slint-ui/slint/commit/a9c48e33502fdebc36c5aa2f4f516c2218424679#diff-944291df2c9c06359d37cc8833d182d705c9e8c3108e7cfe132d61a06e9133dd
diff --git a/.github/workflows/disscustion.yml b/.github/workflows/disscustion.yml
index 4e91b508d2..f863c2fd91 100644
--- a/.github/workflows/disscustion.yml
+++ b/.github/workflows/disscustion.yml
@@ -1,5 +1,5 @@
-name: Discussions
+name: 💬 Discussions
on:
discussion:
@@ -21,6 +21,6 @@ jobs:
"title": "📢 用户: ${{ github.event.discussion.user.login }} 创建了讨论:(${{ github.event.discussion.title }})",
"text": "👀 点击查看",
"messageUrl": "${{ github.event.discussion.html_url }}",
- "picUrl": "https://gw.alipayobjects.com/zos/antfincdn/ISzgBCtgR/2c5c4aaa-4f40-46f7-8f6b-427fa9ff07bb.png"
+ "picUrl": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*1PTTQLk3j5AAAAAAAAAAAAAADmJ7AQ/original"
}
}
diff --git a/.github/workflows/issue-labeled.yml b/.github/workflows/issue-labeled.yml
index 4eb12f78cc..31f9629bdf 100644
--- a/.github/workflows/issue-labeled.yml
+++ b/.github/workflows/issue-labeled.yml
@@ -105,7 +105,7 @@ jobs:
body: |
你好 @${{ github.event.issue.user.login }},经过我们的反复讨论, 你的需求现已被采纳, 我们会排期开发, 但人力资源有限, 短期内无法支持, 请关注后续发布日志。当然, 如果能贡献 PR 帮助我们改进, 不胜感激!
- Hello, @${{ github.vent.issue.user.login }}, your feature request has been accepted after our repeated discussion. We will schedule the development. However, it could not be supported in the short term since limited time, please pay attention to the follow-up release logs. Of course, looking forward for your PR!
+ Hello, @${{ github.event.issue.user.login }}, your feature request has been accepted after our repeated discussion. We will schedule the development. However, it could not be supported in the short term since limited time, please pay attention to the follow-up release logs. Of course, looking forward for your PR!
- name: Rejected
if: github.event.label.name == '❌ won''t support'
@@ -118,3 +118,25 @@ jobs:
你好 @${{ github.event.issue.user.login }},经过我们的反复讨论, 你的需求过于定制化,不适合直接添加到 S2 中, S2 作为开源框架,只会进行通用能力的增强和自定义接口的开放。你可以通过 S2 提供的自定义能力自行实现,感谢你的理解。
Hello, @${{ github.event.issue.user.login }}, After our repeated discussions, your needs are too customized and not suitable for implementing directly to S2. As an open source framework, S2 will only enhance general capabilities and open custom interfaces. You can implement it yourself through the customization capabilities provided by S2, thank you for your understanding.
+
+ - name: Supported or fixed in next
+ if: github.event.label.name == '✨ supported or fixed in next'
+ uses: actions-cool/issues-helper@main
+ with:
+ actions: 'create-comment'
+ token: ${{ secrets.GITHUB_TOKEN }}
+ issue-number: ${{ github.event.issue.number }}
+ body: |
+ 你好 @${{ github.event.issue.user.login }},该功能或缺陷已经在 `2.0 next 版本` 中支持或修复,`next` 版本目前处于内测中, 感谢你的支持与理解。
+
+ 如有任何 `2.0 版本` 问题,请前往[讨论区](https://github.com/antvis/S2/discussions/1933),正式版预计年底发布 (文档施工中 🚧), 抢先试用:
+
+ ```bash
+ yarn add @antv/s2@next
+ yarn add @antv/s2-react@next
+ yarn add @antv/s2-vue@next
+ ```
+
+ Hello, @${{ github.event.issue.user.login }}, This feature or flaw has been supported or fixed in `2.0 next version`, `next` version is currently in private beta, thank you for your support and understanding.
+
+ Any `2.0` version issues, please go to [discussion](https://github.com/antvis/S2/discussions/1933), which released the official version is expected to the end (document 🚧) during construction, the first trial:
diff --git a/.github/workflows/issue-opend.yml b/.github/workflows/issue-opend.yml
index 1cfb08c64c..ec973f8af4 100644
--- a/.github/workflows/issue-opend.yml
+++ b/.github/workflows/issue-opend.yml
@@ -20,9 +20,9 @@ jobs:
Hello, @${{ github.event.issue.user.login }}, please edit your issue title. a concise issue title will save everyone time. please do not leave the title as the body or empty.
- # 如果是 bug 的 issue, 但是基本的版本号,表格类型, 描述都没有, 直接关闭, 不多BB.
- - name: check bug report issue body
- if: contains(github.event.issue.title, '🐛') == true && contains(github.event.issue.body, 'Version') == false && contains(github.event.issue.body, 'Sheet Type') == false && contains(github.event.issue.body, 'Description') == false
+ # 如果 issue 的提交者无视模版, 连基本的版本号,表格类型, 描述都没有, 直接自动关闭, 不多BB.
+ - name: check issue body
+ if: contains(github.event.issue.body, 'Version') == false && contains(github.event.issue.body, 'Sheet Type') == false && contains(github.event.issue.body, 'Description') == false
uses: actions-cool/issues-helper@main
with:
actions: 'create-comment,add-labels,close-issue'
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 2f2d4322d0..c43309deac 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -1,4 +1,4 @@
-name: lint
+name: 👨🔬 lint
on: [pull_request]
@@ -6,7 +6,6 @@ concurrency:
group: ${{github.workflow}}-${{github.event_name}}-${{github.ref}}
cancel-in-progress: true
-
jobs:
lint:
runs-on: macos-latest
@@ -16,7 +15,7 @@ jobs:
node-version: [20]
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
# Python 3.11 和 node-gyp 有兼容问题, 导致无法安装依赖
# https://github.com/slint-ui/slint/commit/a9c48e33502fdebc36c5aa2f4f516c2218424679#diff-944291df2c9c06359d37cc8833d182d705c9e8c3108e7cfe132d61a06e9133dd
@@ -29,7 +28,7 @@ jobs:
version: 8
- name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
@@ -43,8 +42,8 @@ jobs:
- name: Build
run: pnpm build
- - name: Bundle size
- run: pnpm bundle:size
+ - name: Bundle size limit
+ run: pnpm build:size-limit
env:
CI: true
BUNDLESIZE_GITHUB_TOKEN: ${{ secrets.BUNDLESIZE_GITHUB_TOKEN }}
diff --git a/.github/workflows/pr-auto-assign-reviewer.yml b/.github/workflows/pr-auto-assign-reviewer.yml
index 9f74e609f9..cc1f6cec4e 100644
--- a/.github/workflows/pr-auto-assign-reviewer.yml
+++ b/.github/workflows/pr-auto-assign-reviewer.yml
@@ -21,5 +21,5 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
pr-emoji: '+1, rocket'
- reviewers: 'serializedowen,lcx-seima,lijinke666,wjgogogo,stone-lyl,GaoFuhong'
+ reviewers: 'lijinke666,wjgogogo,wuhaiyang'
review-creator: false
diff --git a/.github/workflows/prerelease-notify.yml b/.github/workflows/prerelease-notify.yml
index 12d063a8d8..84126f1d97 100644
--- a/.github/workflows/prerelease-notify.yml
+++ b/.github/workflows/prerelease-notify.yml
@@ -23,7 +23,7 @@ jobs:
${{ secrets.DING_TALK_ACCESS_TOKEN }}
${{ secrets.DING_TALK_GROUP_TOKEN }}
notify_title: '🎉 {release_tag} 发布 🎉'
- notify_body: '## { title }
![preview](https://gw.alipayobjects.com/zos/antfincdn/ISzgBCtgR/2c5c4aaa-4f40-46f7-8f6b-427fa9ff07bb.png)
{ body }
'
+ notify_body: '## { title }
![preview](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*1PTTQLk3j5AAAAAAAAAAAAAADmJ7AQ/original)
{ body }
'
notify_footer: '> 该版本为测试版, 请谨慎使用, 前往 [**AntV/S2 Releases**]({ release_url }) 查看完整更新日志.'
at_all: false
enable_prerelease: true
diff --git a/.github/workflows/release-notify.yml b/.github/workflows/release-notify.yml
index 36452302a0..b4d892176f 100644
--- a/.github/workflows/release-notify.yml
+++ b/.github/workflows/release-notify.yml
@@ -18,8 +18,8 @@ jobs:
${{ secrets.DING_TALK_ACCESS_TOKEN }}
${{ secrets.DING_TALK_GROUP_TOKEN }}
${{ secrets.DING_TALK_PUBLIC_TOKEN }}
- notify_title: '🎉 S2 新版本发布啦 🎉'
- notify_body: '## { title }
![preview](https://gw.alipayobjects.com/zos/antfincdn/ISzgBCtgR/2c5c4aaa-4f40-46f7-8f6b-427fa9ff07bb.png)
看看有哪些更新吧
'
+ notify_title: '🎉 AntV/S2 新版本发布啦 🎉'
+ notify_body: '## { title }
![preview](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*1PTTQLk3j5AAAAAAAAAAAAAADmJ7AQ/original)
看看有哪些更新吧
'
notify_footer: '> 前往 [**AntV/S2 Releases**](https://github.com/antvis/S2/releases/latest) 查看完整更新日志.'
at_all: false
enable_prerelease: false
diff --git a/.github/workflows/release-success.yml b/.github/workflows/release-success.yml
index 164f782554..6fefaea70c 100644
--- a/.github/workflows/release-success.yml
+++ b/.github/workflows/release-success.yml
@@ -16,8 +16,19 @@ jobs:
defaults:
run:
working-directory: s2-site
+
+ strategy:
+ matrix:
+ node-version: [18]
+
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
+
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.node-version }}
+ cache: 'yarn'
- name: Git bootstrap
run: |
@@ -56,7 +67,7 @@ jobs:
{
"msgtype": "link",
"link": {
- "title": "📢 开始自动部署旧版官网(https://s2.antv.vision) 📢 ",
+ "title": "📢 开始自动部署旧版官网 (https://s2.antv.vision) 📢 ",
"text": "🔗 请点击链接查看详情",
"messageUrl": "https://github.com/antvis/S2/actions/workflows/release-success.yml",
"picUrl": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gt5-RZDjt3IAAAAAAAAAAAAADmJ7AQ/original"
@@ -68,7 +79,7 @@ jobs:
with:
node-version: 16
cache: 'yarn'
-
+
# 安装官网依赖
- name: Install Dependencies
run: yarn
diff --git a/.github/workflows/site-build-notify.yml b/.github/workflows/site-build-notify.yml
index 9022cbc5f6..d34d32097c 100644
--- a/.github/workflows/site-build-notify.yml
+++ b/.github/workflows/site-build-notify.yml
@@ -16,10 +16,10 @@ jobs:
{
"msgtype": "link",
"link": {
- "title": "✅ 旧官网(https://s2.antv.vision) 部署成功",
- "text": "点击访问 https://s2.antv.vision/",
+ "title": "✅ 旧官网 (https://s2.antv.vision) 部署成功",
+ "text": "点击访问",
"messageUrl": "https://s2.antv.vision/",
- "picUrl": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Eel8Rp5jlAkAAAAAAAAAAAAADmJ7AQ/original"
+ "picUrl": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*1PTTQLk3j5AAAAAAAAAAAAAADmJ7AQ/original"
}
}
diff --git a/.github/workflows/sync-notify.yml b/.github/workflows/sync-notify.yml
index afde29a503..227d218ae5 100644
--- a/.github/workflows/sync-notify.yml
+++ b/.github/workflows/sync-notify.yml
@@ -23,7 +23,7 @@ jobs:
"title": "✅ 同步 changelog 成功",
"text": "📢 请发布值班合并该 PR 后, 访问官网查看是否有异常",
"messageUrl": "https://s2.antv.antgroup.com",
- "picUrl": "https://gw.alipayobjects.com/zos/antfincdn/ISzgBCtgR/2c5c4aaa-4f40-46f7-8f6b-427fa9ff07bb.png"
+ "picUrl": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*1PTTQLk3j5AAAAAAAAAAAAAADmJ7AQ/original"
}
}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 3fb24312f1..7a6b58f018 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1,4 +1,4 @@
-name: test
+name: 💯 test
on: [pull_request]
@@ -18,7 +18,7 @@ jobs:
node-version: [20]
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
# Python 3.11 和 node-gyp 有兼容问题, 导致无法安装依赖
# https://github.com/slint-ui/slint/commit/a9c48e33502fdebc36c5aa2f4f516c2218424679#diff-944291df2c9c06359d37cc8833d182d705c9e8c3108e7cfe132d61a06e9133dd
@@ -31,7 +31,7 @@ jobs:
version: 8
- name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
@@ -44,9 +44,10 @@ jobs:
pnpm test:ci-coverage
- name: Upload test coverage
- uses: codecov/codecov-action@v2
+ uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
+ fail_ci_if_error: false
verbose: true
- name: Workflow failed alert
diff --git a/.releaserc.base.js b/.releaserc.base.js
index 29d4c0ef0e..544d514383 100644
--- a/.releaserc.base.js
+++ b/.releaserc.base.js
@@ -1,11 +1,13 @@
+const path = require('path');
+
module.exports = {
+ extends: 'semantic-release-monorepo',
branches: [
'latest',
{ name: 'beta', channel: 'beta', prerelease: true },
{ name: 'alpha', channel: 'alpha', prerelease: true },
{ name: 'next', channel: 'next', prerelease: true },
],
- extends: 'semantic-release-monorepo',
plugins: [
[
'@semantic-release/commit-analyzer',
@@ -26,11 +28,19 @@ module.exports = {
'@semantic-release/npm',
[
'@semantic-release/git',
- {
+ {
message: 'chore(release): 🤖 ${nextRelease.gitTag} [skip ci]',
- },
+ },
],
'@semantic-release/github',
+ [
+ '@semantic-release/exec',
+ {
+ prepareCmd:
+ `node ${path.resolve(__dirname, './scripts/add-version.js')} ` +
+ '${nextRelease.gitTag}',
+ },
+ ],
],
preset: 'angular',
};
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b7b5f275ed..5f81433362 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -38,7 +38,7 @@
2. 安装依赖:`pnpm install`
3. 提交你的改动,commit 请遵守 [AngularJS Git Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#heading=h.uyo6cb12dt6w)
4. 如果你的改动是修复 bug, 还可以在提交信息后面加上 `close #issue 号`, 这样可以在 pr 合并后,可以自动关闭对应的 issue, 比如 `fix: render bug close #123`
-5. 确保加上了对应的单元测试和文档 (如有必要)
+5. 确保加上了对应的单元测试和文档 (如果有 `Snapshot` UI 快照 (.snap 文件)更新, 可以运行 `yarn core:test -- -u` 和 `yarn react:test -- -u` 自动更新, 并一起提交上来, 请勿手动编辑)
6. 所有 Lint 和 Test 检查通过后,并且 review 通过,我们会合并你的 pr.
![preview](https://gw.alipayobjects.com/zos/antfincdn/ssOxFrycD/86339514-5f9a-4101-8690-e47c97cd8af5.png)
diff --git a/LICENSE b/LICENSE
index 6fc25ee611..a63e9f8b5b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2021 AntV
+Copyright (c) 2021-present AntV
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.en-US.md b/README.en-US.md
index 1b93f73601..e2902b21bc 100644
--- a/README.en-US.md
+++ b/README.en-US.md
@@ -68,9 +68,9 @@ demo components and expansion capabilities, it allows developers to use it quick
## 📦 Installation
```bash
-$ npm install @antv/s2
-# yarn add @antv/s2
-# pnpm install @antv/s2
+$ npm install @antv/s2 --save
+# yarn add @antv/s2 --save
+# pnpm install @antv/s2 --save
```
## 🔨 Getting Started
@@ -229,9 +229,6 @@ pnpm site:start
-
-
-
## 👬 Contributors
diff --git a/README.md b/README.md
index 5b32f0d71a..1210bbc8bf 100644
--- a/README.md
+++ b/README.md
@@ -64,9 +64,9 @@ S2 是 AntV 在多维交叉分析表格领域的解决方案,完全基于数
## 📦 安装
```bash
-$ npm install @antv/s2
-# yarn add @antv/s2
-# pnpm install @antv/s2
+$ npm install @antv/s2 --save
+# yarn add @antv/s2 --save
+# pnpm install @antv/s2 --save
```
## 🔨 使用
@@ -223,9 +223,6 @@ pnpm site:start
-
-
-
## 👬 Contributors
diff --git a/package.json b/package.json
index 8fcdb05722..0b20ab3a44 100644
--- a/package.json
+++ b/package.json
@@ -97,6 +97,7 @@
"@rollup/plugin-typescript": "^11.1.5",
"@rushstack/eslint-patch": "^1.5.1",
"@semantic-release/changelog": "^6.0.3",
+ "@semantic-release/exec": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@swc/core": "^1.3.95",
"@swc/jest": "^0.2.29",
@@ -164,7 +165,8 @@
"typescript": "^5.2.2",
"vite": "^4.5.0",
"vite-plugin-imp": "^2.4.0",
- "vue-jest": "^5.0.0-alpha.10"
+ "vue-jest": "^5.0.0-alpha.10",
+ "size-limit": "^11.0.0"
},
"license": "MIT",
"repository": {
diff --git a/packages/s2-core/CHANGELOG.md b/packages/s2-core/CHANGELOG.md
index ee669635bd..d2bec1e76c 100644
--- a/packages/s2-core/CHANGELOG.md
+++ b/packages/s2-core/CHANGELOG.md
@@ -1,22 +1,19 @@
# [@antv/s2-v2.0.0-next.10](https://github.com/antvis/S2/compare/@antv/s2-v2.0.0-next.9...@antv/s2-v2.0.0-next.10) (2023-12-12)
-
### Features
* 支持在单元格内渲染 G2 图表 ([#2437](https://github.com/antvis/S2/issues/2437)) ([497f941](https://github.com/antvis/S2/commit/497f9414b89fce01b60db9b6c2eb4292ffe69c1d))
# [@antv/s2-v2.0.0-next.9](https://github.com/antvis/S2/compare/@antv/s2-v2.0.0-next.8...@antv/s2-v2.0.0-next.9) (2023-11-22)
-
### Features
* headerActionIcons 支持细粒度配置 & 修复异步渲染导致无法获取实例的问题 ([#2301](https://github.com/antvis/S2/issues/2301)) ([b2d6f1f](https://github.com/antvis/S2/commit/b2d6f1fb04d3fa73129669fc7d2dec84943252db))
* **layout:** 单元格支持渲染多行文本 ([#2383](https://github.com/antvis/S2/issues/2383)) ([e3b919a](https://github.com/antvis/S2/commit/e3b919a4f37d600a0f516944edf4eed8b2c0174d))
* 支持 antd v5 ([#2413](https://github.com/antvis/S2/issues/2413)) ([299c7bf](https://github.com/antvis/S2/commit/299c7bfe2e86838153273c92dd6d2b72917cfdea))
-* 支持 React 18 (兼容 React 16/17) ([#2373](https://github.com/antvis/S2/issues/2373)) ([25ce9b0](https://github.com/antvis/S2/commit/25ce9b0ccc3e609d8add09b3209f6f981dc1dc4e))
+* 支持 React 18 (兼容 React 16/17) ([#2373](https://github.com/antvis/S2/issues/2373)) ([25ce9b0](https://github.com/antvis/S2/commit/25ce9b0ccc3e609d8add09b3209f6f981dc1dc4e))
* 支持自定义 G 5.0 插件和配置 ([#2423](https://github.com/antvis/S2/issues/2423)) ([cc6c47f](https://github.com/antvis/S2/commit/cc6c47fd0927125bbc378fe6914becfcbe1b0acd))
-
### BREAKING CHANGES
* 移除 devicePixelRatio 和 supportsCSSTransform
@@ -75,13 +72,13 @@
### Features
* 使用 requestIdleCallback 处理数据大量导出的情况 ([#2272](https://github.com/antvis/S2/issues/2272)) ([42a5551](https://github.com/antvis/S2/commit/42a55516dd369d9ab5579b52fbc9900b0ad81858))
-* 同步复制支持自定义transformer ([#2201](https://github.com/antvis/S2/issues/2201)) ([9003767](https://github.com/antvis/S2/commit/9003767d584248b9d122f299326fd14753961883))
+* 同步复制支持自定义 transformer ([#2201](https://github.com/antvis/S2/issues/2201)) ([9003767](https://github.com/antvis/S2/commit/9003767d584248b9d122f299326fd14753961883))
* 增加暗黑主题 ([#2130](https://github.com/antvis/S2/issues/2130)) ([51dbdcf](https://github.com/antvis/S2/commit/51dbdcf564b387a3fd1809a71016f3a91eebde38))
* 完善复制和导出在格式化后,总计、小计对应数值没有格式化的问题 ([#2237](https://github.com/antvis/S2/issues/2237)) ([abc0dbb](https://github.com/antvis/S2/commit/abc0dbb1544d9a4ef133e6a2c7d2d09ac8f35b48))
* 文本和图标的条件格式支持主题配置 ([#2267](https://github.com/antvis/S2/issues/2267)) ([c332c68](https://github.com/antvis/S2/commit/c332c687dfb7be1d07b79b44934f78c1947cc466))
* 条件格式 mapping 增加第三个参数获取单元格实例 ([#2242](https://github.com/antvis/S2/issues/2242)) ([aae427d](https://github.com/antvis/S2/commit/aae427dfe6a87cae577ce2449fd6058d358971f9))
* 行列头兼容 condition icon 和 action icons ([#2161](https://github.com/antvis/S2/issues/2161)) ([1df4286](https://github.com/antvis/S2/commit/1df42860f6a12d3cb182ba7633c4984a04e62890))
-* 适配g5.0异步渲染 ([#2251](https://github.com/antvis/S2/issues/2251)) ([069d03d](https://github.com/antvis/S2/commit/069d03d299429c2ffab3e20d56ecd6bb30119ffd))
+* 适配 g5.0 异步渲染 ([#2251](https://github.com/antvis/S2/issues/2251)) ([069d03d](https://github.com/antvis/S2/commit/069d03d299429c2ffab3e20d56ecd6bb30119ffd))
# [@antv/s2-v2.0.0-next.7](https://github.com/antvis/S2/compare/@antv/s2-v2.0.0-next.6...@antv/s2-v2.0.0-next.7) (2023-04-28)
@@ -95,25 +92,25 @@
* **tooltip:** 修复特定配置下点击 tooltip 内容后 tooltip 关闭 close [#2170](https://github.com/antvis/S2/issues/2170) ([#2172](https://github.com/antvis/S2/issues/2172)) ([6219e57](https://github.com/antvis/S2/commit/6219e579364cfb7ac3a8b3db4ae01c5672d7f2d4))
* 修复 cornerText 配置对树状模式的适配 ([#2167](https://github.com/antvis/S2/issues/2167)) ([e9efcea](https://github.com/antvis/S2/commit/e9efcea944f5d0793d4a1250362e6b6f6b492c52))
* 修复总计小计 linkField 样式问题 ([#2169](https://github.com/antvis/S2/issues/2169)) ([4450278](https://github.com/antvis/S2/commit/4450278d82888c117e5bd9d31874b88ecdb33d99))
-* 修改DataCell类 drawLinkFieldShape 方法名为 drawLinkFieldShapeOwn ([d5e14b2](https://github.com/antvis/S2/commit/d5e14b25abba5bfaf74dddb17d9f5b44c74bc29b))
+* 修改 DataCell 类 drawLinkFieldShape 方法名为 drawLinkFieldShapeOwn ([d5e14b2](https://github.com/antvis/S2/commit/d5e14b25abba5bfaf74dddb17d9f5b44c74bc29b))
* 多指标行头总计节点宽度计算错误 ([#2165](https://github.com/antvis/S2/issues/2165)) ([08ef330](https://github.com/antvis/S2/commit/08ef330a02a1fbf11f49090f4fd7f5d2b0cc1093))
-* 微应用环境识别mouseEvent失效 ([bddbe34](https://github.com/antvis/S2/commit/bddbe34104355ac0087bc9f72377889a8f444d7a)), closes [#2162](https://github.com/antvis/S2/issues/2162)
+* 微应用环境识别 mouseEvent 失效 ([bddbe34](https://github.com/antvis/S2/commit/bddbe34104355ac0087bc9f72377889a8f444d7a)), closes [#2162](https://github.com/antvis/S2/issues/2162)
* 统一风格、删除冗余代码 ([7b4ef0e](https://github.com/antvis/S2/commit/7b4ef0edf72e059b427c54e6ea881c4c8e347aed))
* 行头过宽且不冻结时滚动条渲染错误 ([#2173](https://github.com/antvis/S2/issues/2173)) ([ab79ea0](https://github.com/antvis/S2/commit/ab79ea0664046bc6479a717d7b3b0ee7efe05b31))
-* 避免s2实例被污染 ([8c44a85](https://github.com/antvis/S2/commit/8c44a85a678eadaab3fb2a66b5b02a123f74c9bb))
+* 避免 s2 实例被污染 ([8c44a85](https://github.com/antvis/S2/commit/8c44a85a678eadaab3fb2a66b5b02a123f74c9bb))
### Features
-* icon支持更新name与fill ([#2138](https://github.com/antvis/S2/issues/2138)) ([d000aea](https://github.com/antvis/S2/commit/d000aeac332676cfa15d9986ec7f4be948c565d0))
+* icon 支持更新 name 与 fill ([#2138](https://github.com/antvis/S2/issues/2138)) ([d000aea](https://github.com/antvis/S2/commit/d000aeac332676cfa15d9986ec7f4be948c565d0))
* **interaction:** 点击角头后支持选中所对应那一列的行头 close [#2073](https://github.com/antvis/S2/issues/2073) ([#2081](https://github.com/antvis/S2/issues/2081)) ([ad2b5d8](https://github.com/antvis/S2/commit/ad2b5d87edf4c529d7c9a5e1348e893e14547ef3))
* **interaction:** 行头支持滚动刷选 ([#2087](https://github.com/antvis/S2/issues/2087)) ([65c3f3b](https://github.com/antvis/S2/commit/65c3f3b6a37709c0fa684b0f5717d3b349251e48))
-* 修改文档、添加用例演示、修改方法名drawLinkFieldShapLogic -> drawLinkField ([7f2bd69](https://github.com/antvis/S2/commit/7f2bd690bd703b8e4d678c03b9fc79db30848ca3))
+* 修改文档、添加用例演示、修改方法名 drawLinkFieldShapLogic -> drawLinkField ([7f2bd69](https://github.com/antvis/S2/commit/7f2bd690bd703b8e4d678c03b9fc79db30848ca3))
* 在 shape 中添加文本的原始值 ([#2109](https://github.com/antvis/S2/issues/2109)) ([4d81e72](https://github.com/antvis/S2/commit/4d81e72440d797fd7a06179794c342f009fc39c3))
-* 增加dataCell 下划线测试用例及demo ([a5efe17](https://github.com/antvis/S2/commit/a5efe17bda06cc8eba633cbea9c56ceb8b8c703e))
-* 增加自定义merged-cell ([534cc15](https://github.com/antvis/S2/commit/534cc15da9f766f95be3c622e65e45d8796ff020))
-* 复制支持自定义transformer ([#2090](https://github.com/antvis/S2/issues/2090)) ([250eecd](https://github.com/antvis/S2/commit/250eecd32ed4f48b95ed7c4e480fa3c75d4bb5d7))
+* 增加 dataCell 下划线测试用例及 demo ([a5efe17](https://github.com/antvis/S2/commit/a5efe17bda06cc8eba633cbea9c56ceb8b8c703e))
+* 增加自定义 merged-cell ([534cc15](https://github.com/antvis/S2/commit/534cc15da9f766f95be3c622e65e45d8796ff020))
+* 复制支持自定义 transformer ([#2090](https://github.com/antvis/S2/issues/2090)) ([250eecd](https://github.com/antvis/S2/commit/250eecd32ed4f48b95ed7c4e480fa3c75d4bb5d7))
* 提取跳转链接下划线 公共逻辑 到 BaseCell 类 ([34dbbb3](https://github.com/antvis/S2/commit/34dbbb3bdf028cb96508dcead724d9ac9bcc1ab9))
-* 数据单元格DataCell类中增加链接跳转渲染 ([bb5a964](https://github.com/antvis/S2/commit/bb5a964787a80843515b4d552adb3fdb59393e3d))
+* 数据单元格 DataCell 类中增加链接跳转渲染 ([bb5a964](https://github.com/antvis/S2/commit/bb5a964787a80843515b4d552adb3fdb59393e3d))
# [@antv/s2-v2.0.0-next.6](https://github.com/antvis/S2/compare/@antv/s2-v2.0.0-next.5...@antv/s2-v2.0.0-next.6) (2023-04-23)
@@ -300,7 +297,6 @@
### Bug Fixes
-* 下钻后 meta.childField 不正确 ([#1788](https://github.com/antvis/S2/issues/1788)) ([1c61dd4](https://github.com/antvis/S2/commit/1c61dd4081c9d3fed6f276b0546865914040b07a))
* 重构绘制盒模型,修复边框偏移问题 ([#1854](https://github.com/antvis/S2/issues/1854)) ([f7e0858](https://github.com/antvis/S2/commit/f7e0858a937ea557532a7fff948e9af3b6a1fdff))
# [@antv/s2-v1.35.0](https://github.com/antvis/S2/compare/@antv/s2-v1.34.1...@antv/s2-v1.35.0) (2022-11-21)
@@ -315,11 +311,11 @@
# [@antv/s2-v1.35.0](https://github.com/antvis/S2/compare/@antv/s2-v1.34.1...@antv/s2-v1.35.0) (2022-11-21)
-### Features
+=======
-* 明细表支持多级表头 ([#1921](https://github.com/antvis/S2/issues/1921)) ([47cdbdc](https://github.com/antvis/S2/commit/47cdbdccafbd7f19a05550a483a42aac11a93778)), closes [#1687](https://github.com/antvis/S2/issues/1687) [#1801](https://github.com/antvis/S2/issues/1801)
+# [@antv/s2-v1.35.1](https://github.com/antvis/S2/compare/@antv/s2-v1.35.0...@antv/s2-v1.35.1) (2022-11-28)
-# [@antv/s2-v1.34.1](https://github.com/antvis/S2/compare/@antv/s2-v1.34.0...@antv/s2-v1.34.1) (2022-11-18)
+### Bug Fixes
### Bug Fixes
@@ -487,11 +483,6 @@
* 复制支持 html 格式 ([#1647](https://github.com/antvis/S2/issues/1647)) ([3ea6349](https://github.com/antvis/S2/commit/3ea634970a162d869cf12dad7aa754bebafd30f3))
* 支持 resize 最右侧 column ([#1611](https://github.com/antvis/S2/issues/1611)) ([f63bfa2](https://github.com/antvis/S2/commit/f63bfa2a0e95c8c42c064d0e2e56ce9550ac50c6))
-# [@antv/s2-v1.24.0](https://github.com/antvis/S2/compare/@antv/s2-v1.23.0...@antv/s2-v1.24.0) (2022-07-22)
-
-### Bug Fixes
-
-* **layout:** 修复 Firefox 浏览器部分 icon 渲染失败 close [#1571](https://github.com/antvis/S2/issues/1571) ([#1599](https://github.com/antvis/S2/issues/1599)) ([6b76c4e](https://github.com/antvis/S2/commit/6b76c4e2c80b88eeb63d7adfc6b48da7d0b3ea4c))
* **strategysheet:** 修复单元格宽度拖拽变小后子弹图宽度计算错误 ([#1584](https://github.com/antvis/S2/issues/1584)) ([99b8593](https://github.com/antvis/S2/commit/99b859392c7151d5700bf1c505a02f795b9a3f80))
* **strategysheet:** 修复子弹图进度小于 1% 时显示错误的问题 ([#1563](https://github.com/antvis/S2/issues/1563)) ([936ca6a](https://github.com/antvis/S2/commit/936ca6a3a7bf40ddc0ff1a0271c3a5ffb1091dcf))
* **strategysheet:** 修复子弹图颜色显示错误 & 百分比精度问题 ([#1588](https://github.com/antvis/S2/issues/1588)) ([c4bb48c](https://github.com/antvis/S2/commit/c4bb48cbe128b47e3574af903142934fd7452846))
diff --git a/packages/s2-core/README.md b/packages/s2-core/README.md
index 80a489c909..c04f9fec8c 100644
--- a/packages/s2-core/README.md
+++ b/packages/s2-core/README.md
@@ -143,7 +143,7 @@ const s2DataConfig = {
```ts
const s2Options = {
width: 600,
- height: 600,
+ height: 600
}
```
@@ -219,9 +219,6 @@ pnpm site:start
-
-
-
## 👬 Contributors
diff --git a/packages/s2-core/__tests__/bugs/__snapshots__/issue-2359-spec.ts.snap b/packages/s2-core/__tests__/bugs/__snapshots__/issue-2359-spec.ts.snap
new file mode 100644
index 0000000000..076a151e3f
--- /dev/null
+++ b/packages/s2-core/__tests__/bugs/__snapshots__/issue-2359-spec.ts.snap
@@ -0,0 +1,67 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Table Sheet Custom Multiple Values Tests should use current cell text theme 1`] = `
+Array [
+ Array [
+ Object {
+ "fill": "#000000",
+ "fontSize": 12,
+ },
+ ],
+ Array [
+ Object {
+ "fill": "red",
+ "fontSize": 20,
+ },
+ Object {
+ "fill": "red",
+ "fontSize": 20,
+ },
+ Object {
+ "fill": "red",
+ "fontSize": 20,
+ },
+ ],
+]
+`;
+
+exports[`Table Sheet Custom Multiple Values Tests should use current cell text theme 2`] = `
+Array [
+ Array [
+ Object {
+ "fill": "#000000",
+ "fontSize": 12,
+ },
+ ],
+ Array [
+ Object {
+ "fill": "#000000",
+ "fontSize": 12,
+ },
+ ],
+ Array [
+ Object {
+ "fill": "#000000",
+ "fontSize": 12,
+ },
+ ],
+ Array [
+ Object {
+ "fill": "green",
+ "fontSize": 30,
+ },
+ ],
+ Array [
+ Object {
+ "fill": "green",
+ "fontSize": 30,
+ },
+ ],
+ Array [
+ Object {
+ "fill": "green",
+ "fontSize": 30,
+ },
+ ],
+]
+`;
diff --git a/packages/s2-core/__tests__/bugs/__snapshots__/issue-565-spec.ts.snap b/packages/s2-core/__tests__/bugs/__snapshots__/issue-565-spec.ts.snap
new file mode 100644
index 0000000000..72fd2fd2d2
--- /dev/null
+++ b/packages/s2-core/__tests__/bugs/__snapshots__/issue-565-spec.ts.snap
@@ -0,0 +1,13 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Export data in pivot tree mode should export correct col header in pivot tree mode 1`] = `
+" col0 col0-0 col0-0
+ col1 col1-0 col1-1
+ col2 col2-0 col2-0
+row0 row1 row2 number number
+row0
+row0 row1-0
+row0 row1-0 row2-0 3
+row0 row1-1
+row0 row1-1 row2-0 2 4"
+`;
diff --git a/packages/s2-core/__tests__/bugs/issue-1191-spec.ts b/packages/s2-core/__tests__/bugs/issue-1191-spec.ts
index f533ac3630..696f9e0ca1 100644
--- a/packages/s2-core/__tests__/bugs/issue-1191-spec.ts
+++ b/packages/s2-core/__tests__/bugs/issue-1191-spec.ts
@@ -49,7 +49,7 @@ const dataCfg: S2DataConfig = {
{
field: 'price',
name: '价格',
- formatter: (v) => `price:${v}`,
+ formatter: (v) => `price: ${v}`,
},
],
};
@@ -74,21 +74,21 @@ describe('Link Field Tests', () => {
test('province row cell should use link field style', () => {
// 浙江省对应 cell
- const province = s2.facet.rowHeader?.children[0];
+ const province = s2.facet
+ .getRowCells()
+ .find((cell) => cell.getMeta().value === '浙江');
- // @ts-ignore
- expect(province.textShape.attr('fill')).toEqual('red');
- // @ts-ignore
- expect(province.linkFieldShape).toBeDefined();
+ expect(province?.getTextShape().attr('fill')).toEqual('red');
+ expect(province?.getLinkFieldShape()).toBeDefined();
});
test('city row cell should not use link field style', () => {
// 义乌对应 cell
- const city = s2.facet.rowHeader?.children[1];
+ const city = s2.facet
+ .getRowCells()
+ .find((cell) => cell.getMeta().value === '义乌');
- // @ts-ignore
- expect(city.textShape.attr('fill')).not.toEqual('red');
- // @ts-ignore
- expect(city.linkFieldShape).not.toBeDefined();
+ expect(city?.getTextShape().attr('fill')).not.toEqual('red');
+ expect(city?.getLinkFieldShape()).not.toBeDefined();
});
});
diff --git a/packages/s2-core/__tests__/bugs/issue-1201-spec.ts b/packages/s2-core/__tests__/bugs/issue-1201-spec.ts
index f04d0d57d5..2af1b5b5bb 100644
--- a/packages/s2-core/__tests__/bugs/issue-1201-spec.ts
+++ b/packages/s2-core/__tests__/bugs/issue-1201-spec.ts
@@ -4,11 +4,12 @@
* https://github.com/antvis/S2/issues/1201
* fillOpacity
*/
-import { getContainer } from '../util/helpers';
+import type { S2Options } from '../../src';
import * as mockDataConfig from '../data/data-issue-292.json';
+import { getContainer } from '../util/helpers';
import { PivotSheet } from '@/sheet-type';
-const s2Options = {
+const s2Options: S2Options = {
width: 800,
height: 600,
};
@@ -17,22 +18,20 @@ describe('background color opacity test', () => {
test('should set background color opacity correctly', async () => {
const s2 = new PivotSheet(getContainer(), mockDataConfig, s2Options);
- s2.setThemeCfg({
- theme: {
- cornerCell: {
- cell: {
- backgroundColorOpacity: 0.1,
- },
+ s2.setTheme({
+ cornerCell: {
+ cell: {
+ backgroundColorOpacity: 0.1,
},
- rowCell: {
- cell: {
- backgroundColorOpacity: 0.2,
- },
+ },
+ rowCell: {
+ cell: {
+ backgroundColorOpacity: 0.2,
},
- colCell: {
- cell: {
- backgroundColorOpacity: 0.3,
- },
+ },
+ colCell: {
+ cell: {
+ backgroundColorOpacity: 0.3,
},
},
});
@@ -40,21 +39,18 @@ describe('background color opacity test', () => {
await s2.render();
// corner cell
- const cornerCell = s2.facet.cornerHeader.children[0];
+ const cornerCell = s2.facet.getCornerCells()[0];
- // @ts-ignore
- expect(cornerCell.backgroundShape.attr('fillOpacity')).toEqual(0.1);
+ expect(cornerCell.getBackgroundShape().style.fillOpacity).toEqual(0.1);
// row cell
- const rowCell = s2.facet.rowHeader!.children[0];
+ const rowCell = s2.facet.getRowCells()[0];
- // @ts-ignore
- expect(rowCell.backgroundShape.attr('fillOpacity')).toEqual(0.2);
+ expect(rowCell.getBackgroundShape().style.fillOpacity).toEqual(0.2);
// col cell
- const colCell = s2.facet.columnHeader.children[0].children[0];
+ const colCell = s2.facet.getColCells()[0];
- // @ts-ignore
- expect(colCell.backgroundShape.attr('fillOpacity')).toEqual(0.3);
+ expect(colCell.getBackgroundShape().style.fillOpacity).toEqual(0.3);
});
});
diff --git a/packages/s2-core/__tests__/bugs/issue-1561-spec.ts b/packages/s2-core/__tests__/bugs/issue-1561-spec.ts
index dadd3db4a6..058eeb32c2 100644
--- a/packages/s2-core/__tests__/bugs/issue-1561-spec.ts
+++ b/packages/s2-core/__tests__/bugs/issue-1561-spec.ts
@@ -23,22 +23,23 @@ describe('Grid Border Tests', () => {
const panelScrollGroup = s2.facet.panelGroup.children[0];
const gridGroup = (panelScrollGroup as any).gridGroup as Group;
- const originalLeftBorderBbox = (gridGroup.children[0] as Group).getBBox();
+ const originalLeftBorderBBox = (gridGroup.children[0] as Group).getBBox();
s2.facet.updateScrollOffset({ offsetX: { value: 100, animate: false } });
s2.facet.updateScrollOffset({ offsetX: { value: 200, animate: false } });
s2.facet.updateScrollOffset({ offsetX: { value: 300, animate: false } });
s2.facet.updateScrollOffset({ offsetX: { value: 0, animate: false } });
- const newLeftBorderBbox = (gridGroup.children[0] as Group).getBBox();
+
+ const newLeftBorderBBbox = (gridGroup.children[0] as Group).getBBox();
const widthRatio =
- newLeftBorderBbox.right -
- newLeftBorderBbox.left -
- (originalLeftBorderBbox.right - originalLeftBorderBbox.left);
+ newLeftBorderBBbox.right -
+ newLeftBorderBBbox.left -
+ (originalLeftBorderBBox.right - originalLeftBorderBBox.left);
const heightRatio =
- newLeftBorderBbox.bottom -
- newLeftBorderBbox.top -
- (originalLeftBorderBbox.bottom - originalLeftBorderBbox.top);
+ newLeftBorderBBbox.bottom -
+ newLeftBorderBBbox.top -
+ (originalLeftBorderBBox.bottom - originalLeftBorderBBox.top);
// g绘制时,会将坐标1变成0.5,来达到真正绘制1px的效果,因此宽高不一定完全相同,会有1px的差值
expect(widthRatio).toBeLessThanOrEqual(1);
diff --git a/packages/s2-core/__tests__/bugs/issue-1587-spec.ts b/packages/s2-core/__tests__/bugs/issue-1587-spec.ts
index bb5ff56da7..c39d5c3903 100644
--- a/packages/s2-core/__tests__/bugs/issue-1587-spec.ts
+++ b/packages/s2-core/__tests__/bugs/issue-1587-spec.ts
@@ -11,9 +11,8 @@ import { PivotSheet } from '@/sheet-type';
const s2Options: S2Options = {
width: 800,
height: 600,
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-expect-error
pagination: {
+ current: 1,
pageSize: 2,
},
};
diff --git a/packages/s2-core/__tests__/bugs/issue-1624-spec.ts b/packages/s2-core/__tests__/bugs/issue-1624-spec.ts
new file mode 100644
index 0000000000..9ce404a029
--- /dev/null
+++ b/packages/s2-core/__tests__/bugs/issue-1624-spec.ts
@@ -0,0 +1,51 @@
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+/**
+ * @description spec for issue #1624
+ * https://github.com/antvis/S2/issues/1624
+ */
+
+import * as mockDataConfig from '../data/simple-data.json';
+import { getContainer, sleep } from '../util/helpers';
+import { S2Event, type S2Options } from '@/index';
+import { PivotSheet } from '@/sheet-type';
+
+const s2Options: S2Options = {
+ width: 800,
+ height: 600,
+ hdAdapter: false,
+};
+
+describe('Data Cell Border Tests', () => {
+ const borderWidth = 4;
+
+ test('should draw correct data cell border when hover focus', async () => {
+ const s2 = new PivotSheet(getContainer(), mockDataConfig, s2Options);
+
+ s2.setTheme({
+ dataCell: {
+ cell: {
+ verticalBorderWidth: borderWidth,
+ horizontalBorderWidth: borderWidth,
+ },
+ },
+ });
+ await s2.render();
+
+ const dataCell = s2.facet.getDataCells()[0];
+
+ s2.emit(S2Event.DATA_CELL_HOVER, {
+ target: dataCell,
+ } as any);
+
+ await sleep(40);
+
+ const meta = dataCell.getBBoxByType();
+ const borderBBox = dataCell
+ .getStateShapes()
+ .get('interactiveBorderShape')!
+ .getBBox();
+
+ expect(meta.width).toBeGreaterThanOrEqual(borderBBox.width + borderWidth);
+ expect(meta.height).toBeGreaterThanOrEqual(borderBBox.height + borderWidth);
+ });
+});
diff --git a/packages/s2-core/__tests__/bugs/issue-1715-spec.ts b/packages/s2-core/__tests__/bugs/issue-1715-spec.ts
index 682d3f62d6..4eaf9d183b 100644
--- a/packages/s2-core/__tests__/bugs/issue-1715-spec.ts
+++ b/packages/s2-core/__tests__/bugs/issue-1715-spec.ts
@@ -4,6 +4,7 @@
* https://github.com/antvis/S2/issues/1715
* https://github.com/antvis/S2/issues/2049
*/
+
import { getContainer } from '../util/helpers';
import * as mockDataConfig from '../data/mock-dataset.json';
import type { S2DataConfig, S2Options, SpreadSheet } from '../../src';
@@ -81,9 +82,10 @@ describe('Multi Values GrandTotal Height Test', () => {
const grandTotalsNode = s2.facet
.getColNodes()
- .find((node) => node.isGrandTotals)!;
+ .find((node) => node.isGrandTotals && node.isTotalRoot);
- expect(s2.facet.getLayoutResult().colsHierarchy.height).toBe(60);
- expect(grandTotalsNode.height).toEqual(30);
+ // 有多个 Value 时不允许隐藏度量列
+ expect(s2.facet.getLayoutResult().colsHierarchy.height).toBe(90);
+ expect(grandTotalsNode!.height).toEqual(60);
});
});
diff --git a/packages/s2-core/__tests__/bugs/issue-1781-spec.ts b/packages/s2-core/__tests__/bugs/issue-1781-spec.ts
index 30dee7a17b..c8a357c5b3 100644
--- a/packages/s2-core/__tests__/bugs/issue-1781-spec.ts
+++ b/packages/s2-core/__tests__/bugs/issue-1781-spec.ts
@@ -4,12 +4,13 @@
* https://github.com/antvis/S2/issues/1781
*/
+import type { FederatedPointerEvent } from '@antv/g';
+import * as mockDataConfig from '../data/simple-table-data.json';
import {
createFederatedMouseEvent,
getContainer,
sleep,
} from '../util/helpers';
-import * as mockDataConfig from '../data/simple-table-data.json';
import {
OriginEventType,
S2Event,
@@ -46,27 +47,29 @@ describe('Hover Focus Tests', () => {
await sleep(3000);
// 浙江省份信息
- const provinceCell = s2.facet.panelScrollGroup.getChildByIndex(7);
+ const provinceCell = s2.facet.getDataCells()[7];
// 义乌城市信息
- const cityCell = s2.facet.panelScrollGroup.getChildByIndex(10);
+ const cityCell = s2.facet.getDataCells()[10];
const event = createFederatedMouseEvent(s2, OriginEventType.POINTER_MOVE);
event.target = provinceCell;
- // @ts-ignore
- s2.emit(S2Event.DATA_CELL_HOVER, event);
+ s2.emit(S2Event.DATA_CELL_HOVER, event as FederatedPointerEvent);
expect(
- // @ts-ignore
- provinceCell.stateShapes
+ provinceCell
+ .getStateShapes()
.get('interactiveBorderShape')
?.attr('visibility'),
).toEqual('visible');
+
expect(
- // @ts-ignore
- cityCell.stateShapes.get('interactiveBorderShape')?.attr('visibility'),
+ cityCell
+ .getStateShapes()
+ .get('interactiveBorderShape')
+ ?.attr('visibility'),
).toEqual('hidden');
});
});
diff --git a/packages/s2-core/__tests__/bugs/issue-2164-spec.ts b/packages/s2-core/__tests__/bugs/issue-2164-spec.ts
index 394da2dc35..a9dde4113f 100644
--- a/packages/s2-core/__tests__/bugs/issue-2164-spec.ts
+++ b/packages/s2-core/__tests__/bugs/issue-2164-spec.ts
@@ -6,14 +6,14 @@
import { getContainer } from '../util/helpers';
import * as mockDataConfig from '../data/simple-data.json';
-import type { S2Options } from '@/index';
+import { LayoutWidthType, type S2Options } from '@/index';
import { PivotSheet } from '@/sheet-type';
const s2Options: S2Options = {
width: 400,
height: 400,
style: {
- layoutWidthType: 'compact',
+ layoutWidthType: LayoutWidthType.Compact,
},
totals: {
row: {
@@ -32,7 +32,8 @@ describe('Grand Total Row Node Tests', () => {
...mockDataConfig,
fields: {
...mockDataConfig.fields,
- valueInCols: false, // 指标放行头
+ // 指标放行头
+ valueInCols: false,
},
},
s2Options,
diff --git a/packages/s2-core/__tests__/bugs/issue-2195-spec.ts b/packages/s2-core/__tests__/bugs/issue-2195-spec.ts
new file mode 100644
index 0000000000..ed8c1e1d7f
--- /dev/null
+++ b/packages/s2-core/__tests__/bugs/issue-2195-spec.ts
@@ -0,0 +1,74 @@
+/**
+ * 字段代码中有方括号,无法拖拽调整该字段所在列的宽度
+ * 描述应当调整为:字段代码中有方括号,无法使用 `xxxByField` 配置调整该字段的布局
+ * @description spec for issue #2195
+ * https://github.com/antvis/S2/issues/2195
+ */
+
+import { getContainer } from '../util/helpers';
+import type { S2DataConfig, S2Options } from '@/index';
+import { PivotSheet } from '@/sheet-type';
+
+const modifiedMockDataConfig: S2DataConfig = {
+ fields: {
+ rows: ['province', '[city]'],
+ columns: ['type'],
+ values: ['price', 'cost'],
+ valueInCols: true,
+ },
+ data: [
+ {
+ province: '浙江',
+ '[city]': '义乌',
+ type: '笔',
+ price: 1,
+ cost: 2,
+ },
+ {
+ province: '浙江',
+ '[city]': '义乌',
+ type: '笔',
+ price: 1,
+ cost: 2,
+ },
+ {
+ province: '浙江',
+ '[city]': '杭州',
+ type: '笔',
+ price: 1,
+ cost: 2,
+ },
+ ],
+};
+
+const s2Options: S2Options = {
+ width: 400,
+ height: 400,
+ style: {
+ rowCell: {
+ widthByField: {
+ province: 300,
+ '[city]': 123,
+ },
+ },
+ },
+};
+
+describe('Field surrounded by square brackets Tests', () => {
+ test('should render correctly when use field surrounded by square brackets', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ modifiedMockDataConfig,
+ s2Options,
+ );
+
+ await s2.render();
+
+ s2.facet
+ .getLayoutResult()
+ .rowNodes.filter((node) => node.field === '[city]')
+ .forEach((node) => {
+ expect(node.width).toEqual(123);
+ });
+ });
+});
diff --git a/packages/s2-core/__tests__/bugs/issue-2199-spec.ts b/packages/s2-core/__tests__/bugs/issue-2199-spec.ts
new file mode 100644
index 0000000000..fa82bb1813
--- /dev/null
+++ b/packages/s2-core/__tests__/bugs/issue-2199-spec.ts
@@ -0,0 +1,41 @@
+/**
+ * @description spec for issue #2199
+ * https://github.com/antvis/S2/issues/2199
+ * 明细表: 当有冻结列 + 列分组的情况下, 会出现列头文本不居中现象
+ */
+import { getContainer } from 'tests/util/helpers';
+import dataCfg from '../data/data-issue-2199.json';
+import { TableSheet } from '@/sheet-type';
+import type { S2Options } from '@/common/interface';
+
+const s2Options: S2Options = {
+ width: 300,
+ height: 480,
+ showSeriesNumber: true,
+ frozen: {
+ colCount: 1,
+ },
+};
+
+describe('ColCell Text Center Tests', () => {
+ test('should draw text centered in cell', async () => {
+ const s2 = new TableSheet(getContainer(), dataCfg, s2Options);
+
+ await s2.render();
+
+ s2.facet.updateScrollOffset({
+ offsetX: {
+ value: 500,
+ animate: false,
+ },
+ });
+
+ const node = s2.facet.getColNodes(0).slice(-1)?.[0];
+ const cell = node?.belongsCell;
+ const { width: nodeWidth, x: nodeX } = node;
+ const { width: textWidth, x: textXActual } = cell!.getBBoxByType();
+ const textXCalc = nodeX + (nodeWidth - textWidth) / 2;
+
+ expect(textXCalc).toBeCloseTo(textXActual);
+ });
+});
diff --git a/packages/s2-core/__tests__/bugs/issue-2322-spec.ts b/packages/s2-core/__tests__/bugs/issue-2322-spec.ts
new file mode 100644
index 0000000000..3b5a8874dd
--- /dev/null
+++ b/packages/s2-core/__tests__/bugs/issue-2322-spec.ts
@@ -0,0 +1,50 @@
+/**
+ * @description spec for issue #2322
+ * https://github.com/antvis/S2/issues/2322
+ * 明细表: 多列筛选后清空其中一列筛选,导致其他筛选也清空
+ */
+import { getContainer, sleep } from 'tests/util/helpers';
+import dataCfg from '../data/data-issue-2322.json';
+import { S2Event } from '@/common';
+import type { S2Options } from '@/common/interface';
+import { TableSheet } from '@/sheet-type';
+
+const s2Options: S2Options = {
+ width: 800,
+ height: 480,
+ showSeriesNumber: true,
+ frozen: {
+ colCount: 1,
+ },
+};
+
+describe('Table Sheet Filter Test', () => {
+ test('should filter correctly when part of the filter is cleaned', async () => {
+ const s2 = new TableSheet(getContainer(), dataCfg, s2Options);
+
+ await s2.render();
+
+ // 为两个不同的列设定过滤
+ s2.emit(S2Event.RANGE_FILTER, {
+ filterKey: 'province',
+ filteredValues: ['吉林'],
+ });
+ s2.emit(S2Event.RANGE_FILTER, {
+ filterKey: 'city',
+ filteredValues: ['杭州'],
+ });
+
+ // 删除一列过滤
+ s2.emit(S2Event.RANGE_FILTER, {
+ filterKey: 'province',
+ filteredValues: [],
+ });
+
+ await sleep(200);
+
+ // 应过滤掉 city = 杭州 的值,共4行
+ expect(s2.dataSet.getDisplayDataSet()).toHaveLength(
+ s2.dataSet.originData.length - 4,
+ );
+ });
+});
diff --git a/packages/s2-core/__tests__/bugs/issue-2340-spec.ts b/packages/s2-core/__tests__/bugs/issue-2340-spec.ts
new file mode 100644
index 0000000000..33f194d379
--- /dev/null
+++ b/packages/s2-core/__tests__/bugs/issue-2340-spec.ts
@@ -0,0 +1,80 @@
+/**
+ * @description spec for issue #2340
+ * https://github.com/antvis/S2/issues/2340
+ */
+import {
+ CellType,
+ InteractionStateName,
+ getCellMeta,
+ type S2CellType,
+ type S2Options,
+} from '../../src';
+import { createPivotSheet, sleep } from '../util/helpers';
+
+const s2Options: S2Options = {
+ width: 800,
+ height: 600,
+ style: {
+ dataCell: {
+ width: 200,
+ height: 200,
+ },
+ },
+};
+
+describe('Header Brush Selection Tests', () => {
+ test.each([CellType.COL_CELL, CellType.ROW_CELL])(
+ 'should not trigger data cell selected when header selected and scroll out of viewport',
+ async (cellType) => {
+ const s2 = createPivotSheet(s2Options, { useSimpleData: false });
+
+ await s2.render();
+
+ const isRow = cellType === CellType.ROW_CELL;
+ const targetCells = isRow
+ ? s2.facet.getRowCells()
+ : s2.facet.getColCells();
+
+ const cells = [
+ targetCells.find((cell) => {
+ const meta = cell.getMeta();
+
+ return meta.isLeaf;
+ }),
+ ] as S2CellType[];
+
+ s2.interaction.changeState({
+ cells: cells.map(getCellMeta),
+ stateName: InteractionStateName.BRUSH_SELECTED,
+ });
+
+ await sleep(500);
+
+ const offsetKey = isRow ? 'offsetY' : 'offsetX';
+
+ // 将圈选的单元格滑出可视范围
+ s2.facet.updateScrollOffset({
+ [offsetKey]: { value: 300 },
+ });
+
+ await sleep(500);
+
+ // 还原
+ s2.facet.updateScrollOffset({
+ [offsetKey]: { value: 0 },
+ });
+
+ expect(s2.interaction.getActiveCells()).toHaveLength(1);
+ expect(s2.interaction.getCurrentStateName()).toEqual(
+ InteractionStateName.BRUSH_SELECTED,
+ );
+
+ // 交互过的不应该有 dataCell (未触发过列头多选)
+ s2.interaction.getInteractedCells().forEach((cell) => {
+ expect(cell.cellType).toEqual(
+ isRow ? CellType.ROW_CELL : CellType.COL_CELL,
+ );
+ });
+ },
+ );
+});
diff --git a/packages/s2-core/__tests__/bugs/issue-2359-spec.ts b/packages/s2-core/__tests__/bugs/issue-2359-spec.ts
new file mode 100644
index 0000000000..2d4ad61d5e
--- /dev/null
+++ b/packages/s2-core/__tests__/bugs/issue-2359-spec.ts
@@ -0,0 +1,66 @@
+/**
+ * @description spec for issue #2359
+ * https://github.com/antvis/S2/issues/2359
+ * 明细表: 自定义列头误用 dataCell 样式
+ */
+import { pick } from 'lodash';
+import { createTableSheet } from 'tests/util/helpers';
+import { TableColCell, drawObjectText } from '../../src';
+import type { S2CellType, S2Options } from '@/common/interface';
+
+class TestColCell extends TableColCell {
+ drawTextShape() {
+ drawObjectText(this, {
+ values: [['A', 'B', 'C']],
+ });
+ }
+}
+
+const s2Options: S2Options = {
+ width: 300,
+ height: 480,
+ showSeriesNumber: true,
+ colCell: (...args) => new TestColCell(...args),
+};
+
+describe('Table Sheet Custom Multiple Values Tests', () => {
+ test('should use current cell text theme', async () => {
+ const s2 = createTableSheet(s2Options);
+
+ s2.setTheme({
+ colCell: {
+ measureText: {
+ fontSize: 12,
+ },
+ bolderText: {
+ fontSize: 14,
+ },
+ text: {
+ fontSize: 20,
+ fill: 'red',
+ },
+ },
+ dataCell: {
+ text: {
+ fontSize: 30,
+ fill: 'green',
+ },
+ },
+ });
+ await s2.render();
+
+ const mapTheme = (cell: S2CellType) => {
+ return cell
+ .getTextShapes()
+ .map((shape) => pick(shape.attributes, ['fill', 'fontSize']));
+ };
+
+ const colCellTexts = s2.facet.getColCells().map(mapTheme);
+
+ const dataCellTexts = s2.facet.getDataCells().map(mapTheme);
+
+ expect(colCellTexts).toMatchSnapshot();
+
+ expect(dataCellTexts).toMatchSnapshot();
+ });
+});
diff --git a/packages/s2-core/__tests__/bugs/issue-2385-spec.ts b/packages/s2-core/__tests__/bugs/issue-2385-spec.ts
new file mode 100644
index 0000000000..592524fa35
--- /dev/null
+++ b/packages/s2-core/__tests__/bugs/issue-2385-spec.ts
@@ -0,0 +1,62 @@
+/**
+ * @description spec for issue #2385
+ * https://github.com/antvis/S2/issues/2385
+ */
+import { LayoutWidthType, type S2Options } from '../../src';
+import * as mockDataConfig from '../data/data-issue-2385.json';
+import { getContainer } from '../util/helpers';
+import { PivotSheet, TableSheet } from '@/sheet-type';
+
+const s2Options: S2Options = {
+ width: 800,
+ height: 600,
+ style: {
+ dataCell: {
+ width: 200,
+ },
+ layoutWidthType: LayoutWidthType.Compact,
+ },
+};
+
+describe('Compare Layout Tests', () => {
+ test('should get max col width for pivot sheet', async () => {
+ const s2 = new PivotSheet(getContainer(), mockDataConfig, s2Options);
+
+ s2.setTheme({
+ dataCell: {
+ text: {
+ fontSize: 20,
+ },
+ },
+ });
+ await s2.render();
+
+ const colLeafNodes = s2.facet.getColLeafNodes();
+
+ expect(Math.floor(colLeafNodes[0].width)).toBeCloseTo(189);
+ expect(Math.floor(colLeafNodes[1].width)).toEqual(90);
+ });
+
+ test('should get max col width for table sheet', async () => {
+ const s2 = new TableSheet(getContainer(), mockDataConfig, s2Options);
+
+ s2.setDataCfg({
+ fields: {
+ columns: ['price'],
+ },
+ });
+ s2.setTheme({
+ dataCell: {
+ text: {
+ fontSize: 20,
+ },
+ },
+ });
+
+ await s2.render();
+
+ const colLeafNodes = s2.facet.getColLeafNodes();
+
+ expect(Math.floor(colLeafNodes[0].width)).toBeCloseTo(182);
+ });
+});
diff --git a/packages/s2-core/__tests__/bugs/issue-2501-spec.ts b/packages/s2-core/__tests__/bugs/issue-2501-spec.ts
new file mode 100644
index 0000000000..143c76f1ad
--- /dev/null
+++ b/packages/s2-core/__tests__/bugs/issue-2501-spec.ts
@@ -0,0 +1,63 @@
+/**
+ * @description spec for issue #2501
+ * https://github.com/antvis/S2/issues/2501
+ */
+
+import type { TableFacet } from '../../src/facet';
+import * as mockDataConfig from '../data/simple-table-data.json';
+import { getContainer } from '../util/helpers';
+import type { SpreadSheet, S2DataConfig, S2Options } from '@/index';
+import { TableSheet } from '@/sheet-type';
+
+const s2DataConfig: S2DataConfig = {
+ ...mockDataConfig,
+};
+
+const s2Options: S2Options = {
+ width: 800,
+ height: 400,
+ style: {
+ rowCell: {
+ heightByField: {
+ '0': 100,
+ '1': 150,
+ },
+ },
+ },
+};
+
+describe('Table Sheet Row Offsets Tests', () => {
+ let s2: SpreadSheet;
+
+ beforeEach(() => {
+ s2 = new TableSheet(getContainer(), s2DataConfig, s2Options);
+
+ s2.render();
+ });
+
+ test('should get correctly row offset data', () => {
+ expect((s2.facet as TableFacet).rowOffsets).toMatchInlineSnapshot(`
+ Array [
+ 0,
+ 100,
+ 250,
+ 280,
+ ]
+ `);
+ });
+
+ test('should get correctly data cell offset for heightByField', () => {
+ const { getCellOffsetY, getTotalHeight } = s2.facet.getViewCellHeights();
+
+ expect(getCellOffsetY(0)).toEqual(0);
+ expect(getCellOffsetY(1)).toEqual(100);
+ expect(getCellOffsetY(2)).toEqual(250);
+ expect(getTotalHeight()).toEqual(280);
+ });
+
+ test('should get correctly row layout for heightByField', () => {
+ const { getTotalLength } = s2.facet.getViewCellHeights();
+
+ expect(getTotalLength()).toEqual(3);
+ });
+});
diff --git a/packages/s2-core/__tests__/bugs/issue-446-spec.ts b/packages/s2-core/__tests__/bugs/issue-446-spec.ts
index 385d726105..5d8f283250 100644
--- a/packages/s2-core/__tests__/bugs/issue-446-spec.ts
+++ b/packages/s2-core/__tests__/bugs/issue-446-spec.ts
@@ -7,7 +7,7 @@
import { getContainer } from '../util/helpers';
import * as mockDataConfig from '../data/data-issue-446.json';
import { TableSheet } from '@/sheet-type';
-import { copyData } from '@/utils';
+import { asyncGetAllPlainData } from '@/utils';
const s2Options = {
width: 800,
@@ -20,7 +20,7 @@ describe('export', () => {
const s2 = new TableSheet(getContainer(), mockDataConfig, s2Options);
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: '\t',
formatOptions: true,
@@ -43,7 +43,7 @@ describe('export', () => {
});
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: '\t',
});
diff --git a/packages/s2-core/__tests__/bugs/issue-565-spec.ts b/packages/s2-core/__tests__/bugs/issue-565-spec.ts
index d86f5100eb..2705af69a9 100644
--- a/packages/s2-core/__tests__/bugs/issue-565-spec.ts
+++ b/packages/s2-core/__tests__/bugs/issue-565-spec.ts
@@ -6,13 +6,14 @@
*/
import * as mockDataConfig from 'tests/data/data-issue-565.json';
import { getContainer } from 'tests/util/helpers';
+import type { S2Options } from '../../src';
import { PivotSheet } from '@/sheet-type';
-import { copyData } from '@/utils';
+import { asyncGetAllPlainData } from '@/utils';
-const s2Options = {
+const s2Options: S2Options = {
width: 800,
height: 600,
- hierarchyType: 'tree' as const,
+ hierarchyType: 'tree',
};
describe('Export data in pivot tree mode', () => {
@@ -20,7 +21,8 @@ describe('Export data in pivot tree mode', () => {
const s2 = new PivotSheet(getContainer(), mockDataConfig, s2Options);
await s2.render();
- const data = copyData({
+
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: '\t',
});
@@ -32,16 +34,6 @@ describe('Export data in pivot tree mode', () => {
expect(rows[1].split('\t')[0]).toEqual('');
expect(rows[7].split('\t')[0]).toEqual('row0');
expect(rows[8].split('\t')[0]).toEqual('row0');
- expect(data).toMatchInlineSnapshot(`
- " col0 col0-0 col0-0
- col1 col1-0 col1-1
- col2 col2-0 col2-0
- row0 row1 row2 number number
- row0
- row0 row1-0
- row0 row1-0 row2-0 3
- row0 row1-1
- row0 row1-1 row2-0 2 4"
- `);
+ expect(data).toMatchSnapshot();
});
});
diff --git a/packages/s2-core/__tests__/bugs/issue-725-spec.ts b/packages/s2-core/__tests__/bugs/issue-725-spec.ts
index 6d222d4230..ad503c135b 100644
--- a/packages/s2-core/__tests__/bugs/issue-725-spec.ts
+++ b/packages/s2-core/__tests__/bugs/issue-725-spec.ts
@@ -3,15 +3,13 @@
* https://github.com/antvis/S2/issues/725
* Wrong multi measure render
* Wrong group sort
- *
*/
import * as mockDataConfig from 'tests/data/data-issue-725.json';
import { assembleDataCfg } from '../util';
import type { S2DataConfig } from '@/common/interface';
-import { PivotSheet } from '@/sheet-type';
import { PivotDataSet } from '@/data-set';
-import { getDimensionsWithoutPathPre } from '@/utils/dataset/pivot-data-set';
+import { PivotSheet } from '@/sheet-type';
jest.mock('@/sheet-type');
@@ -39,18 +37,17 @@ describe('Group Sort When Have Same Child Measure', () => {
});
test('should get correct group sort', () => {
- expect(
- getDimensionsWithoutPathPre(dataSet.getDimensionValues('type')),
- ).toEqual(['办公用品', '家具产品', '家具产品', '办公用品']);
- expect(
- getDimensionsWithoutPathPre(
- dataSet.getDimensionValues('type', { city: '白山' }),
- ),
- ).toEqual(['办公用品', '家具产品']);
- expect(
- getDimensionsWithoutPathPre(
- dataSet.getDimensionValues('type', { city: '抚顺' }),
- ),
- ).toEqual(['家具产品', '办公用品']);
+ expect(dataSet.getDimensionValues('type')).toEqual([
+ '办公用品',
+ '家具产品',
+ ]);
+ expect(dataSet.getDimensionValues('type', { city: '白山' })).toEqual([
+ '办公用品',
+ '家具产品',
+ ]);
+ expect(dataSet.getDimensionValues('type', { city: '抚顺' })).toEqual([
+ '家具产品',
+ '办公用品',
+ ]);
});
});
diff --git a/packages/s2-core/__tests__/data/data-custom-trees.ts b/packages/s2-core/__tests__/data/data-custom-trees.ts
new file mode 100644
index 0000000000..7e5a8832a2
--- /dev/null
+++ b/packages/s2-core/__tests__/data/data-custom-trees.ts
@@ -0,0 +1,22 @@
+export const dataCustomTrees = [
+ {
+ type: '家具',
+ sub_type: '桌子',
+ 'measure-a': 1,
+ 'measure-b': 2,
+ 'measure-c': 3,
+ 'measure-d': 4,
+ 'measure-e': 5,
+ 'measure-f': 6,
+ },
+ {
+ type: '家具',
+ sub_type: '椅子',
+ 'measure-a': 11,
+ 'measure-b': 22,
+ 'measure-c': 33,
+ 'measure-d': 44,
+ 'measure-e': 55,
+ 'measure-f': 66,
+ },
+];
diff --git a/packages/s2-core/__tests__/data/data-issue-2199.json b/packages/s2-core/__tests__/data/data-issue-2199.json
new file mode 100644
index 0000000000..bb93e0401f
--- /dev/null
+++ b/packages/s2-core/__tests__/data/data-issue-2199.json
@@ -0,0 +1,126 @@
+{
+ "fields": {
+ "columns": [
+ {
+ "field": "area",
+ "title": "位置",
+ "children": [
+ { "field": "province", "title": "省份" },
+ { "field": "city", "title": "城市" }
+ ]
+ },
+ {
+ "field": "type",
+ "title": "商品类别"
+ },
+ {
+ "field": "money",
+ "title": "金额",
+ "children": [
+ {
+ "field": "price",
+ "title": "价格"
+ }
+ ]
+ }
+ ]
+ },
+ "data": [
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "笔",
+ "price": 1
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "纸张",
+ "price": 2
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "笔",
+ "price": 17
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "纸张",
+ "price": 6
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "笔",
+ "price": 8
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "笔",
+ "price": 12
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "纸张",
+ "price": 3
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "纸张",
+ "price": 25
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "笔",
+ "price": 20
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "纸张",
+ "price": 10
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "笔",
+ "price": 15
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "纸张",
+ "price": 2
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "笔",
+ "price": 15
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "笔",
+ "price": 30
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "纸张",
+ "price": 40
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "纸张",
+ "price": 50
+ }
+ ]
+}
diff --git a/packages/s2-core/__tests__/data/data-issue-2322.json b/packages/s2-core/__tests__/data/data-issue-2322.json
new file mode 100644
index 0000000000..9dde6f3fc4
--- /dev/null
+++ b/packages/s2-core/__tests__/data/data-issue-2322.json
@@ -0,0 +1,132 @@
+{
+ "fields": {
+ "columns": [
+ {
+ "field": "area",
+ "title": "区域",
+ "children": [
+ {
+ "field": "province",
+ "title": "省份"
+ },
+ {
+ "field": "city",
+ "title": "城市"
+ }
+ ]
+ },
+ {
+ "field": "type",
+ "title": "商品类别"
+ },
+ {
+ "field": "money",
+ "title": "金额",
+ "children": [
+ {
+ "field": "price",
+ "title": "价格"
+ }
+ ]
+ }
+ ]
+ },
+ "data": [
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "笔",
+ "price": 1
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "纸张",
+ "price": 2
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "笔",
+ "price": 17
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "纸张",
+ "price": 6
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "笔",
+ "price": 8
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "笔",
+ "price": 12
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "纸张",
+ "price": 3
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "纸张",
+ "price": 25
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "笔",
+ "price": 20
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "纸张",
+ "price": 10
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "笔",
+ "price": 15
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "纸张",
+ "price": 2
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "笔",
+ "price": 15
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "笔",
+ "price": 30
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "纸张",
+ "price": 40
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "纸张",
+ "price": 50
+ }
+ ]
+}
diff --git a/packages/s2-core/__tests__/data/data-issue-2385.json b/packages/s2-core/__tests__/data/data-issue-2385.json
new file mode 100644
index 0000000000..d6f20caac5
--- /dev/null
+++ b/packages/s2-core/__tests__/data/data-issue-2385.json
@@ -0,0 +1,138 @@
+{
+ "data": [
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "笔",
+ "price": "11111111111111111",
+ "cost": "33.333"
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "纸张",
+ "price": "2",
+ "cost": "1.5"
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "笔",
+ "price": "2",
+ "cost": "1.5"
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "纸张",
+ "price": "666.333",
+ "cost": "0.2"
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "笔",
+ "price": "3",
+ "cost": "2"
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "纸张",
+ "price": "2",
+ "cost": "1"
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "笔",
+ "price": "4",
+ "cost": "3"
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "纸张",
+ "price": "1",
+ "cost": "33.333"
+ },
+ {
+ "price": "15.5",
+ "cost": "10.2"
+ },
+ {
+ "province": "浙江",
+ "price": "5.5",
+ "cost": "3.7"
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "price": "3",
+ "cost": "2"
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "price": "2.5",
+ "cost": "1.7"
+ },
+ {
+ "province": "吉林",
+ "price": "10",
+ "cost": "6.5"
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "price": "5",
+ "cost": "3"
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "price": "5",
+ "cost": "3.5"
+ },
+ {
+ "type": "笔",
+ "price": "10",
+ "cost": "7"
+ },
+ {
+ "type": "笔",
+ "province": "浙江",
+ "price": "3",
+ "cost": "2"
+ },
+ {
+ "type": "笔",
+ "province": "吉林",
+ "price": "7",
+ "cost": "5"
+ },
+ {
+ "type": "纸张",
+ "price": "5.5",
+ "cost": "3.2"
+ },
+ {
+ "type": "纸张",
+ "province": "浙江",
+ "price": "2.5",
+ "cost": "1.7"
+ },
+ {
+ "type": "纸张",
+ "province": "吉林",
+ "price": "3",
+ "cost": "1.5"
+ }
+ ],
+ "fields": {
+ "rows": ["province", "city"],
+ "columns": ["type"],
+ "values": ["price"],
+ "valueInCols": true
+ }
+}
diff --git a/packages/s2-core/__tests__/data/data-issue-292.json b/packages/s2-core/__tests__/data/data-issue-292.json
index 8a387e8391..98ccfbf083 100644
--- a/packages/s2-core/__tests__/data/data-issue-292.json
+++ b/packages/s2-core/__tests__/data/data-issue-292.json
@@ -10,12 +10,7 @@
"province": "浙江",
"city": "义乌",
"type": "笔",
- "cost": "2"
- },
- {
- "province": "浙江",
- "city": "义乌",
- "type": "笔",
+ "cost": "2",
"price": "8"
},
{
diff --git a/packages/s2-core/__tests__/data/data-issue-725.json b/packages/s2-core/__tests__/data/data-issue-725.json
index ad4d2a36dc..5510e53fd0 100644
--- a/packages/s2-core/__tests__/data/data-issue-725.json
+++ b/packages/s2-core/__tests__/data/data-issue-725.json
@@ -19,11 +19,6 @@
}
],
"data": [
- {
- "city": "白山",
- "type": "办公用品",
- "price": ""
- },
{
"city": "白山",
"type": "办公用品",
diff --git a/packages/s2-core/__tests__/data/sort-advanced.ts b/packages/s2-core/__tests__/data/sort-advanced.ts
index bd067d3b47..e6068afe62 100644
--- a/packages/s2-core/__tests__/data/sort-advanced.ts
+++ b/packages/s2-core/__tests__/data/sort-advanced.ts
@@ -183,4 +183,5 @@ export const sortData = {
price: '3',
},
],
+ totalData: [],
};
diff --git a/packages/s2-core/__tests__/data/total-group-data.ts b/packages/s2-core/__tests__/data/total-group-data.ts
new file mode 100644
index 0000000000..ec1c1a7e3c
--- /dev/null
+++ b/packages/s2-core/__tests__/data/total-group-data.ts
@@ -0,0 +1,201 @@
+import { Aggregation, type S2DataConfig, type S2Options } from '@/common';
+
+export const s2Options: S2Options = {
+ width: 800,
+ height: 600,
+ // 配置行小计总计显示,且按维度分组(列小计总计同理)
+ totals: {
+ row: {
+ showGrandTotals: true,
+ showSubTotals: true,
+ reverseGrandTotalsLayout: true,
+ reverseSubTotalsLayout: true,
+ subTotalsDimensions: ['province'],
+ calcGrandTotals: {
+ aggregation: Aggregation.SUM,
+ },
+ calcSubTotals: {
+ aggregation: Aggregation.SUM,
+ },
+ grandTotalsGroupDimensions: ['type'],
+ subTotalsGroupDimensions: ['type'],
+ },
+ col: {
+ showGrandTotals: true,
+ showSubTotals: true,
+ reverseGrandTotalsLayout: true,
+ reverseSubTotalsLayout: true,
+ calcGrandTotals: {
+ aggregation: Aggregation.SUM,
+ },
+ calcSubTotals: {
+ aggregation: Aggregation.SUM,
+ },
+ grandTotalsGroupDimensions: ['sub_type'],
+ },
+ },
+};
+
+export const dataCfg: S2DataConfig = {
+ fields: {
+ rows: ['province', 'city', 'type'],
+ columns: ['sub_type'],
+ values: ['price', 'cost'],
+ },
+ meta: [
+ {
+ field: 'province',
+ name: '省份',
+ },
+ {
+ field: 'city',
+ name: '城市',
+ },
+ {
+ field: 'type',
+ name: '商品类别',
+ },
+ {
+ field: 'sub_type',
+ name: '商品子类别',
+ },
+ {
+ field: 'price',
+ name: '价格',
+ },
+ {
+ field: 'cost',
+ name: '成本',
+ },
+ ],
+ data: [
+ {
+ price: 100,
+ cost: 100,
+ province: '浙江省',
+ city: '杭州市',
+ type: '家具',
+ sub_type: '桌子',
+ },
+ {
+ price: 100,
+ cost: 100,
+ province: '浙江省',
+ city: '杭州市',
+ type: '家具',
+ sub_type: '沙发',
+ },
+ {
+ price: 100,
+ cost: 100,
+ province: '浙江省',
+ city: '杭州市',
+ type: '办公用品',
+ sub_type: '笔',
+ },
+
+ {
+ price: 200,
+ cost: 200,
+ province: '浙江省',
+ city: '舟山市',
+ type: '家具',
+ sub_type: '桌子',
+ },
+
+ {
+ price: 200,
+ cost: 200,
+ province: '浙江省',
+ city: '舟山市',
+ type: '家具',
+ sub_type: '沙发',
+ },
+
+ {
+ price: 200,
+ cost: 200,
+ province: '浙江省',
+ city: '舟山市',
+ type: '办公用品',
+ sub_type: '笔',
+ },
+
+ {
+ price: 200,
+ cost: 200,
+ province: '浙江省',
+ city: '舟山市',
+ type: '办公用品',
+ sub_type: '纸张',
+ },
+ {
+ price: 300,
+ cost: 300,
+ province: '四川省',
+ city: '成都市',
+ type: '家具',
+ sub_type: '桌子',
+ },
+ {
+ price: 400,
+ cost: 400,
+ province: '四川省',
+ city: '绵阳市',
+ type: '家具',
+ sub_type: '桌子',
+ },
+
+ {
+ price: 300,
+ cost: 300,
+ province: '四川省',
+ city: '成都市',
+ type: '家具',
+ sub_type: '沙发',
+ },
+ {
+ price: 400,
+ cost: 400,
+ province: '四川省',
+ city: '绵阳市',
+ type: '家具',
+ sub_type: '沙发',
+ },
+
+ {
+ price: 300,
+ cost: 300,
+ province: '四川省',
+ city: '成都市',
+ type: '办公用品',
+ sub_type: '笔',
+ },
+ {
+ price: 400,
+ cost: 400,
+ province: '四川省',
+ city: '绵阳市',
+ type: '办公用品',
+ sub_type: '笔',
+ },
+
+ {
+ price: 300,
+ cost: 300,
+ province: '四川省',
+ city: '成都市',
+ type: '办公用品',
+ sub_type: '纸张',
+ },
+ {
+ price: 400,
+ cost: 400,
+ province: '四川省',
+ city: '绵阳市',
+ type: '办公用品',
+ sub_type: '纸张',
+ },
+ ],
+ totalData: [],
+};
diff --git a/packages/s2-core/__tests__/spreadsheet/__snapshots__/corner-spec.ts.snap b/packages/s2-core/__tests__/spreadsheet/__snapshots__/corner-spec.ts.snap
index e906a49ea1..8bb717bbfc 100644
--- a/packages/s2-core/__tests__/spreadsheet/__snapshots__/corner-spec.ts.snap
+++ b/packages/s2-core/__tests__/spreadsheet/__snapshots__/corner-spec.ts.snap
@@ -11,7 +11,7 @@ Array [
"field": "province",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "province",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -19,6 +19,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -28,7 +29,7 @@ Array [
"seriesNumberWidth": undefined,
"spreadsheet": Anything,
"value": "province",
- "width": 99,
+ "width": 99.33,
"x": 0,
"y": 0,
},
@@ -41,7 +42,7 @@ Array [
"field": "city",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "city",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -49,6 +50,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -58,8 +60,8 @@ Array [
"seriesNumberWidth": undefined,
"spreadsheet": Anything,
"value": "city",
- "width": 99,
- "x": 99,
+ "width": 99.33,
+ "x": 99.33,
"y": 0,
},
]
@@ -84,6 +86,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -106,7 +109,7 @@ Array [
"field": "province",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "province",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -114,6 +117,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -136,7 +140,7 @@ Array [
"field": "city",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "city",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -144,6 +148,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -171,7 +176,7 @@ Array [
"field": "",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "province/city/数值",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -179,6 +184,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -188,7 +194,7 @@ Array [
"seriesNumberWidth": 0,
"spreadsheet": Anything,
"value": "province/city/数值",
- "width": 145,
+ "width": 145.36,
"x": 0,
"y": 0,
},
@@ -214,6 +220,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -236,7 +243,7 @@ Array [
"field": "",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "province/city/数值",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -244,6 +251,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -253,7 +261,7 @@ Array [
"seriesNumberWidth": 80,
"spreadsheet": Anything,
"value": "province/city/数值",
- "width": 145,
+ "width": 145.36,
"x": 80,
"y": 0,
},
@@ -271,7 +279,7 @@ Array [
"field": "province",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "province",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -279,6 +287,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -301,7 +310,7 @@ Array [
"field": "city",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "city",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -309,6 +318,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -344,6 +354,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -366,7 +377,7 @@ Array [
"field": "province",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "province",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -374,6 +385,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -396,7 +408,7 @@ Array [
"field": "city",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "city",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -404,6 +416,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -431,7 +444,7 @@ Array [
"field": "",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "province/city",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -439,6 +452,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -474,6 +488,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -496,7 +511,7 @@ Array [
"field": "",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "province/city",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -504,6 +519,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -531,7 +547,7 @@ Array [
"field": "province",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "province",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -539,6 +555,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -548,7 +565,7 @@ Array [
"seriesNumberWidth": undefined,
"spreadsheet": Anything,
"value": "province",
- "width": 99,
+ "width": 99.33,
"x": 0,
"y": 0,
},
@@ -561,7 +578,7 @@ Array [
"field": "city",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "city",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -569,6 +586,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -578,8 +596,8 @@ Array [
"seriesNumberWidth": undefined,
"spreadsheet": Anything,
"value": "city",
- "width": 99,
- "x": 99,
+ "width": 99.33,
+ "x": 99.33,
"y": 0,
},
]
@@ -604,6 +622,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -626,7 +645,7 @@ Array [
"field": "province",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "province",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -634,6 +653,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -656,7 +676,7 @@ Array [
"field": "city",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "city",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -664,6 +684,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -691,7 +712,7 @@ Array [
"field": "",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "province/city",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -699,6 +720,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -734,6 +756,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
@@ -756,7 +779,7 @@ Array [
"field": "",
"height": 30,
"hierarchy": undefined,
- "id": "",
+ "id": "province/city",
"inCollapseNode": undefined,
"isCollapsed": undefined,
"isGrandTotals": undefined,
@@ -764,6 +787,7 @@ Array [
"isPivotMode": true,
"isSubTotals": undefined,
"isTotalMeasure": undefined,
+ "isTotalRoot": undefined,
"isTotals": undefined,
"level": undefined,
"padding": 0,
diff --git a/packages/s2-core/__tests__/spreadsheet/__snapshots__/custom-cell-style-spec.ts.snap b/packages/s2-core/__tests__/spreadsheet/__snapshots__/custom-cell-style-spec.ts.snap
index 2baf34699e..14478ee83c 100644
--- a/packages/s2-core/__tests__/spreadsheet/__snapshots__/custom-cell-style-spec.ts.snap
+++ b/packages/s2-core/__tests__/spreadsheet/__snapshots__/custom-cell-style-spec.ts.snap
@@ -45,17 +45,17 @@ Array [
Object {
"height": 30,
"id": "root[&]笔",
- "width": 300,
+ "width": 299,
},
Object {
"height": 30,
"id": "root[&]笔[&]price",
- "width": 150,
+ "width": 149.5,
},
Object {
"height": 30,
"id": "root[&]笔[&]cost",
- "width": 150,
+ "width": 149.5,
},
]
`;
@@ -65,17 +65,17 @@ Array [
Object {
"height": 60,
"id": "root[&]浙江",
- "width": 149,
+ "width": 149.5,
},
Object {
"height": 30,
"id": "root[&]浙江[&]义乌",
- "width": 149,
+ "width": 149.5,
},
Object {
"height": 30,
"id": "root[&]浙江[&]杭州",
- "width": 149,
+ "width": 149.5,
},
]
`;
@@ -140,7 +140,7 @@ Array [
Object {
"height": 66,
"id": "root[&]浙江",
- "width": 149,
+ "width": 149.5,
},
Object {
"height": 33,
@@ -160,17 +160,17 @@ Array [
Object {
"height": 330,
"id": "root[&]浙江",
- "width": 149,
+ "width": 149.5,
},
Object {
"height": 30,
"id": "root[&]浙江[&]义乌",
- "width": 149,
+ "width": 149.5,
},
Object {
"height": 300,
"id": "root[&]浙江[&]杭州",
- "width": 149,
+ "width": 149.5,
},
]
`;
@@ -180,17 +180,17 @@ Array [
Object {
"height": 60,
"id": "root[&]浙江",
- "width": 149,
+ "width": 149.5,
},
Object {
"height": 30,
"id": "root[&]浙江[&]义乌",
- "width": 149,
+ "width": 149.5,
},
Object {
"height": 30,
"id": "root[&]浙江[&]杭州",
- "width": 149,
+ "width": 149.5,
},
]
`;
@@ -200,17 +200,17 @@ Array [
Object {
"height": 30,
"id": "root[&]笔",
- "width": 300,
+ "width": 299,
},
Object {
"height": 30,
"id": "root[&]笔[&]price",
- "width": 150,
+ "width": 149.5,
},
Object {
"height": 30,
"id": "root[&]笔[&]cost",
- "width": 150,
+ "width": 149.5,
},
]
`;
@@ -220,22 +220,22 @@ Array [
Object {
"height": 30,
"id": "root[&]浙江[&]义乌-root[&]笔[&]price",
- "width": 150,
+ "width": 149.5,
},
Object {
"height": 30,
"id": "root[&]浙江[&]杭州-root[&]笔[&]price",
- "width": 150,
+ "width": 149.5,
},
Object {
"height": 30,
"id": "root[&]浙江[&]义乌-root[&]笔[&]cost",
- "width": 150,
+ "width": 149.5,
},
Object {
"height": 30,
"id": "root[&]浙江[&]杭州-root[&]笔[&]cost",
- "width": 150,
+ "width": 149.5,
},
]
`;
@@ -247,12 +247,12 @@ Array [
Object {
"height": 30,
"id": "root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
]
`;
@@ -262,132 +262,132 @@ Array [
Object {
"height": 30,
"id": "0-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "1-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "2-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "3-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "4-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "5-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "6-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "7-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "8-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "9-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "10-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "11-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "12-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "0-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "1-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "2-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "3-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "4-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "5-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "6-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "7-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "8-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "9-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "10-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "11-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "12-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
]
`;
@@ -427,7 +427,7 @@ Array [
Object {
"height": 60,
"id": "root[&]类型",
- "width": 119,
+ "width": 119.8,
},
Object {
"height": 30,
@@ -482,72 +482,72 @@ Array [
Object {
"height": 60,
"id": "0-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "1-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "2-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "3-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "4-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "5-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "6-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "0-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "1-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "2-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "3-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "4-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "5-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 60,
"id": "6-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
]
`;
@@ -557,102 +557,102 @@ Array [
Object {
"height": 40,
"id": "0-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "1-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 100,
"id": "2-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "3-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "4-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "5-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "6-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "7-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "8-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "9-root[&]类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 40,
"id": "0-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "1-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 100,
"id": "2-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "3-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "4-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "5-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "6-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "7-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "8-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
Object {
"height": 30,
"id": "9-root[&]子类别",
- "width": 299,
+ "width": 299.5,
},
]
`;
diff --git a/packages/s2-core/__tests__/spreadsheet/__snapshots__/custom-grid-spec.ts.snap b/packages/s2-core/__tests__/spreadsheet/__snapshots__/custom-grid-spec.ts.snap
index 4e93984e3d..63872b5a1c 100644
--- a/packages/s2-core/__tests__/spreadsheet/__snapshots__/custom-grid-spec.ts.snap
+++ b/packages/s2-core/__tests__/spreadsheet/__snapshots__/custom-grid-spec.ts.snap
@@ -253,7 +253,7 @@ Array [
"field": "a-1",
"height": 30,
"value": "自定义节点 a-1",
- "width": 300,
+ "width": 299.01,
"x": 0,
"y": 0,
},
@@ -262,7 +262,7 @@ Array [
"field": "a-1-1",
"height": 30,
"value": "自定义节点 a-1-1",
- "width": 200,
+ "width": 199.34,
"x": 0,
"y": 30,
},
@@ -271,7 +271,7 @@ Array [
"field": "measure-1",
"height": 30,
"value": "指标1",
- "width": 100,
+ "width": 99.67,
"x": 0,
"y": 60,
},
@@ -280,8 +280,8 @@ Array [
"field": "measure-2",
"height": 30,
"value": "指标2",
- "width": 100,
- "x": 100,
+ "width": 99.67,
+ "x": 99.67,
"y": 60,
},
Object {
@@ -289,8 +289,8 @@ Array [
"field": "a-1-2",
"height": 60,
"value": "自定义节点 a-1-2",
- "width": 100,
- "x": 200,
+ "width": 99.67,
+ "x": 199.34,
"y": 30,
},
Object {
@@ -298,8 +298,8 @@ Array [
"field": "a-2",
"height": 90,
"value": "自定义节点 a-2",
- "width": 100,
- "x": 300,
+ "width": 99.67,
+ "x": 299.01,
"y": 0,
},
]
@@ -309,19 +309,19 @@ exports[`SpreadSheet Custom Grid Tests Custom Row Grid Tests should calc correct
Array [
Object {
"field": "measure-1",
- "width": 119,
+ "width": 119.6,
},
Object {
"field": "measure-2",
- "width": 119,
+ "width": 119.6,
},
Object {
"field": "a-1-2",
- "width": 159,
+ "width": 159.6,
},
Object {
"field": "a-2",
- "width": 278,
+ "width": 279.2,
},
]
`;
@@ -330,11 +330,11 @@ exports[`SpreadSheet Custom Grid Tests Custom Row Grid Tests should calc correct
Array [
Object {
"field": "sub_type",
- "width": 160,
+ "width": 159.4,
},
Object {
"field": "sub_type",
- "width": 160,
+ "width": 159.4,
},
]
`;
@@ -435,37 +435,37 @@ Array [
"description": "a-1 描述",
"height": 90,
"value": "自定义节点 a-1",
- "width": 119,
+ "width": 119.6,
},
Object {
"description": "a-1-1 描述",
"height": 60,
"value": "自定义节点 a-1-1",
- "width": 119,
+ "width": 119.6,
},
Object {
"description": "指标1描述",
"height": 30,
"value": "指标1",
- "width": 119,
+ "width": 119.6,
},
Object {
"description": "指标2描述",
"height": 30,
"value": "指标2",
- "width": 119,
+ "width": 119.6,
},
Object {
"description": "a-1-2 描述",
"height": 30,
"value": "自定义节点 a-1-2",
- "width": 238,
+ "width": 239.2,
},
Object {
"description": "a-2 描述",
"height": 30,
"value": "自定义节点 a-2",
- "width": 357,
+ "width": 358.79999999999995,
},
]
`;
diff --git a/packages/s2-core/__tests__/spreadsheet/__snapshots__/custom-table-col-spec.ts.snap b/packages/s2-core/__tests__/spreadsheet/__snapshots__/custom-table-col-spec.ts.snap
index e607dd4387..e7310e8255 100644
--- a/packages/s2-core/__tests__/spreadsheet/__snapshots__/custom-table-col-spec.ts.snap
+++ b/packages/s2-core/__tests__/spreadsheet/__snapshots__/custom-table-col-spec.ts.snap
@@ -169,43 +169,43 @@ Array [
"description": undefined,
"height": 30,
"value": "地区",
- "width": 238,
+ "width": 239.6,
},
Object {
"description": undefined,
"height": 30,
"value": "省份",
- "width": 119,
+ "width": 119.8,
},
Object {
"description": undefined,
"height": 30,
"value": "城市",
- "width": 119,
+ "width": 119.8,
},
Object {
"description": undefined,
"height": 60,
"value": "类型",
- "width": 119,
+ "width": 119.8,
},
Object {
"description": undefined,
"height": 30,
"value": "金额",
- "width": 238,
+ "width": 239.6,
},
Object {
"description": "价格描述",
"height": 30,
"value": "价格",
- "width": 119,
+ "width": 119.8,
},
Object {
"description": undefined,
"height": 30,
"value": "数量",
- "width": 119,
+ "width": 119.8,
},
]
`;
@@ -216,37 +216,37 @@ Array [
"description": "a-1 描述",
"height": 30,
"value": "自定义节点 a-1",
- "width": 447,
+ "width": 449.25,
},
Object {
"description": "a-1-1 描述",
"height": 30,
"value": "自定义节点 a-1-1",
- "width": 298,
+ "width": 299.5,
},
Object {
"description": "指标1描述",
"height": 30,
"value": "指标1",
- "width": 149,
+ "width": 149.75,
},
Object {
"description": "指标2描述",
"height": 30,
"value": "指标2",
- "width": 149,
+ "width": 149.75,
},
Object {
"description": "a-1-2 描述",
"height": 60,
"value": "自定义节点 a-1-2",
- "width": 149,
+ "width": 149.75,
},
Object {
"description": "a-2 描述",
"height": 90,
"value": "自定义节点 a-2",
- "width": 149,
+ "width": 149.75,
},
]
`;
diff --git a/packages/s2-core/__tests__/spreadsheet/__snapshots__/hidden-columns-spec.ts.snap b/packages/s2-core/__tests__/spreadsheet/__snapshots__/hidden-columns-spec.ts.snap
new file mode 100644
index 0000000000..90c2f63ff0
--- /dev/null
+++ b/packages/s2-core/__tests__/spreadsheet/__snapshots__/hidden-columns-spec.ts.snap
@@ -0,0 +1,30 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`SpreadSheet Hidden Columns Tests PivotSheet Multiple Values Tests should render correct row corner after hide measure node 1`] = `
+Array [
+ Object {
+ "height": 30,
+ "width": 119.6,
+ "x": 0,
+ "y": 60,
+ },
+ Object {
+ "height": 30,
+ "width": 119.6,
+ "x": 119.6,
+ "y": 60,
+ },
+ Object {
+ "height": 30,
+ "width": 239.2,
+ "x": 0,
+ "y": 0,
+ },
+ Object {
+ "height": 30,
+ "width": 239.2,
+ "x": 0,
+ "y": 30,
+ },
+]
+`;
diff --git a/packages/s2-core/__tests__/spreadsheet/__snapshots__/multi-line-text-spec.ts.snap b/packages/s2-core/__tests__/spreadsheet/__snapshots__/multi-line-text-spec.ts.snap
index 5b04f4dac4..f9206280f8 100644
--- a/packages/s2-core/__tests__/spreadsheet/__snapshots__/multi-line-text-spec.ts.snap
+++ b/packages/s2-core/__tests__/spreadsheet/__snapshots__/multi-line-text-spec.ts.snap
@@ -2428,12 +2428,12 @@ Array [
"width": 96,
},
Object {
- "actualText": "城我是省略号",
+ "actualText": "城市城@@@",
"actualTextHeight": 16,
- "actualTextWidth": 73,
+ "actualTextWidth": 72,
"height": 30,
"multiLineActualTexts": Array [
- "城我是省略号",
+ "城市城@@@",
],
"originalText": "城市城市城市城市城市城市城市城市城市城市城市城市",
"width": 96,
@@ -2977,7 +2977,7 @@ Array [
"省份",
],
"originalText": "省份",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "城市城市城市城市城市城市城市城市城市城市...",
@@ -2990,7 +2990,7 @@ Array [
"城市城市城市...",
],
"originalText": "城市城市城市城市城市城市城市城市城市城市城市城市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "类别类别类别类别类别类别类别类别类别类别",
@@ -3003,7 +3003,7 @@ Array [
"类别类别类别",
],
"originalText": "类别类别类别类别类别类别类别类别类别类别",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "子类别",
@@ -3014,7 +3014,7 @@ Array [
"子类别",
],
"originalText": "子类别",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "数量数量数量数量数量数量数量数量数量数量...",
@@ -3027,7 +3027,7 @@ Array [
"数量数量数量...",
],
"originalText": "数量数量数量数量数量数量数量数量数量数量数量",
- "width": 103,
+ "width": 103.8,
},
]
`;
@@ -3177,7 +3177,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省浙江省浙江省浙江省浙江省浙江省浙江...",
@@ -3190,7 +3190,7 @@ Array [
"省浙江省浙江...",
],
"originalText": "浙江省浙江省浙江省浙江省浙江省浙江省浙江省浙江省浙江省浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -3201,7 +3201,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -3212,7 +3212,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -3223,7 +3223,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -3234,7 +3234,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -3245,7 +3245,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -3256,7 +3256,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -3267,7 +3267,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -3278,7 +3278,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -3289,7 +3289,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -3300,7 +3300,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -3311,7 +3311,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市杭州市杭州市杭州市杭州市杭州市杭州...",
@@ -3324,7 +3324,7 @@ Array [
"市杭州市杭州...",
],
"originalText": "杭州市杭州市杭州市杭州市杭州市杭州市杭州市杭州市杭州市杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -3335,7 +3335,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -3346,7 +3346,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "舟山市",
@@ -3357,7 +3357,7 @@ Array [
"舟山市",
],
"originalText": "舟山市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市",
@@ -3368,7 +3368,7 @@ Array [
"杭州市",
],
"originalText": "杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -3379,7 +3379,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -3390,7 +3390,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "舟山市",
@@ -3401,7 +3401,7 @@ Array [
"舟山市",
],
"originalText": "舟山市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市",
@@ -3412,7 +3412,7 @@ Array [
"杭州市",
],
"originalText": "杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -3423,7 +3423,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -3434,7 +3434,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -3445,7 +3445,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具家具家具家具家具家具家具家具家具家具...",
@@ -3458,7 +3458,7 @@ Array [
"家具家具家具...",
],
"originalText": "家具家具家具家具家具家具家具家具家具家具家具家具家具家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -3469,7 +3469,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -3480,7 +3480,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -3491,7 +3491,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -3502,7 +3502,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -3513,7 +3513,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -3524,7 +3524,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -3535,7 +3535,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -3546,7 +3546,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -3557,7 +3557,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -3568,7 +3568,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -3579,7 +3579,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子...",
@@ -3592,7 +3592,7 @@ Array [
"桌子桌子桌子...",
],
"originalText": "桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -3603,7 +3603,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -3614,7 +3614,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -3625,7 +3625,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -3636,7 +3636,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -3647,7 +3647,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -3658,7 +3658,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -3669,7 +3669,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -3680,7 +3680,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -3691,7 +3691,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -3702,7 +3702,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "236723672361111",
@@ -3710,11 +3710,11 @@ Array [
"actualTextWidth": 100,
"height": 30,
"multiLineActualTexts": Array [
- "236723672361",
- "111",
+ "2367236723611",
+ "11",
],
"originalText": "236723672361111",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "7789778977897789778977897789",
@@ -3722,12 +3722,12 @@ Array [
"actualTextWidth": 189,
"height": 30,
"multiLineActualTexts": Array [
- "778977897789",
- "778977897789",
- "7789",
+ "7789778977897",
+ "7897789778977",
+ "89",
],
"originalText": "7789778977897789778977897789",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "236723672361111",
@@ -3735,11 +3735,11 @@ Array [
"actualTextWidth": 100,
"height": 30,
"multiLineActualTexts": Array [
- "236723672361",
- "111",
+ "2367236723611",
+ "11",
],
"originalText": "236723672361111",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "3877",
@@ -3750,7 +3750,7 @@ Array [
"3877",
],
"originalText": "3877",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "4342",
@@ -3761,7 +3761,7 @@ Array [
"4342",
],
"originalText": "4342",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "5343",
@@ -3772,7 +3772,7 @@ Array [
"5343",
],
"originalText": "5343",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "632",
@@ -3783,7 +3783,7 @@ Array [
"632",
],
"originalText": "632",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "7234",
@@ -3794,7 +3794,7 @@ Array [
"7234",
],
"originalText": "7234",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "834",
@@ -3805,7 +3805,7 @@ Array [
"834",
],
"originalText": "834",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "945",
@@ -3816,7 +3816,7 @@ Array [
"945",
],
"originalText": "945",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1304",
@@ -3827,7 +3827,7 @@ Array [
"1304",
],
"originalText": "1304",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1145",
@@ -3838,7 +3838,7 @@ Array [
"1145",
],
"originalText": "1145",
- "width": 103,
+ "width": 103.8,
},
]
`;
@@ -4018,7 +4018,7 @@ Array [
"省份",
],
"originalText": "省份",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "城市城市城市城市城市城市城...",
@@ -4030,7 +4030,7 @@ Array [
"市城市城市城...",
],
"originalText": "城市城市城市城市城市城市城市城市城市城市城市城市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "类别类别类别类别类别类别类...",
@@ -4042,7 +4042,7 @@ Array [
"别类别类别类...",
],
"originalText": "类别类别类别类别类别类别类别类别类别类别",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "子类别",
@@ -4053,7 +4053,7 @@ Array [
"子类别",
],
"originalText": "子类别",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "数量数量数量数量数量数量数...",
@@ -4065,7 +4065,7 @@ Array [
"量数量数量数...",
],
"originalText": "数量数量数量数量数量数量数量数量数量数量数量",
- "width": 103,
+ "width": 103.8,
},
]
`;
@@ -4215,7 +4215,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省浙江省浙江省浙江省浙...",
@@ -4227,7 +4227,7 @@ Array [
"江省浙江省浙...",
],
"originalText": "浙江省浙江省浙江省浙江省浙江省浙江省浙江省浙江省浙江省浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -4238,7 +4238,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -4249,7 +4249,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -4260,7 +4260,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -4271,7 +4271,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -4282,7 +4282,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -4293,7 +4293,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -4304,7 +4304,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -4315,7 +4315,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -4326,7 +4326,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -4337,7 +4337,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -4348,7 +4348,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市杭州市杭州市杭州市杭...",
@@ -4360,7 +4360,7 @@ Array [
"州市杭州市杭...",
],
"originalText": "杭州市杭州市杭州市杭州市杭州市杭州市杭州市杭州市杭州市杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -4371,7 +4371,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -4382,7 +4382,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "舟山市",
@@ -4393,7 +4393,7 @@ Array [
"舟山市",
],
"originalText": "舟山市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市",
@@ -4404,7 +4404,7 @@ Array [
"杭州市",
],
"originalText": "杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -4415,7 +4415,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -4426,7 +4426,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "舟山市",
@@ -4437,7 +4437,7 @@ Array [
"舟山市",
],
"originalText": "舟山市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市",
@@ -4448,7 +4448,7 @@ Array [
"杭州市",
],
"originalText": "杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -4459,7 +4459,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -4470,7 +4470,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -4481,7 +4481,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具家具家具家具家具家具家...",
@@ -4493,7 +4493,7 @@ Array [
"具家具家具家...",
],
"originalText": "家具家具家具家具家具家具家具家具家具家具家具家具家具家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -4504,7 +4504,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -4515,7 +4515,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -4526,7 +4526,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -4537,7 +4537,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -4548,7 +4548,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -4559,7 +4559,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -4570,7 +4570,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -4581,7 +4581,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -4592,7 +4592,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -4603,7 +4603,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -4614,7 +4614,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子桌子桌子桌子桌子桌子桌...",
@@ -4626,7 +4626,7 @@ Array [
"子桌子桌子桌...",
],
"originalText": "桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -4637,7 +4637,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -4648,7 +4648,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -4659,7 +4659,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -4670,7 +4670,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -4681,7 +4681,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -4692,7 +4692,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -4703,7 +4703,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -4714,7 +4714,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -4725,7 +4725,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -4736,7 +4736,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "236723672361111",
@@ -4744,23 +4744,23 @@ Array [
"actualTextWidth": 100,
"height": 30,
"multiLineActualTexts": Array [
- "236723672361",
- "111",
+ "2367236723611",
+ "11",
],
"originalText": "236723672361111",
- "width": 103,
+ "width": 103.8,
},
Object {
- "actualText": "77897789778977897789778...",
+ "actualText": "778977897789778977897789...",
"actualTextHeight": 30,
- "actualTextWidth": 165,
+ "actualTextWidth": 172,
"height": 30,
"multiLineActualTexts": Array [
- "778977897789",
- "77897789778...",
+ "7789778977897",
+ "78977897789...",
],
"originalText": "7789778977897789778977897789",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "236723672361111",
@@ -4768,11 +4768,11 @@ Array [
"actualTextWidth": 100,
"height": 30,
"multiLineActualTexts": Array [
- "236723672361",
- "111",
+ "2367236723611",
+ "11",
],
"originalText": "236723672361111",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "3877",
@@ -4783,7 +4783,7 @@ Array [
"3877",
],
"originalText": "3877",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "4342",
@@ -4794,7 +4794,7 @@ Array [
"4342",
],
"originalText": "4342",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "5343",
@@ -4805,7 +4805,7 @@ Array [
"5343",
],
"originalText": "5343",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "632",
@@ -4816,7 +4816,7 @@ Array [
"632",
],
"originalText": "632",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "7234",
@@ -4827,7 +4827,7 @@ Array [
"7234",
],
"originalText": "7234",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "834",
@@ -4838,7 +4838,7 @@ Array [
"834",
],
"originalText": "834",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "945",
@@ -4849,7 +4849,7 @@ Array [
"945",
],
"originalText": "945",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1304",
@@ -4860,7 +4860,7 @@ Array [
"1304",
],
"originalText": "1304",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1145",
@@ -4871,7 +4871,7 @@ Array [
"1145",
],
"originalText": "1145",
- "width": 103,
+ "width": 103.8,
},
]
`;
@@ -5062,7 +5062,7 @@ Array [
"省份",
],
"originalText": "省份",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "城市城市城市...",
@@ -5073,7 +5073,7 @@ Array [
"城市城市城市...",
],
"originalText": "城市城市城市城市城市城市城市城市城市城市城市城市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "类别类别类别...",
@@ -5084,7 +5084,7 @@ Array [
"类别类别类别...",
],
"originalText": "类别类别类别类别类别类别类别类别类别类别",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "子类别",
@@ -5095,7 +5095,7 @@ Array [
"子类别",
],
"originalText": "子类别",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "数量数量数量...",
@@ -5106,7 +5106,7 @@ Array [
"数量数量数量...",
],
"originalText": "数量数量数量数量数量数量数量数量数量数量数量",
- "width": 103,
+ "width": 103.8,
},
]
`;
@@ -5267,7 +5267,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省浙江省...",
@@ -5278,7 +5278,7 @@ Array [
"浙江省浙江省...",
],
"originalText": "浙江省浙江省浙江省浙江省浙江省浙江省浙江省浙江省浙江省浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -5289,7 +5289,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -5300,7 +5300,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -5311,7 +5311,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -5322,7 +5322,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -5333,7 +5333,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -5344,7 +5344,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -5355,7 +5355,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -5366,7 +5366,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -5377,7 +5377,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -5388,7 +5388,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -5399,7 +5399,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -5410,7 +5410,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市杭州市...",
@@ -5421,7 +5421,7 @@ Array [
"杭州市杭州市...",
],
"originalText": "杭州市杭州市杭州市杭州市杭州市杭州市杭州市杭州市杭州市杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -5432,7 +5432,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -5443,7 +5443,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "舟山市",
@@ -5454,7 +5454,7 @@ Array [
"舟山市",
],
"originalText": "舟山市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市",
@@ -5465,7 +5465,7 @@ Array [
"杭州市",
],
"originalText": "杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -5476,7 +5476,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -5487,7 +5487,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "舟山市",
@@ -5498,7 +5498,7 @@ Array [
"舟山市",
],
"originalText": "舟山市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市",
@@ -5509,7 +5509,7 @@ Array [
"杭州市",
],
"originalText": "杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -5520,7 +5520,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -5531,7 +5531,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "舟山市",
@@ -5542,7 +5542,7 @@ Array [
"舟山市",
],
"originalText": "舟山市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -5553,7 +5553,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具家具家具...",
@@ -5564,7 +5564,7 @@ Array [
"家具家具家具...",
],
"originalText": "家具家具家具家具家具家具家具家具家具家具家具家具家具家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -5575,7 +5575,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -5586,7 +5586,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -5597,7 +5597,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -5608,7 +5608,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -5619,7 +5619,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -5630,7 +5630,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -5641,7 +5641,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -5652,7 +5652,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -5663,7 +5663,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -5674,7 +5674,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -5685,7 +5685,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -5696,7 +5696,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子桌子桌子...",
@@ -5707,7 +5707,7 @@ Array [
"桌子桌子桌子...",
],
"originalText": "桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -5718,7 +5718,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -5729,7 +5729,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -5740,7 +5740,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -5751,7 +5751,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -5762,7 +5762,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -5773,7 +5773,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -5784,7 +5784,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -5795,7 +5795,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -5806,7 +5806,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -5817,7 +5817,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -5828,7 +5828,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "23672367236...",
@@ -5839,7 +5839,7 @@ Array [
"23672367236...",
],
"originalText": "236723672361111",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "77897789778...",
@@ -5850,7 +5850,7 @@ Array [
"77897789778...",
],
"originalText": "7789778977897789778977897789",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "23672367236...",
@@ -5861,7 +5861,7 @@ Array [
"23672367236...",
],
"originalText": "236723672361111",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "3877",
@@ -5872,7 +5872,7 @@ Array [
"3877",
],
"originalText": "3877",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "4342",
@@ -5883,7 +5883,7 @@ Array [
"4342",
],
"originalText": "4342",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "5343",
@@ -5894,7 +5894,7 @@ Array [
"5343",
],
"originalText": "5343",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "632",
@@ -5905,7 +5905,7 @@ Array [
"632",
],
"originalText": "632",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "7234",
@@ -5916,7 +5916,7 @@ Array [
"7234",
],
"originalText": "7234",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "834",
@@ -5927,7 +5927,7 @@ Array [
"834",
],
"originalText": "834",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "945",
@@ -5938,7 +5938,7 @@ Array [
"945",
],
"originalText": "945",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1304",
@@ -5949,7 +5949,7 @@ Array [
"1304",
],
"originalText": "1304",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1145",
@@ -5960,7 +5960,7 @@ Array [
"1145",
],
"originalText": "1145",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1432",
@@ -5971,7 +5971,7 @@ Array [
"1432",
],
"originalText": "1432",
- "width": 103,
+ "width": 103.8,
},
]
`;
@@ -6217,7 +6217,7 @@ Array [
"省份",
],
"originalText": "省份",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "城市城市城市城市城市城市城...",
@@ -6229,7 +6229,7 @@ Array [
"市城市城市城...",
],
"originalText": "城市城市城市城市城市城市城市城市城市城市城市城市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "类别类别类别类别类别类别类...",
@@ -6241,7 +6241,7 @@ Array [
"别类别类别类...",
],
"originalText": "类别类别类别类别类别类别类别类别类别类别",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "子类别",
@@ -6252,7 +6252,7 @@ Array [
"子类别",
],
"originalText": "子类别",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "数量数量数量数量数量数量数...",
@@ -6264,7 +6264,7 @@ Array [
"量数量数量数...",
],
"originalText": "数量数量数量数量数量数量数量数量数量数量数量",
- "width": 103,
+ "width": 103.8,
},
]
`;
@@ -6480,7 +6480,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省浙江省浙江省浙江省浙...",
@@ -6492,7 +6492,7 @@ Array [
"江省浙江省浙...",
],
"originalText": "浙江省浙江省浙江省浙江省浙江省浙江省浙江省浙江省浙江省浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6503,7 +6503,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6514,7 +6514,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6525,7 +6525,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6536,7 +6536,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6547,7 +6547,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6558,7 +6558,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6569,7 +6569,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6580,7 +6580,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6591,7 +6591,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6602,7 +6602,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6613,7 +6613,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6624,7 +6624,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6635,7 +6635,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6646,7 +6646,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "浙江省",
@@ -6657,7 +6657,7 @@ Array [
"浙江省",
],
"originalText": "浙江省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "四川省",
@@ -6668,7 +6668,7 @@ Array [
"四川省",
],
"originalText": "四川省",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -6679,7 +6679,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市杭州市杭州市杭州市杭...",
@@ -6691,7 +6691,7 @@ Array [
"州市杭州市杭...",
],
"originalText": "杭州市杭州市杭州市杭州市杭州市杭州市杭州市杭州市杭州市杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -6702,7 +6702,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -6713,7 +6713,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "舟山市",
@@ -6724,7 +6724,7 @@ Array [
"舟山市",
],
"originalText": "舟山市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市",
@@ -6735,7 +6735,7 @@ Array [
"杭州市",
],
"originalText": "杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -6746,7 +6746,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -6757,7 +6757,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "舟山市",
@@ -6768,7 +6768,7 @@ Array [
"舟山市",
],
"originalText": "舟山市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市",
@@ -6779,7 +6779,7 @@ Array [
"杭州市",
],
"originalText": "杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -6790,7 +6790,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -6801,7 +6801,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "舟山市",
@@ -6812,7 +6812,7 @@ Array [
"舟山市",
],
"originalText": "舟山市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "杭州市",
@@ -6823,7 +6823,7 @@ Array [
"杭州市",
],
"originalText": "杭州市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "绍兴市",
@@ -6834,7 +6834,7 @@ Array [
"绍兴市",
],
"originalText": "绍兴市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "宁波市",
@@ -6845,7 +6845,7 @@ Array [
"宁波市",
],
"originalText": "宁波市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "舟山市",
@@ -6856,7 +6856,7 @@ Array [
"舟山市",
],
"originalText": "舟山市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "成都市",
@@ -6867,7 +6867,7 @@ Array [
"成都市",
],
"originalText": "成都市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -6878,7 +6878,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具家具家具家具家具家具家...",
@@ -6890,7 +6890,7 @@ Array [
"具家具家具家...",
],
"originalText": "家具家具家具家具家具家具家具家具家具家具家具家具家具家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -6901,7 +6901,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -6912,7 +6912,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -6923,7 +6923,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -6934,7 +6934,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -6945,7 +6945,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -6956,7 +6956,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -6967,7 +6967,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -6978,7 +6978,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -6989,7 +6989,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -7000,7 +7000,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -7011,7 +7011,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -7022,7 +7022,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -7033,7 +7033,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -7044,7 +7044,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "办公用品",
@@ -7055,7 +7055,7 @@ Array [
"办公用品",
],
"originalText": "办公用品",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "家具",
@@ -7066,7 +7066,7 @@ Array [
"家具",
],
"originalText": "家具",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -7077,7 +7077,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子桌子桌子桌子桌子桌子桌...",
@@ -7089,7 +7089,7 @@ Array [
"子桌子桌子桌...",
],
"originalText": "桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -7100,7 +7100,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -7111,7 +7111,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -7122,7 +7122,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -7133,7 +7133,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -7144,7 +7144,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -7155,7 +7155,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "沙发",
@@ -7166,7 +7166,7 @@ Array [
"沙发",
],
"originalText": "沙发",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -7177,7 +7177,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -7188,7 +7188,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -7199,7 +7199,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "笔",
@@ -7210,7 +7210,7 @@ Array [
"笔",
],
"originalText": "笔",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "纸张",
@@ -7221,7 +7221,7 @@ Array [
"纸张",
],
"originalText": "纸张",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "纸张",
@@ -7232,7 +7232,7 @@ Array [
"纸张",
],
"originalText": "纸张",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "纸张",
@@ -7243,7 +7243,7 @@ Array [
"纸张",
],
"originalText": "纸张",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "纸张",
@@ -7254,7 +7254,7 @@ Array [
"纸张",
],
"originalText": "纸张",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "桌子",
@@ -7265,7 +7265,7 @@ Array [
"桌子",
],
"originalText": "桌子",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "236723672361111",
@@ -7273,23 +7273,23 @@ Array [
"actualTextWidth": 100,
"height": 20,
"multiLineActualTexts": Array [
- "236723672361",
- "111",
+ "2367236723611",
+ "11",
],
"originalText": "236723672361111",
- "width": 103,
+ "width": 103.8,
},
Object {
- "actualText": "77897789778977897789778...",
+ "actualText": "778977897789778977897789...",
"actualTextHeight": 30,
- "actualTextWidth": 165,
+ "actualTextWidth": 172,
"height": 20,
"multiLineActualTexts": Array [
- "778977897789",
- "77897789778...",
+ "7789778977897",
+ "78977897789...",
],
"originalText": "7789778977897789778977897789",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "236723672361111",
@@ -7297,11 +7297,11 @@ Array [
"actualTextWidth": 100,
"height": 20,
"multiLineActualTexts": Array [
- "236723672361",
- "111",
+ "2367236723611",
+ "11",
],
"originalText": "236723672361111",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "3877",
@@ -7312,7 +7312,7 @@ Array [
"3877",
],
"originalText": "3877",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "4342",
@@ -7323,7 +7323,7 @@ Array [
"4342",
],
"originalText": "4342",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "5343",
@@ -7334,7 +7334,7 @@ Array [
"5343",
],
"originalText": "5343",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "632",
@@ -7345,7 +7345,7 @@ Array [
"632",
],
"originalText": "632",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "7234",
@@ -7356,7 +7356,7 @@ Array [
"7234",
],
"originalText": "7234",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "834",
@@ -7367,7 +7367,7 @@ Array [
"834",
],
"originalText": "834",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "945",
@@ -7378,7 +7378,7 @@ Array [
"945",
],
"originalText": "945",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1304",
@@ -7389,7 +7389,7 @@ Array [
"1304",
],
"originalText": "1304",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1145",
@@ -7400,7 +7400,7 @@ Array [
"1145",
],
"originalText": "1145",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1432",
@@ -7411,7 +7411,7 @@ Array [
"1432",
],
"originalText": "1432",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1343",
@@ -7422,7 +7422,7 @@ Array [
"1343",
],
"originalText": "1343",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1354",
@@ -7433,7 +7433,7 @@ Array [
"1354",
],
"originalText": "1354",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1523",
@@ -7444,7 +7444,7 @@ Array [
"1523",
],
"originalText": "1523",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1634",
@@ -7455,7 +7455,7 @@ Array [
"1634",
],
"originalText": "1634",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "1723",
@@ -7466,7 +7466,7 @@ Array [
"1723",
],
"originalText": "1723",
- "width": 103,
+ "width": 103.8,
},
]
`;
@@ -7493,7 +7493,7 @@ Array [
"省份",
],
"originalText": "省份",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "城市城市城市城市城市城市城...",
@@ -7505,7 +7505,7 @@ Array [
"市城市城市城...",
],
"originalText": "城市城市城市城市城市城市城市城市城市城市城市城市",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "类别类别类别类别类别类别类...",
@@ -7517,7 +7517,7 @@ Array [
"别类别类别类...",
],
"originalText": "类别类别类别类别类别类别类别类别类别类别",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "子类别",
@@ -7528,7 +7528,7 @@ Array [
"子类别",
],
"originalText": "子类别",
- "width": 103,
+ "width": 103.8,
},
Object {
"actualText": "数量数量数量数量数量数量数...",
@@ -7540,7 +7540,7 @@ Array [
"量数量数量数...",
],
"originalText": "数量数量数量数量数量数量数量数量数量数量数量",
- "width": 103,
+ "width": 103.8,
},
]
`;
diff --git a/packages/s2-core/__tests__/spreadsheet/__snapshots__/spread-sheet-resize-spec.ts.snap b/packages/s2-core/__tests__/spreadsheet/__snapshots__/spread-sheet-resize-spec.ts.snap
new file mode 100644
index 0000000000..fc3bf7f405
--- /dev/null
+++ b/packages/s2-core/__tests__/spreadsheet/__snapshots__/spread-sheet-resize-spec.ts.snap
@@ -0,0 +1,21 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`SpreadSheet Resize Active Tests should render correctly layout when tree row width is invalid number 1`] = `
+Array [
+ Object {
+ "height": 30,
+ "id": "root[&]浙江",
+ "width": 120,
+ },
+ Object {
+ "height": 30,
+ "id": "root[&]浙江[&]义乌",
+ "width": 120,
+ },
+ Object {
+ "height": 30,
+ "id": "root[&]浙江[&]杭州",
+ "width": 120,
+ },
+]
+`;
diff --git a/packages/s2-core/__tests__/spreadsheet/__snapshots__/theme-spec.ts.snap b/packages/s2-core/__tests__/spreadsheet/__snapshots__/theme-spec.ts.snap
index 309bd54147..81c158e752 100644
--- a/packages/s2-core/__tests__/spreadsheet/__snapshots__/theme-spec.ts.snap
+++ b/packages/s2-core/__tests__/spreadsheet/__snapshots__/theme-spec.ts.snap
@@ -22,6 +22,7 @@ Object {
"cell": Object {
"backgroundColor": "#3471F9",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"horizontalBorderColor": "#5286FA",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
@@ -106,7 +107,7 @@ Object {
"fontWeight": 700,
"maxLines": 1,
"opacity": 1,
- "textAlign": "left",
+ "textAlign": "right",
"textBaseline": "middle",
"textOverflow": "ellipsis",
"wordWrap": true,
@@ -114,6 +115,7 @@ Object {
"cell": Object {
"backgroundColor": "#3471F9",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"horizontalBorderColor": "#5286FA",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
@@ -142,7 +144,7 @@ Object {
"fontWeight": 700,
"maxLines": 1,
"opacity": 1,
- "textAlign": "right",
+ "textAlign": "left",
"textBaseline": "middle",
"textOverflow": "ellipsis",
"wordWrap": true,
@@ -448,6 +450,7 @@ Object {
"cell": Object {
"backgroundColor": "#F5F8FF",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"horizontalBorderColor": "#E1EAFE",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
@@ -549,6 +552,7 @@ Object {
"trackColor": "rgba(0,0,0,0.01)",
},
"splitLine": Object {
+ "borderDash": Array [],
"horizontalBorderColor": "#3471F9",
"horizontalBorderColorOpacity": 0.2,
"horizontalBorderWidth": 2,
@@ -587,6 +591,7 @@ Object {
"cell": Object {
"backgroundColor": "#133aad",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"horizontalBorderColor": "#0647b1",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
@@ -671,7 +676,7 @@ Object {
"fontWeight": 700,
"maxLines": 1,
"opacity": 1,
- "textAlign": "left",
+ "textAlign": "right",
"textBaseline": "middle",
"textOverflow": "ellipsis",
"wordWrap": true,
@@ -679,6 +684,7 @@ Object {
"cell": Object {
"backgroundColor": "#133aad",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"horizontalBorderColor": "#0647b1",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
@@ -707,7 +713,7 @@ Object {
"fontWeight": 700,
"maxLines": 1,
"opacity": 1,
- "textAlign": "right",
+ "textAlign": "left",
"textBaseline": "middle",
"textOverflow": "ellipsis",
"wordWrap": true,
@@ -1013,6 +1019,7 @@ Object {
"cell": Object {
"backgroundColor": "#151a27",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"horizontalBorderColor": "#1e2436",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
@@ -1114,6 +1121,7 @@ Object {
"trackColor": "rgba(0,0,0,0.01)",
},
"splitLine": Object {
+ "borderDash": Array [],
"horizontalBorderColor": "#7899ff",
"horizontalBorderColorOpacity": 0.2,
"horizontalBorderWidth": 2,
@@ -1152,6 +1160,7 @@ Object {
"cell": Object {
"backgroundColor": "#E0E9FD",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"horizontalBorderColor": "#CCDBFC",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
@@ -1236,7 +1245,7 @@ Object {
"fontWeight": 700,
"maxLines": 1,
"opacity": 1,
- "textAlign": "left",
+ "textAlign": "right",
"textBaseline": "middle",
"textOverflow": "ellipsis",
"wordWrap": true,
@@ -1244,6 +1253,7 @@ Object {
"cell": Object {
"backgroundColor": "#E0E9FD",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"horizontalBorderColor": "#CCDBFC",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
@@ -1272,7 +1282,7 @@ Object {
"fontWeight": 700,
"maxLines": 1,
"opacity": 1,
- "textAlign": "right",
+ "textAlign": "left",
"textBaseline": "middle",
"textOverflow": "ellipsis",
"wordWrap": true,
@@ -1578,6 +1588,7 @@ Object {
"cell": Object {
"backgroundColor": "#F5F8FE",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"horizontalBorderColor": "#E0E9FD",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
@@ -1679,6 +1690,7 @@ Object {
"trackColor": "rgba(0,0,0,0.01)",
},
"splitLine": Object {
+ "borderDash": Array [],
"horizontalBorderColor": "#326EF4",
"horizontalBorderColorOpacity": 0.2,
"horizontalBorderWidth": 2,
@@ -1695,7 +1707,7 @@ Object {
}
`;
-exports[`SpreadSheet Theme Tests Theme Default Value Tests should get default theme 2`] = `
+exports[`SpreadSheet Theme Tests Theme Default Value Tests should get gray theme 1`] = `
Object {
"background": Object {
"color": "#FFFFFF",
@@ -1715,9 +1727,10 @@ Object {
"wordWrap": true,
},
"cell": Object {
- "backgroundColor": "#E0E9FD",
+ "backgroundColor": "#F0F2F4",
"backgroundColorOpacity": 1,
- "horizontalBorderColor": "#CCDBFC",
+ "borderDash": Array [],
+ "horizontalBorderColor": "#E7E9ED",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
"interactionState": Object {
@@ -1726,7 +1739,7 @@ Object {
"backgroundOpacity": 1,
},
"hover": Object {
- "backgroundColor": "#CCDBFC",
+ "backgroundColor": "#E7E9ED",
"backgroundOpacity": 0.6,
},
"prepareSelect": Object {
@@ -1739,7 +1752,7 @@ Object {
"backgroundOpacity": 1,
},
"selected": Object {
- "backgroundColor": "#CCDBFC",
+ "backgroundColor": "#E7E9ED",
"backgroundOpacity": 0.6,
},
"unselected": Object {
@@ -1754,7 +1767,7 @@ Object {
"right": 8,
"top": 4,
},
- "verticalBorderColor": "#CCDBFC",
+ "verticalBorderColor": "#E7E9ED",
"verticalBorderColorOpacity": 1,
"verticalBorderWidth": 1,
},
@@ -1801,15 +1814,16 @@ Object {
"fontWeight": 700,
"maxLines": 1,
"opacity": 1,
- "textAlign": "left",
+ "textAlign": "right",
"textBaseline": "middle",
"textOverflow": "ellipsis",
"wordWrap": true,
},
"cell": Object {
- "backgroundColor": "#E0E9FD",
+ "backgroundColor": "#F0F2F4",
"backgroundColorOpacity": 1,
- "horizontalBorderColor": "#CCDBFC",
+ "borderDash": Array [],
+ "horizontalBorderColor": "#E7E9ED",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
"padding": Object {
@@ -1818,7 +1832,7 @@ Object {
"right": 8,
"top": 4,
},
- "verticalBorderColor": "#CCDBFC",
+ "verticalBorderColor": "#E7E9ED",
"verticalBorderColorOpacity": 1,
"verticalBorderWidth": 1,
},
@@ -1837,7 +1851,7 @@ Object {
"fontWeight": 700,
"maxLines": 1,
"opacity": 1,
- "textAlign": "right",
+ "textAlign": "left",
"textBaseline": "middle",
"textOverflow": "ellipsis",
"wordWrap": true,
@@ -1849,7 +1863,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": 700,
- "linkTextFill": "#326EF4",
+ "linkTextFill": "#565C64",
"maxLines": 1,
"opacity": 1,
"textAlign": "right",
@@ -1860,8 +1874,8 @@ Object {
"cell": Object {
"backgroundColor": "#FFFFFF",
"backgroundColorOpacity": 1,
- "crossBackgroundColor": "#F5F8FE",
- "horizontalBorderColor": "#E0E9FD",
+ "crossBackgroundColor": "#FAFBFB",
+ "horizontalBorderColor": "#F0F2F4",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
"interactionState": Object {
@@ -1870,11 +1884,11 @@ Object {
"backgroundOpacity": 1,
},
"hover": Object {
- "backgroundColor": "#E0E9FD",
+ "backgroundColor": "#F0F2F4",
"backgroundOpacity": 0.6,
},
"hoverFocus": Object {
- "backgroundColor": "#E0E9FD",
+ "backgroundColor": "#F0F2F4",
"backgroundOpacity": 0.6,
"borderColor": "#000000",
"borderOpacity": 1,
@@ -1890,7 +1904,7 @@ Object {
"backgroundOpacity": 1,
},
"selected": Object {
- "backgroundColor": "#E0E9FD",
+ "backgroundColor": "#F0F2F4",
"backgroundOpacity": 0.6,
},
"unselected": Object {
@@ -1905,7 +1919,7 @@ Object {
"right": 8,
"top": 8,
},
- "verticalBorderColor": "#E0E9FD",
+ "verticalBorderColor": "#F0F2F4",
"verticalBorderColorOpacity": 1,
"verticalBorderWidth": 1,
},
@@ -1919,7 +1933,7 @@ Object {
},
"miniChart": Object {
"bar": Object {
- "fill": "#326EF4",
+ "fill": "#565C64",
"intervalPadding": 4,
"opacity": 1,
},
@@ -1943,17 +1957,17 @@ Object {
},
},
"interval": Object {
- "fill": "#326EF4",
+ "fill": "#9DA7B6",
"height": 12,
},
"line": Object {
"linkLine": Object {
- "fill": "#326EF4",
+ "fill": "#565C64",
"opacity": 0.6,
"size": 1.5,
},
"point": Object {
- "fill": "#326EF4",
+ "fill": "#565C64",
"opacity": 1,
"size": 2.2,
},
@@ -1964,7 +1978,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": "normal",
- "linkTextFill": "#326EF4",
+ "linkTextFill": "#565C64",
"maxLines": 1,
"opacity": 1,
"textAlign": "right",
@@ -1979,7 +1993,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": 700,
- "linkTextFill": "#326EF4",
+ "linkTextFill": "#565C64",
"maxLines": 1,
"opacity": 1,
"textAlign": "right",
@@ -1990,8 +2004,8 @@ Object {
"cell": Object {
"backgroundColor": "#FFFFFF",
"backgroundColorOpacity": 1,
- "crossBackgroundColor": "#F5F8FE",
- "horizontalBorderColor": "#E0E9FD",
+ "crossBackgroundColor": "#FAFBFB",
+ "horizontalBorderColor": "#F0F2F4",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
"interactionState": Object {
@@ -2000,11 +2014,11 @@ Object {
"backgroundOpacity": 1,
},
"hover": Object {
- "backgroundColor": "#E0E9FD",
+ "backgroundColor": "#F0F2F4",
"backgroundOpacity": 0.6,
},
"hoverFocus": Object {
- "backgroundColor": "#E0E9FD",
+ "backgroundColor": "#F0F2F4",
"backgroundOpacity": 0.6,
"borderColor": "#000000",
"borderOpacity": 1,
@@ -2020,7 +2034,7 @@ Object {
"backgroundOpacity": 1,
},
"selected": Object {
- "backgroundColor": "#E0E9FD",
+ "backgroundColor": "#F0F2F4",
"backgroundOpacity": 0.6,
},
"unselected": Object {
@@ -2035,7 +2049,7 @@ Object {
"right": 8,
"top": 8,
},
- "verticalBorderColor": "#E0E9FD",
+ "verticalBorderColor": "#F0F2F4",
"verticalBorderColorOpacity": 1,
"verticalBorderWidth": 1,
},
@@ -2049,7 +2063,7 @@ Object {
},
"miniChart": Object {
"bar": Object {
- "fill": "#326EF4",
+ "fill": "#565C64",
"intervalPadding": 4,
"opacity": 1,
},
@@ -2073,17 +2087,17 @@ Object {
},
},
"interval": Object {
- "fill": "#326EF4",
+ "fill": "#9DA7B6",
"height": 12,
},
"line": Object {
"linkLine": Object {
- "fill": "#326EF4",
+ "fill": "#565C64",
"opacity": 0.6,
"size": 1.5,
},
"point": Object {
- "fill": "#326EF4",
+ "fill": "#565C64",
"opacity": 1,
"size": 2.2,
},
@@ -2094,7 +2108,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": "normal",
- "linkTextFill": "#326EF4",
+ "linkTextFill": "#565C64",
"maxLines": 1,
"opacity": 1,
"textAlign": "right",
@@ -2104,13 +2118,13 @@ Object {
},
},
"prepareSelectMask": Object {
- "backgroundColor": "#234DAB",
+ "backgroundColor": "#6E757F",
"backgroundOpacity": 0.3,
},
"resizeArea": Object {
- "background": "#326EF4",
+ "background": "#9DA7B6",
"backgroundOpacity": 0,
- "guideLineColor": "#326EF4",
+ "guideLineColor": "#9DA7B6",
"guideLineDash": Array [
3,
3,
@@ -2118,7 +2132,7 @@ Object {
"guideLineDisableColor": "rgba(0,0,0,0.25)",
"interactionState": Object {
"hover": Object {
- "backgroundColor": "#326EF4",
+ "backgroundColor": "#9DA7B6",
"backgroundOpacity": 1,
},
},
@@ -2132,7 +2146,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": 700,
- "linkTextFill": "#326EF4",
+ "linkTextFill": "#565C64",
"maxLines": 1,
"opacity": 1,
"textAlign": "left",
@@ -2141,9 +2155,10 @@ Object {
"wordWrap": true,
},
"cell": Object {
- "backgroundColor": "#F5F8FE",
+ "backgroundColor": "#FAFBFB",
"backgroundColorOpacity": 1,
- "horizontalBorderColor": "#E0E9FD",
+ "borderDash": Array [],
+ "horizontalBorderColor": "#F0F2F4",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
"interactionState": Object {
@@ -2152,7 +2167,7 @@ Object {
"backgroundOpacity": 1,
},
"hover": Object {
- "backgroundColor": "#E0E9FD",
+ "backgroundColor": "#F0F2F4",
"backgroundOpacity": 0.6,
},
"prepareSelect": Object {
@@ -2165,7 +2180,7 @@ Object {
"backgroundOpacity": 1,
},
"selected": Object {
- "backgroundColor": "#E0E9FD",
+ "backgroundColor": "#F0F2F4",
"backgroundOpacity": 0.6,
},
"unselected": Object {
@@ -2180,7 +2195,7 @@ Object {
"right": 8,
"top": 4,
},
- "verticalBorderColor": "#E0E9FD",
+ "verticalBorderColor": "#F0F2F4",
"verticalBorderColorOpacity": 1,
"verticalBorderWidth": 1,
},
@@ -2197,7 +2212,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": "normal",
- "linkTextFill": "#326EF4",
+ "linkTextFill": "#565C64",
"maxLines": 1,
"opacity": 1,
"textAlign": "left",
@@ -2211,7 +2226,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": "normal",
- "linkTextFill": "#326EF4",
+ "linkTextFill": "#565C64",
"maxLines": 1,
"opacity": 1,
"textAlign": "center",
@@ -2224,7 +2239,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": "normal",
- "linkTextFill": "#326EF4",
+ "linkTextFill": "#565C64",
"maxLines": 1,
"opacity": 1,
"textAlign": "left",
@@ -2244,7 +2259,8 @@ Object {
"trackColor": "rgba(0,0,0,0.01)",
},
"splitLine": Object {
- "horizontalBorderColor": "#326EF4",
+ "borderDash": Array [],
+ "horizontalBorderColor": "#BAC1CC",
"horizontalBorderColorOpacity": 0.2,
"horizontalBorderWidth": 2,
"shadowColors": Object {
@@ -2253,14 +2269,14 @@ Object {
},
"shadowWidth": 8,
"showShadow": true,
- "verticalBorderColor": "#326EF4",
+ "verticalBorderColor": "#BAC1CC",
"verticalBorderColorOpacity": 0.25,
"verticalBorderWidth": 2,
},
}
`;
-exports[`SpreadSheet Theme Tests Theme Default Value Tests should get gray theme 1`] = `
+exports[`SpreadSheet Theme Tests Theme Default Value Tests should get pivot sheet default theme 1`] = `
Object {
"background": Object {
"color": "#FFFFFF",
@@ -2280,9 +2296,10 @@ Object {
"wordWrap": true,
},
"cell": Object {
- "backgroundColor": "#F0F2F4",
+ "backgroundColor": "#E0E9FD",
"backgroundColorOpacity": 1,
- "horizontalBorderColor": "#E7E9ED",
+ "borderDash": Array [],
+ "horizontalBorderColor": "#CCDBFC",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
"interactionState": Object {
@@ -2291,7 +2308,7 @@ Object {
"backgroundOpacity": 1,
},
"hover": Object {
- "backgroundColor": "#E7E9ED",
+ "backgroundColor": "#CCDBFC",
"backgroundOpacity": 0.6,
},
"prepareSelect": Object {
@@ -2304,7 +2321,7 @@ Object {
"backgroundOpacity": 1,
},
"selected": Object {
- "backgroundColor": "#E7E9ED",
+ "backgroundColor": "#CCDBFC",
"backgroundOpacity": 0.6,
},
"unselected": Object {
@@ -2319,7 +2336,7 @@ Object {
"right": 8,
"top": 4,
},
- "verticalBorderColor": "#E7E9ED",
+ "verticalBorderColor": "#CCDBFC",
"verticalBorderColorOpacity": 1,
"verticalBorderWidth": 1,
},
@@ -2366,15 +2383,16 @@ Object {
"fontWeight": 700,
"maxLines": 1,
"opacity": 1,
- "textAlign": "left",
+ "textAlign": "right",
"textBaseline": "middle",
"textOverflow": "ellipsis",
"wordWrap": true,
},
"cell": Object {
- "backgroundColor": "#F0F2F4",
+ "backgroundColor": "#E0E9FD",
"backgroundColorOpacity": 1,
- "horizontalBorderColor": "#E7E9ED",
+ "borderDash": Array [],
+ "horizontalBorderColor": "#CCDBFC",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
"padding": Object {
@@ -2383,7 +2401,7 @@ Object {
"right": 8,
"top": 4,
},
- "verticalBorderColor": "#E7E9ED",
+ "verticalBorderColor": "#CCDBFC",
"verticalBorderColorOpacity": 1,
"verticalBorderWidth": 1,
},
@@ -2402,7 +2420,7 @@ Object {
"fontWeight": 700,
"maxLines": 1,
"opacity": 1,
- "textAlign": "right",
+ "textAlign": "left",
"textBaseline": "middle",
"textOverflow": "ellipsis",
"wordWrap": true,
@@ -2414,7 +2432,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": 700,
- "linkTextFill": "#565C64",
+ "linkTextFill": "#326EF4",
"maxLines": 1,
"opacity": 1,
"textAlign": "right",
@@ -2425,8 +2443,8 @@ Object {
"cell": Object {
"backgroundColor": "#FFFFFF",
"backgroundColorOpacity": 1,
- "crossBackgroundColor": "#FAFBFB",
- "horizontalBorderColor": "#F0F2F4",
+ "crossBackgroundColor": "#F5F8FE",
+ "horizontalBorderColor": "#E0E9FD",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
"interactionState": Object {
@@ -2435,11 +2453,11 @@ Object {
"backgroundOpacity": 1,
},
"hover": Object {
- "backgroundColor": "#F0F2F4",
+ "backgroundColor": "#E0E9FD",
"backgroundOpacity": 0.6,
},
"hoverFocus": Object {
- "backgroundColor": "#F0F2F4",
+ "backgroundColor": "#E0E9FD",
"backgroundOpacity": 0.6,
"borderColor": "#000000",
"borderOpacity": 1,
@@ -2455,7 +2473,7 @@ Object {
"backgroundOpacity": 1,
},
"selected": Object {
- "backgroundColor": "#F0F2F4",
+ "backgroundColor": "#E0E9FD",
"backgroundOpacity": 0.6,
},
"unselected": Object {
@@ -2470,7 +2488,7 @@ Object {
"right": 8,
"top": 8,
},
- "verticalBorderColor": "#F0F2F4",
+ "verticalBorderColor": "#E0E9FD",
"verticalBorderColorOpacity": 1,
"verticalBorderWidth": 1,
},
@@ -2484,7 +2502,7 @@ Object {
},
"miniChart": Object {
"bar": Object {
- "fill": "#565C64",
+ "fill": "#326EF4",
"intervalPadding": 4,
"opacity": 1,
},
@@ -2508,17 +2526,17 @@ Object {
},
},
"interval": Object {
- "fill": "#9DA7B6",
+ "fill": "#326EF4",
"height": 12,
},
"line": Object {
"linkLine": Object {
- "fill": "#565C64",
+ "fill": "#326EF4",
"opacity": 0.6,
"size": 1.5,
},
"point": Object {
- "fill": "#565C64",
+ "fill": "#326EF4",
"opacity": 1,
"size": 2.2,
},
@@ -2529,7 +2547,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": "normal",
- "linkTextFill": "#565C64",
+ "linkTextFill": "#326EF4",
"maxLines": 1,
"opacity": 1,
"textAlign": "right",
@@ -2544,7 +2562,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": 700,
- "linkTextFill": "#565C64",
+ "linkTextFill": "#326EF4",
"maxLines": 1,
"opacity": 1,
"textAlign": "right",
@@ -2555,8 +2573,8 @@ Object {
"cell": Object {
"backgroundColor": "#FFFFFF",
"backgroundColorOpacity": 1,
- "crossBackgroundColor": "#FAFBFB",
- "horizontalBorderColor": "#F0F2F4",
+ "crossBackgroundColor": "#F5F8FE",
+ "horizontalBorderColor": "#E0E9FD",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
"interactionState": Object {
@@ -2565,11 +2583,11 @@ Object {
"backgroundOpacity": 1,
},
"hover": Object {
- "backgroundColor": "#F0F2F4",
+ "backgroundColor": "#E0E9FD",
"backgroundOpacity": 0.6,
},
"hoverFocus": Object {
- "backgroundColor": "#F0F2F4",
+ "backgroundColor": "#E0E9FD",
"backgroundOpacity": 0.6,
"borderColor": "#000000",
"borderOpacity": 1,
@@ -2585,7 +2603,7 @@ Object {
"backgroundOpacity": 1,
},
"selected": Object {
- "backgroundColor": "#F0F2F4",
+ "backgroundColor": "#E0E9FD",
"backgroundOpacity": 0.6,
},
"unselected": Object {
@@ -2600,7 +2618,7 @@ Object {
"right": 8,
"top": 8,
},
- "verticalBorderColor": "#F0F2F4",
+ "verticalBorderColor": "#E0E9FD",
"verticalBorderColorOpacity": 1,
"verticalBorderWidth": 1,
},
@@ -2614,7 +2632,7 @@ Object {
},
"miniChart": Object {
"bar": Object {
- "fill": "#565C64",
+ "fill": "#326EF4",
"intervalPadding": 4,
"opacity": 1,
},
@@ -2638,17 +2656,17 @@ Object {
},
},
"interval": Object {
- "fill": "#9DA7B6",
+ "fill": "#326EF4",
"height": 12,
},
"line": Object {
"linkLine": Object {
- "fill": "#565C64",
+ "fill": "#326EF4",
"opacity": 0.6,
"size": 1.5,
},
"point": Object {
- "fill": "#565C64",
+ "fill": "#326EF4",
"opacity": 1,
"size": 2.2,
},
@@ -2659,7 +2677,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": "normal",
- "linkTextFill": "#565C64",
+ "linkTextFill": "#326EF4",
"maxLines": 1,
"opacity": 1,
"textAlign": "right",
@@ -2669,13 +2687,13 @@ Object {
},
},
"prepareSelectMask": Object {
- "backgroundColor": "#6E757F",
+ "backgroundColor": "#234DAB",
"backgroundOpacity": 0.3,
},
"resizeArea": Object {
- "background": "#9DA7B6",
+ "background": "#326EF4",
"backgroundOpacity": 0,
- "guideLineColor": "#9DA7B6",
+ "guideLineColor": "#326EF4",
"guideLineDash": Array [
3,
3,
@@ -2683,7 +2701,7 @@ Object {
"guideLineDisableColor": "rgba(0,0,0,0.25)",
"interactionState": Object {
"hover": Object {
- "backgroundColor": "#9DA7B6",
+ "backgroundColor": "#326EF4",
"backgroundOpacity": 1,
},
},
@@ -2697,7 +2715,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": 700,
- "linkTextFill": "#565C64",
+ "linkTextFill": "#326EF4",
"maxLines": 1,
"opacity": 1,
"textAlign": "left",
@@ -2706,9 +2724,10 @@ Object {
"wordWrap": true,
},
"cell": Object {
- "backgroundColor": "#FAFBFB",
+ "backgroundColor": "#F5F8FE",
"backgroundColorOpacity": 1,
- "horizontalBorderColor": "#F0F2F4",
+ "borderDash": Array [],
+ "horizontalBorderColor": "#E0E9FD",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
"interactionState": Object {
@@ -2717,7 +2736,7 @@ Object {
"backgroundOpacity": 1,
},
"hover": Object {
- "backgroundColor": "#F0F2F4",
+ "backgroundColor": "#E0E9FD",
"backgroundOpacity": 0.6,
},
"prepareSelect": Object {
@@ -2730,7 +2749,7 @@ Object {
"backgroundOpacity": 1,
},
"selected": Object {
- "backgroundColor": "#F0F2F4",
+ "backgroundColor": "#E0E9FD",
"backgroundOpacity": 0.6,
},
"unselected": Object {
@@ -2745,7 +2764,7 @@ Object {
"right": 8,
"top": 4,
},
- "verticalBorderColor": "#F0F2F4",
+ "verticalBorderColor": "#E0E9FD",
"verticalBorderColorOpacity": 1,
"verticalBorderWidth": 1,
},
@@ -2762,7 +2781,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": "normal",
- "linkTextFill": "#565C64",
+ "linkTextFill": "#326EF4",
"maxLines": 1,
"opacity": 1,
"textAlign": "left",
@@ -2776,7 +2795,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": "normal",
- "linkTextFill": "#565C64",
+ "linkTextFill": "#326EF4",
"maxLines": 1,
"opacity": 1,
"textAlign": "center",
@@ -2789,7 +2808,7 @@ Object {
"fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
"fontSize": 12,
"fontWeight": "normal",
- "linkTextFill": "#565C64",
+ "linkTextFill": "#326EF4",
"maxLines": 1,
"opacity": 1,
"textAlign": "left",
@@ -2809,7 +2828,8 @@ Object {
"trackColor": "rgba(0,0,0,0.01)",
},
"splitLine": Object {
- "horizontalBorderColor": "#BAC1CC",
+ "borderDash": Array [],
+ "horizontalBorderColor": "#326EF4",
"horizontalBorderColorOpacity": 0.2,
"horizontalBorderWidth": 2,
"shadowColors": Object {
@@ -2818,7 +2838,576 @@ Object {
},
"shadowWidth": 8,
"showShadow": true,
- "verticalBorderColor": "#BAC1CC",
+ "verticalBorderColor": "#326EF4",
+ "verticalBorderColorOpacity": 0.25,
+ "verticalBorderWidth": 2,
+ },
+}
+`;
+
+exports[`SpreadSheet Theme Tests Theme Default Value Tests should get table sheet theme 1`] = `
+Object {
+ "background": Object {
+ "color": "#FFFFFF",
+ "opacity": 1,
+ },
+ "colCell": Object {
+ "bolderText": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": 700,
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "center",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ "cell": Object {
+ "backgroundColor": "#E0E9FD",
+ "backgroundColorOpacity": 1,
+ "borderDash": Array [],
+ "horizontalBorderColor": "#CCDBFC",
+ "horizontalBorderColorOpacity": 1,
+ "horizontalBorderWidth": 1,
+ "interactionState": Object {
+ "highlight": Object {
+ "backgroundColor": "#87B5FF",
+ "backgroundOpacity": 1,
+ },
+ "hover": Object {
+ "backgroundColor": "#CCDBFC",
+ "backgroundOpacity": 0.6,
+ },
+ "prepareSelect": Object {
+ "borderColor": "#000000",
+ "borderOpacity": 1,
+ "borderWidth": 1,
+ },
+ "searchResult": Object {
+ "backgroundColor": "#F0F7FF",
+ "backgroundOpacity": 1,
+ },
+ "selected": Object {
+ "backgroundColor": "#CCDBFC",
+ "backgroundOpacity": 0.6,
+ },
+ "unselected": Object {
+ "backgroundOpacity": 0.3,
+ "opacity": 0.3,
+ "textOpacity": 0.3,
+ },
+ },
+ "padding": Object {
+ "bottom": 4,
+ "left": 8,
+ "right": 8,
+ "top": 4,
+ },
+ "verticalBorderColor": "#CCDBFC",
+ "verticalBorderColorOpacity": 1,
+ "verticalBorderWidth": 1,
+ },
+ "icon": Object {
+ "fill": "#000000",
+ "margin": Object {
+ "bottom": 6,
+ "left": 4,
+ "right": 4,
+ "top": 6,
+ },
+ "size": 10,
+ },
+ "measureText": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": "normal",
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "right",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ "text": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": "normal",
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "center",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ },
+ "cornerCell": Object {
+ "bolderText": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": 700,
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "center",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ "cell": Object {
+ "backgroundColor": "#E0E9FD",
+ "backgroundColorOpacity": 1,
+ "borderDash": Array [],
+ "horizontalBorderColor": "#CCDBFC",
+ "horizontalBorderColorOpacity": 1,
+ "horizontalBorderWidth": 1,
+ "padding": Object {
+ "bottom": 4,
+ "left": 8,
+ "right": 8,
+ "top": 4,
+ },
+ "verticalBorderColor": "#CCDBFC",
+ "verticalBorderColorOpacity": 1,
+ "verticalBorderWidth": 1,
+ },
+ "icon": Object {
+ "fill": "#000000",
+ "margin": Object {
+ "left": 4,
+ "right": 4,
+ },
+ "size": 10,
+ },
+ "text": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": 700,
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "center",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ },
+ "dataCell": Object {
+ "bolderText": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": 700,
+ "linkTextFill": "#326EF4",
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "right",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ "cell": Object {
+ "backgroundColor": "#FFFFFF",
+ "backgroundColorOpacity": 1,
+ "crossBackgroundColor": "#F5F8FE",
+ "horizontalBorderColor": "#E0E9FD",
+ "horizontalBorderColorOpacity": 1,
+ "horizontalBorderWidth": 1,
+ "interactionState": Object {
+ "highlight": Object {
+ "backgroundColor": "#87B5FF",
+ "backgroundOpacity": 1,
+ },
+ "hover": Object {
+ "backgroundColor": "#E0E9FD",
+ "backgroundOpacity": 0.6,
+ },
+ "hoverFocus": Object {
+ "backgroundColor": "#E0E9FD",
+ "backgroundOpacity": 0.6,
+ "borderColor": "#000000",
+ "borderOpacity": 1,
+ "borderWidth": 1,
+ },
+ "prepareSelect": Object {
+ "borderColor": "#000000",
+ "borderOpacity": 1,
+ "borderWidth": 1,
+ },
+ "searchResult": Object {
+ "backgroundColor": "#F0F7FF",
+ "backgroundOpacity": 1,
+ },
+ "selected": Object {
+ "backgroundColor": "#E0E9FD",
+ "backgroundOpacity": 0.6,
+ },
+ "unselected": Object {
+ "backgroundOpacity": 0.3,
+ "opacity": 0.3,
+ "textOpacity": 0.3,
+ },
+ },
+ "padding": Object {
+ "bottom": 8,
+ "left": 8,
+ "right": 8,
+ "top": 8,
+ },
+ "verticalBorderColor": "#E0E9FD",
+ "verticalBorderColorOpacity": 1,
+ "verticalBorderWidth": 1,
+ },
+ "icon": Object {
+ "fill": "#000000",
+ "margin": Object {
+ "left": 4,
+ "right": 4,
+ },
+ "size": 10,
+ },
+ "miniChart": Object {
+ "bar": Object {
+ "fill": "#326EF4",
+ "intervalPadding": 4,
+ "opacity": 1,
+ },
+ "bullet": Object {
+ "backgroundColor": "#E9E9E9",
+ "comparativeMeasure": Object {
+ "fill": "#000000",
+ "height": 12,
+ "opacity": 0.25,
+ "width": 1,
+ },
+ "progressBar": Object {
+ "height": 10,
+ "innerHeight": 6,
+ "widthPercent": 0.6,
+ },
+ "rangeColors": Object {
+ "bad": "#FF4D4F",
+ "good": "#29A294",
+ "satisfactory": "#FAAD14",
+ },
+ },
+ "interval": Object {
+ "fill": "#326EF4",
+ "height": 12,
+ },
+ "line": Object {
+ "linkLine": Object {
+ "fill": "#326EF4",
+ "opacity": 0.6,
+ "size": 1.5,
+ },
+ "point": Object {
+ "fill": "#326EF4",
+ "opacity": 1,
+ "size": 2.2,
+ },
+ },
+ },
+ "text": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": "normal",
+ "linkTextFill": "#326EF4",
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "right",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ },
+ "mergedCell": Object {
+ "bolderText": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": 700,
+ "linkTextFill": "#326EF4",
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "right",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ "cell": Object {
+ "backgroundColor": "#FFFFFF",
+ "backgroundColorOpacity": 1,
+ "crossBackgroundColor": "#F5F8FE",
+ "horizontalBorderColor": "#E0E9FD",
+ "horizontalBorderColorOpacity": 1,
+ "horizontalBorderWidth": 1,
+ "interactionState": Object {
+ "highlight": Object {
+ "backgroundColor": "#87B5FF",
+ "backgroundOpacity": 1,
+ },
+ "hover": Object {
+ "backgroundColor": "#E0E9FD",
+ "backgroundOpacity": 0.6,
+ },
+ "hoverFocus": Object {
+ "backgroundColor": "#E0E9FD",
+ "backgroundOpacity": 0.6,
+ "borderColor": "#000000",
+ "borderOpacity": 1,
+ "borderWidth": 1,
+ },
+ "prepareSelect": Object {
+ "borderColor": "#000000",
+ "borderOpacity": 1,
+ "borderWidth": 1,
+ },
+ "searchResult": Object {
+ "backgroundColor": "#F0F7FF",
+ "backgroundOpacity": 1,
+ },
+ "selected": Object {
+ "backgroundColor": "#E0E9FD",
+ "backgroundOpacity": 0.6,
+ },
+ "unselected": Object {
+ "backgroundOpacity": 0.3,
+ "opacity": 0.3,
+ "textOpacity": 0.3,
+ },
+ },
+ "padding": Object {
+ "bottom": 8,
+ "left": 8,
+ "right": 8,
+ "top": 8,
+ },
+ "verticalBorderColor": "#E0E9FD",
+ "verticalBorderColorOpacity": 1,
+ "verticalBorderWidth": 1,
+ },
+ "icon": Object {
+ "fill": "#000000",
+ "margin": Object {
+ "left": 4,
+ "right": 4,
+ },
+ "size": 10,
+ },
+ "miniChart": Object {
+ "bar": Object {
+ "fill": "#326EF4",
+ "intervalPadding": 4,
+ "opacity": 1,
+ },
+ "bullet": Object {
+ "backgroundColor": "#E9E9E9",
+ "comparativeMeasure": Object {
+ "fill": "#000000",
+ "height": 12,
+ "opacity": 0.25,
+ "width": 1,
+ },
+ "progressBar": Object {
+ "height": 10,
+ "innerHeight": 6,
+ "widthPercent": 0.6,
+ },
+ "rangeColors": Object {
+ "bad": "#FF4D4F",
+ "good": "#29A294",
+ "satisfactory": "#FAAD14",
+ },
+ },
+ "interval": Object {
+ "fill": "#326EF4",
+ "height": 12,
+ },
+ "line": Object {
+ "linkLine": Object {
+ "fill": "#326EF4",
+ "opacity": 0.6,
+ "size": 1.5,
+ },
+ "point": Object {
+ "fill": "#326EF4",
+ "opacity": 1,
+ "size": 2.2,
+ },
+ },
+ },
+ "text": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": "normal",
+ "linkTextFill": "#326EF4",
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "right",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ },
+ "prepareSelectMask": Object {
+ "backgroundColor": "#234DAB",
+ "backgroundOpacity": 0.3,
+ },
+ "resizeArea": Object {
+ "background": "#326EF4",
+ "backgroundOpacity": 0,
+ "guideLineColor": "#326EF4",
+ "guideLineDash": Array [
+ 3,
+ 3,
+ ],
+ "guideLineDisableColor": "rgba(0,0,0,0.25)",
+ "interactionState": Object {
+ "hover": Object {
+ "backgroundColor": "#326EF4",
+ "backgroundOpacity": 1,
+ },
+ },
+ "minCellHeight": 40,
+ "minCellWidth": 42,
+ "size": 3,
+ },
+ "rowCell": Object {
+ "bolderText": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": 700,
+ "linkTextFill": "#326EF4",
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "center",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ "cell": Object {
+ "backgroundColor": "#F5F8FE",
+ "backgroundColorOpacity": 1,
+ "borderDash": Array [],
+ "horizontalBorderColor": "#E0E9FD",
+ "horizontalBorderColorOpacity": 1,
+ "horizontalBorderWidth": 1,
+ "interactionState": Object {
+ "highlight": Object {
+ "backgroundColor": "#87B5FF",
+ "backgroundOpacity": 1,
+ },
+ "hover": Object {
+ "backgroundColor": "#E0E9FD",
+ "backgroundOpacity": 0.6,
+ },
+ "prepareSelect": Object {
+ "borderColor": "#000000",
+ "borderOpacity": 1,
+ "borderWidth": 1,
+ },
+ "searchResult": Object {
+ "backgroundColor": "#F0F7FF",
+ "backgroundOpacity": 1,
+ },
+ "selected": Object {
+ "backgroundColor": "#E0E9FD",
+ "backgroundOpacity": 0.6,
+ },
+ "unselected": Object {
+ "backgroundOpacity": 0.3,
+ "opacity": 0.3,
+ "textOpacity": 0.3,
+ },
+ },
+ "padding": Object {
+ "bottom": 4,
+ "left": 8,
+ "right": 8,
+ "top": 4,
+ },
+ "verticalBorderColor": "#E0E9FD",
+ "verticalBorderColorOpacity": 1,
+ "verticalBorderWidth": 1,
+ },
+ "icon": Object {
+ "fill": "#000000",
+ "margin": Object {
+ "left": 4,
+ "right": 4,
+ },
+ "size": 10,
+ },
+ "measureText": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": "normal",
+ "linkTextFill": "#326EF4",
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "center",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ "seriesNumberWidth": 80,
+ "seriesText": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": "normal",
+ "linkTextFill": "#326EF4",
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "center",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ "text": Object {
+ "fill": "#000000",
+ "fontFamily": "Roboto, PingFangSC, Microsoft YaHei, Arial, sans-serif",
+ "fontSize": 12,
+ "fontWeight": "normal",
+ "linkTextFill": "#326EF4",
+ "maxLines": 1,
+ "opacity": 1,
+ "textAlign": "center",
+ "textBaseline": "middle",
+ "textOverflow": "ellipsis",
+ "wordWrap": true,
+ },
+ },
+ "scrollBar": Object {
+ "hoverSize": 8,
+ "lineCap": "round",
+ "size": 6,
+ "thumbColor": "rgba(0,0,0,0.15)",
+ "thumbHorizontalMinSize": 32,
+ "thumbHoverColor": "rgba(0,0,0,0.25)",
+ "thumbVerticalMinSize": 32,
+ "trackColor": "rgba(0,0,0,0.01)",
+ },
+ "splitLine": Object {
+ "borderDash": Array [],
+ "horizontalBorderColor": "#326EF4",
+ "horizontalBorderColorOpacity": 0.2,
+ "horizontalBorderWidth": 2,
+ "shadowColors": Object {
+ "left": "rgba(0,0,0,0.1)",
+ "right": "rgba(0,0,0,0)",
+ },
+ "shadowWidth": 8,
+ "showShadow": true,
+ "verticalBorderColor": "#326EF4",
"verticalBorderColorOpacity": 0.25,
"verticalBorderWidth": 2,
},
diff --git a/packages/s2-core/__tests__/spreadsheet/corner-spec.ts b/packages/s2-core/__tests__/spreadsheet/corner-spec.ts
index 0336cbc086..4acec56dde 100644
--- a/packages/s2-core/__tests__/spreadsheet/corner-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/corner-spec.ts
@@ -49,6 +49,7 @@ describe('PivotSheet Corner Tests', () => {
fields: {
...simpleDataConfig.fields,
columns: [],
+ values: ['price'],
},
});
s2.setOptions({
@@ -96,6 +97,15 @@ describe('PivotSheet Corner Tests', () => {
},
},
});
+
+ s2.setDataCfg({
+ ...simpleDataConfig,
+ fields: {
+ ...simpleDataConfig.fields,
+ values: ['price'],
+ },
+ });
+
await s2.render();
const cornerNodes = s2.facet.getCornerNodes();
@@ -315,11 +325,9 @@ describe('PivotSheet Corner Tests', () => {
expect(cornerNode.value).toEqual(cornerText);
- const cell = s2.facet.cornerHeader.children[0];
+ const cornerCell = s2.facet.getCornerCells()[0];
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- expect(cell.actualText).toEqual(cornerText);
+ expect(cornerCell.getActualText()).toEqual(cornerText);
});
test('should get custom corner extra text when hierarchy type is tree', async () => {
@@ -343,10 +351,8 @@ describe('PivotSheet Corner Tests', () => {
expect(cornerNode.value).toEqual(cornerExtraFieldText);
- const cell = s2.facet.cornerHeader.children[2];
+ const cornerCell = s2.facet.getCornerCells()[2];
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- expect(cell.actualText).toEqual(cornerExtraFieldText);
+ expect(cornerCell.getActualText()).toEqual(cornerExtraFieldText);
});
});
diff --git a/packages/s2-core/__tests__/spreadsheet/custom-cell-style-spec.ts b/packages/s2-core/__tests__/spreadsheet/custom-cell-style-spec.ts
index e8a04a4caf..fad262d910 100644
--- a/packages/s2-core/__tests__/spreadsheet/custom-cell-style-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/custom-cell-style-spec.ts
@@ -4,12 +4,13 @@ import {
getContainer,
} from 'tests/util/helpers';
import * as dataConfig from 'tests/data/mock-dataset.json';
+import * as simpleDataConfig from 'tests/data/simple-data.json';
import { customColSimpleColumns } from '../data/custom-table-col-fields';
import { EXTRA_FIELD, type S2DataConfig } from '@/common';
import type { ViewMeta } from '@/common/interface/basic';
import type { Node } from '@/facet/layout/node';
import type { S2Options } from '@/common/interface';
-import { TableSheet, type SpreadSheet } from '@/sheet-type';
+import { TableSheet, type SpreadSheet, PivotSheet } from '@/sheet-type';
describe('SpreadSheet Custom Cell Style Tests', () => {
let s2: SpreadSheet;
@@ -37,7 +38,7 @@ describe('SpreadSheet Custom Cell Style Tests', () => {
});
afterEach(() => {
- s2.destroy();
+ // s2.destroy();
});
test('should render default cell style', () => {
@@ -386,17 +387,27 @@ describe('SpreadSheet Custom Cell Style Tests', () => {
});
test('should get custom col cell style if measure column hidden', async () => {
- const sheet = createPivotSheet({
- ...s2Options,
- style: {
- colCell: {
- hideValue: true,
- widthByField: {
- 'root[&]笔': 100,
+ const sheet = new PivotSheet(
+ getContainer(),
+ {
+ ...simpleDataConfig,
+ fields: {
+ ...simpleDataConfig.fields,
+ values: ['price'],
+ },
+ },
+ {
+ ...s2Options,
+ style: {
+ colCell: {
+ hideValue: true,
+ widthByField: {
+ 'root[&]笔': 100,
+ },
},
},
},
- });
+ );
await sheet.render();
diff --git a/packages/s2-core/__tests__/spreadsheet/custom-grid-spec.ts b/packages/s2-core/__tests__/spreadsheet/custom-grid-spec.ts
index 5c4a40292f..05c7d307a8 100644
--- a/packages/s2-core/__tests__/spreadsheet/custom-grid-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/custom-grid-spec.ts
@@ -3,7 +3,6 @@ import { CustomGridData } from 'tests/data/data-custom-grid';
import { getContainer } from 'tests/util/helpers';
import { pick } from 'lodash';
import { waitForRender } from 'tests/util';
-import type { HeaderCell } from '../../src/cell/header-cell';
import { KEY_GROUP_COL_RESIZE_AREA } from '../../src/common/constant';
import { CustomGridPivotDataSet } from '../../src/data-set/custom-grid-pivot-data-set';
import {
@@ -186,9 +185,7 @@ describe('SpreadSheet Custom Grid Tests', () => {
);
test('should render custom format corner text', () => {
- const cornerCellLabels = (
- s2.facet.cornerHeader.children as HeaderCell[]
- ).map((cell: HeaderCell) => {
+ const cornerCellLabels = s2.facet.getCornerCells().map((cell) => {
const value = cell.getActualText();
const meta = cell.getMeta();
@@ -363,9 +360,7 @@ describe('SpreadSheet Custom Grid Tests', () => {
);
test('should render custom format corner text', () => {
- const cornerCellLabels = (
- s2.facet.cornerHeader.children as HeaderCell[]
- ).map((cell: HeaderCell) => {
+ const cornerCellLabels = s2.facet.getCornerCells().map((cell) => {
const value = cell.getActualText();
const meta = cell.getMeta();
diff --git a/packages/s2-core/__tests__/spreadsheet/custom-tree-spec.ts b/packages/s2-core/__tests__/spreadsheet/custom-tree-spec.ts
index 8c5ecdd755..854a168503 100644
--- a/packages/s2-core/__tests__/spreadsheet/custom-tree-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/custom-tree-spec.ts
@@ -27,11 +27,9 @@ const s2Options: S2Options = {
describe('SpreadSheet Custom Tree Tests', () => {
let s2: SpreadSheet;
- const getCornerCellLabels = () =>
- (s2.facet as any)
- .getCornerHeader()
- .getChildren()
- .map((cell: HeaderCell) => cell.getActualText());
+ const getCornerCellLabels = () => {
+ return s2.facet.getCornerCells().map((cell) => cell.getActualText());
+ };
const mapRowNodes = (spreadsheet: SpreadSheet) =>
spreadsheet.facet.getRowLeafNodes().map((node) => {
@@ -202,10 +200,7 @@ describe('SpreadSheet Custom Tree Tests', () => {
await s2.render();
- const cornerCellLabels = (s2.facet as any)
- .getCornerHeader()
- .getChildren()
- .map((cell: HeaderCell) => cell.getActualText());
+ const cornerCellLabels = getCornerCellLabels();
expect(cornerCellLabels).toEqual(['测试', '类型']);
});
diff --git a/packages/s2-core/__tests__/spreadsheet/empty-dataset-spec.ts b/packages/s2-core/__tests__/spreadsheet/empty-dataset-spec.ts
new file mode 100644
index 0000000000..9f70f1426c
--- /dev/null
+++ b/packages/s2-core/__tests__/spreadsheet/empty-dataset-spec.ts
@@ -0,0 +1,69 @@
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+import { getContainer } from 'tests/util/helpers';
+import type { S2DataConfig } from '../../src';
+import { PivotSheet, TableSheet } from '@/sheet-type';
+import type { S2Options } from '@/common/interface/s2Options';
+
+const s2Options: S2Options = {
+ width: 400,
+ height: 400,
+ hierarchyType: 'grid',
+};
+
+describe('Empty Dataset Structure Tests', () => {
+ test('should generate placeholder for pivot mode with single dimension', async () => {
+ const container = getContainer();
+
+ const s2DataCfg: S2DataConfig = {
+ fields: {
+ rows: ['province', 'city'],
+ columns: ['type'],
+ values: ['price'],
+ valueInCols: true,
+ },
+ data: [],
+ };
+ const s2 = new PivotSheet(container, s2DataCfg, s2Options);
+
+ await s2.render();
+
+ // @ts-ignore
+ expect(s2.facet.panelScrollGroupIndexes).toEqual([0, 0, 0, 0]);
+ });
+
+ test('should generate placeholder for pivot mode with two dimensions', async () => {
+ const container = getContainer();
+
+ const s2DataCfg: S2DataConfig = {
+ fields: {
+ rows: ['province', 'city'],
+ columns: ['type'],
+ values: ['price', 'cost'],
+ valueInCols: true,
+ },
+ data: [],
+ };
+
+ const s2 = new PivotSheet(container, s2DataCfg, s2Options);
+
+ await s2.render();
+ // @ts-ignore
+ expect(s2.facet.panelScrollGroupIndexes).toEqual([0, 1, 0, 0]);
+ });
+
+ test(`shouldn't generate placeholder for table mode`, async () => {
+ const container = getContainer();
+
+ const s2DataCfg: S2DataConfig = {
+ fields: {
+ columns: ['province', 'city', 'type', 'price', 'cost'],
+ },
+ data: [],
+ };
+ const s2 = new TableSheet(container, s2DataCfg, s2Options);
+
+ await s2.render();
+ // @ts-ignore
+ expect(s2.facet.panelScrollGroupIndexes).toEqual([]);
+ });
+});
diff --git a/packages/s2-core/__tests__/spreadsheet/empty-string-values-spec.ts b/packages/s2-core/__tests__/spreadsheet/empty-string-values-spec.ts
new file mode 100644
index 0000000000..ea9933c33e
--- /dev/null
+++ b/packages/s2-core/__tests__/spreadsheet/empty-string-values-spec.ts
@@ -0,0 +1,124 @@
+import { getContainer } from 'tests/util/helpers';
+import { LayoutWidthType, type S2DataConfig, type S2Options } from '@/common';
+import { PivotSheet, SpreadSheet } from '@/sheet-type';
+
+const s2Options: S2Options = {
+ debug: true,
+ width: 600,
+ height: 400,
+ hierarchyType: 'grid',
+ style: {
+ layoutWidthType: LayoutWidthType.Adaptive,
+ dataCell: {
+ height: 30,
+ },
+ },
+};
+
+const testDataCfg: S2DataConfig = {
+ meta: [
+ {
+ field: 'first',
+ name: '一级维度',
+ },
+ {
+ field: 'second',
+ name: '二级维度',
+ },
+ {
+ field: 'number',
+ name: '数值',
+ },
+ ],
+ fields: {
+ rows: ['first', 'second'],
+ columns: [],
+ values: ['number'],
+ valueInCols: true,
+ },
+ data: [
+ {
+ first: '',
+ second: '维值1',
+ number: 100,
+ },
+ {
+ first: '',
+ second: '维值2',
+ number: 200,
+ },
+ {
+ first: null,
+ second: '维值3',
+ number: 300,
+ },
+ {
+ first: null,
+ second: '维值4',
+ number: 400,
+ },
+ {
+ first: '非空维度',
+ second: '维值5',
+ number: 500,
+ },
+ {
+ first: '非空维度',
+ second: '维值6',
+ number: 600,
+ },
+ ],
+};
+
+describe('Empty String Values Tests', () => {
+ let s2: SpreadSheet;
+
+ beforeEach(() => {
+ s2 = new PivotSheet(getContainer(), testDataCfg, s2Options);
+ s2.render();
+ });
+
+ test('should get correctly first dimension values', () => {
+ const values = s2.dataSet.getDimensionValues('first');
+
+ expect(values).toEqual(['', 'null', '非空维度']);
+ });
+
+ test('should get correctly second dimension values', () => {
+ const values = s2.dataSet.getDimensionValues('second');
+
+ expect(values).toEqual([
+ '维值1',
+ '维值2',
+ '维值3',
+ '维值4',
+ '维值5',
+ '维值6',
+ ]);
+ });
+
+ test('should get correctly second dimension values by specific query', () => {
+ let values = s2.dataSet.getDimensionValues('second', { first: '' });
+
+ expect(values).toEqual(['维值1', '维值2']);
+
+ values = s2.dataSet.getDimensionValues('second', { first: 'null' });
+ expect(values).toEqual(['维值3', '维值4']);
+
+ values = s2.dataSet.getDimensionValues('second', { first: '非空维度' });
+ expect(values).toEqual(['维值5', '维值6']);
+ });
+
+ test('should get correctly layout result', () => {
+ const nodes = s2.facet.getLayoutResult().rowLeafNodes;
+
+ expect(nodes.map((node) => node.id)).toEqual([
+ 'root[&][&]维值1',
+ 'root[&][&]维值2',
+ 'root[&]null[&]维值3',
+ 'root[&]null[&]维值4',
+ 'root[&]非空维度[&]维值5',
+ 'root[&]非空维度[&]维值6',
+ ]);
+ });
+});
diff --git a/packages/s2-core/__tests__/spreadsheet/header-action-icons-spec.ts b/packages/s2-core/__tests__/spreadsheet/header-action-icons-spec.ts
index 993e89ef0d..4a9390d360 100644
--- a/packages/s2-core/__tests__/spreadsheet/header-action-icons-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/header-action-icons-spec.ts
@@ -183,21 +183,21 @@ describe('HeaderActionIcons Tests', () => {
],
Array [
Object {
- "x": 158,
+ "x": 158.5,
"y": 9.5,
},
Object {
- "x": 200,
+ "x": 200.5,
"y": 9.5,
},
],
Array [
Object {
- "x": 158,
+ "x": 158.5,
"y": 39.5,
},
Object {
- "x": 200,
+ "x": 200.5,
"y": 39.5,
},
],
@@ -281,13 +281,13 @@ describe('HeaderActionIcons Tests', () => {
},
Object {
"cfg": Object {
- "x": 186,
+ "x": 186.5,
"y": 9.5,
},
},
Object {
"cfg": Object {
- "x": 186,
+ "x": 186.5,
"y": 39.5,
},
},
diff --git a/packages/s2-core/__tests__/spreadsheet/hidden-columns-spec.ts b/packages/s2-core/__tests__/spreadsheet/hidden-columns-spec.ts
index ac6c7760e1..19cc8de525 100644
--- a/packages/s2-core/__tests__/spreadsheet/hidden-columns-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/hidden-columns-spec.ts
@@ -3,11 +3,11 @@ import * as mockDataConfig from 'tests/data/mock-dataset.json';
import * as mockPivotDataConfig from 'tests/data/simple-data.json';
import * as mockTableDataConfig from 'tests/data/simple-table-data.json';
import { waitForRender } from 'tests/util';
-import { getContainer } from 'tests/util/helpers';
+import { createPivotSheet, getContainer } from 'tests/util/helpers';
import { customColGridSimpleFields } from '../data/custom-grid-simple-fields';
import { customColMultipleColumns } from '../data/custom-table-col-fields';
import { PivotSheet, TableSheet } from '@/sheet-type';
-import type { HiddenColumnsInfo, S2Options } from '@/common';
+import type { HiddenColumnsInfo, S2DataConfig, S2Options } from '@/common';
const s2Options: S2Options = {
width: 400,
@@ -213,7 +213,7 @@ describe('SpreadSheet Hidden Columns Tests', () => {
let pivotSheet: PivotSheet;
- const pivotDataCfg = {
+ const pivotDataCfg: S2DataConfig = {
...mockPivotDataConfig,
fields: {
rows: ['province'],
@@ -229,7 +229,7 @@ describe('SpreadSheet Hidden Columns Tests', () => {
});
afterEach(() => {
- pivotSheet.destroy();
+ // pivotSheet.destroy();
});
test('should get init column node', () => {
@@ -297,7 +297,7 @@ describe('SpreadSheet Hidden Columns Tests', () => {
);
});
- test('should not rerender after hidden empty column fields if disable force render', () => {
+ test('should not rerender after hidden empty column fields if disable force render', async () => {
const defaultHiddenColumnsDetail = [
null,
] as unknown as HiddenColumnsInfo[];
@@ -308,7 +308,7 @@ describe('SpreadSheet Hidden Columns Tests', () => {
.spyOn(pivotSheet, 'render')
.mockImplementationOnce(async () => {});
- pivotSheet.interaction.hideColumns([], false);
+ await pivotSheet.interaction.hideColumns([], false);
const hiddenColumnsDetail = pivotSheet.store.get('hiddenColumnsDetail');
@@ -316,7 +316,7 @@ describe('SpreadSheet Hidden Columns Tests', () => {
expect(hiddenColumnsDetail).toEqual(defaultHiddenColumnsDetail);
});
- test('should rerender after hidden empty column fields if enable force render', () => {
+ test('should rerender after hidden empty column fields if enable force render', async () => {
const defaultHiddenColumnsDetail = [
null,
] as unknown as HiddenColumnsInfo[];
@@ -327,7 +327,7 @@ describe('SpreadSheet Hidden Columns Tests', () => {
.spyOn(pivotSheet, 'render')
.mockImplementationOnce(async () => {});
- pivotSheet.interaction.hideColumns([], true);
+ await pivotSheet.interaction.hideColumns([], true);
const hiddenColumnsDetail = pivotSheet.store.get('hiddenColumnsDetail');
@@ -402,13 +402,8 @@ describe('SpreadSheet Hidden Columns Tests', () => {
.getColNodes()
.find((node) => node.isGrandTotals)!;
- const rootNode = pivotSheet.facet
- .getColNodes()
- .find((node) => node.id === 'root[&]笔')!;
-
- const parentNode = pivotSheet.facet
- .getColNodes()
- .find((node) => node.id === 'root[&]笔[&]义乌')!;
+ const rootNode = pivotSheet.facet.getColNodeById('root[&]笔')!;
+ const parentNode = pivotSheet.facet.getColNodeById('root[&]笔[&]义乌')!;
const hiddenColumnsInfo = pivotSheet.store.get('hiddenColumnsDetail')[0];
@@ -420,6 +415,67 @@ describe('SpreadSheet Hidden Columns Tests', () => {
expect(parentNode.hiddenChildNodeInfo).toEqual(hiddenColumnsInfo);
});
+ // https://github.com/antvis/S2/issues/2355
+ test('should render correctly x and width after hide columns when there is only one value for the higher-level dimension.', async () => {
+ const nodeId = 'root[&]笔[&]义乌[&]price';
+
+ pivotSheet.setOptions({
+ style: {
+ colCell: {
+ width: 100,
+ },
+ },
+ });
+ const data = pivotSheet.dataCfg.data.map((i) => ({ ...i, cost: 0 }));
+
+ pivotSheet.setDataCfg({
+ data,
+ fields: {
+ values: ['cost', 'price'],
+ },
+ });
+ await pivotSheet.render();
+
+ await pivotSheet.interaction.hideColumns([nodeId]);
+
+ const rootNode = pivotSheet.facet.getColNodeById('root[&]笔');
+
+ expect(rootNode!.width).toEqual(300);
+ expect(rootNode!.x).toEqual(0);
+ });
+
+ // https://github.com/antvis/S2/issues/2194
+ test('should render correctly when always hidden last column', async () => {
+ const sheet = createPivotSheet(
+ {
+ interaction: {
+ hiddenColumnFields: [],
+ },
+ },
+ { useSimpleData: false },
+ );
+
+ await sheet.render();
+
+ // 模拟一列一列的手动隐藏最后一列
+ const colIds = [
+ 'root[&]办公用品[&]纸张[&]数量',
+ 'root[&]办公用品[&]笔[&]数量',
+ 'root[&]家具[&]沙发[&]数量',
+ ];
+
+ await Promise.all(
+ colIds.map(async (field) => {
+ await sheet.interaction.hideColumns([field]);
+ }),
+ );
+
+ const leafNodes = sheet.facet.getColLeafNodes();
+
+ expect(leafNodes).toHaveLength(1);
+ expect(leafNodes[0].id).toEqual('root[&]家具[&]桌子[&]数量');
+ });
+
test('should hide columns for multiple columns', async () => {
const hiddenColumns = [
'root[&]自定义节点 a-1[&]自定义节点 a-1-1[&]指标1',
@@ -512,9 +568,7 @@ describe('SpreadSheet Hidden Columns Tests', () => {
await sheet.interaction.hideColumns([id]);
});
- const totalsSiblingNode = sheet.facet
- .getColNodes()
- .find((node) => node.id === 'root[&]家具')!;
+ const totalsSiblingNode = sheet.facet.getColNodeById('root[&]家具')!;
expect(totalsSiblingNode.x).toEqual(x);
expect(totalsSiblingNode.width).toEqual(width);
@@ -526,8 +580,8 @@ describe('SpreadSheet Hidden Columns Tests', () => {
test('should hide measure node', async () => {
const nodeIds = [
- 'root[&]家具[&]桌子[&]number',
- 'root[&]办公用品[&]笔[&]number',
+ 'root[&]家具[&]桌子[&]数量',
+ 'root[&]办公用品[&]笔[&]数量',
];
await waitForRender(sheet, async () => {
@@ -545,8 +599,8 @@ describe('SpreadSheet Hidden Columns Tests', () => {
const nodeIds = [
'root[&]总计',
'root[&]家具[&]小计',
- 'root[&]家具[&]桌子[&]number',
- 'root[&]办公用品[&]笔[&]number',
+ 'root[&]家具[&]桌子[&]数量',
+ 'root[&]办公用品[&]笔[&]数量',
];
await waitForRender(sheet, async () => {
@@ -564,39 +618,12 @@ describe('SpreadSheet Hidden Columns Tests', () => {
expect(colsHierarchy.sampleNodeForLastLevel?.height).toStrictEqual(30);
expect(colsHierarchy.sampleNodeForLastLevel?.y).toStrictEqual(60);
expect(colsHierarchy.height).toStrictEqual(90);
- expect(colCornerNodesMeta).toMatchInlineSnapshot(`
- Array [
- Object {
- "height": 30,
- "width": 119,
- "x": 0,
- "y": 60,
- },
- Object {
- "height": 30,
- "width": 119,
- "x": 119,
- "y": 60,
- },
- Object {
- "height": 30,
- "width": 238,
- "x": 0,
- "y": 0,
- },
- Object {
- "height": 30,
- "width": 238,
- "x": 0,
- "y": 30,
- },
- ]
- `);
+ expect(colCornerNodesMeta).toMatchSnapshot();
});
// https://github.com/antvis/S2/issues/1721
- test('should hide grand totals node1', async () => {
- const nodeId = 'root[&]总计[&]sub_type';
+ test('should hide grand totals node', async () => {
+ const nodeId = 'root[&]总计[&]子类别';
sheet.setDataCfg({
...mockDataConfig,
@@ -607,16 +634,37 @@ describe('SpreadSheet Hidden Columns Tests', () => {
valueInCols: true,
},
});
+
await sheet.render();
- await waitForRender(sheet, async () => {
- await sheet.interaction.hideColumns([nodeId]);
- });
+ await sheet.interaction.hideColumns([nodeId]);
const leafNodes = sheet.facet.getColLeafNodes();
expect(leafNodes.some((node) => node.id === nodeId)).toBeFalsy();
expect(leafNodes).toHaveLength(5);
});
+
+ test.each(['grid', 'tree'] as S2Options['hierarchyType'][])(
+ 'hiding the column totals should not hide the row totals for %s mode',
+ async (hierarchyType) => {
+ sheet.setOptions({ hierarchyType });
+ await sheet.render();
+
+ const nodeId = 'root[&]总计';
+ const preRowNodes = sheet.facet.getRowNodes();
+ const preColumnNodes = sheet.facet.getColNodes();
+
+ await waitForRender(sheet, async () => {
+ await sheet.interaction.hideColumns([nodeId]);
+ });
+
+ expect(sheet.facet.getRowNodes()[0].id).toBe(nodeId);
+ expect(sheet.facet.getRowNodes().length).toBe(preRowNodes.length);
+ expect(sheet.facet.getColNodes().length).toBe(
+ preColumnNodes.length - 1,
+ );
+ },
+ );
});
});
});
diff --git a/packages/s2-core/__tests__/spreadsheet/interaction-brush-selection-scroll-spec.ts b/packages/s2-core/__tests__/spreadsheet/interaction-brush-selection-scroll-spec.ts
index a1a8739ac9..a579f830b5 100644
--- a/packages/s2-core/__tests__/spreadsheet/interaction-brush-selection-scroll-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/interaction-brush-selection-scroll-spec.ts
@@ -15,6 +15,7 @@ import {
TableSheet,
SpreadSheet,
type S2CellType,
+ LayoutWidthType,
} from '@/index';
const data = getMockData(
@@ -55,7 +56,7 @@ const options: S2Options = {
showSeriesNumber: true,
placeholder: '',
style: {
- layoutWidthType: 'compact',
+ layoutWidthType: LayoutWidthType.Compact,
dataCell: {
height: 32,
},
diff --git a/packages/s2-core/__tests__/spreadsheet/miss-dimension-values-spec.ts b/packages/s2-core/__tests__/spreadsheet/miss-dimension-values-spec.ts
new file mode 100644
index 0000000000..7fd84b7ba9
--- /dev/null
+++ b/packages/s2-core/__tests__/spreadsheet/miss-dimension-values-spec.ts
@@ -0,0 +1,269 @@
+import { getContainer } from 'tests/util/helpers';
+import {
+ EMPTY_FIELD_VALUE,
+ LayoutWidthType,
+ ORIGIN_FIELD,
+ type S2DataConfig,
+ type S2Options,
+} from '@/common';
+import { PivotSheet, SpreadSheet } from '@/sheet-type';
+
+const s2Options: S2Options = {
+ debug: true,
+ width: 600,
+ height: 400,
+ hierarchyType: 'grid',
+ totals: {
+ row: {
+ showGrandTotals: false,
+ showSubTotals: {
+ always: false,
+ },
+ reverseGrandTotalsLayout: false,
+ reverseSubTotalsLayout: false,
+ subTotalsDimensions: ['first', 'second'],
+ },
+ col: {
+ showGrandTotals: false,
+ showSubTotals: false,
+ reverseGrandTotalsLayout: false,
+ reverseSubTotalsLayout: false,
+ subTotalsDimensions: [],
+ },
+ },
+ style: {
+ layoutWidthType: LayoutWidthType.Adaptive,
+ dataCell: {
+ height: 30,
+ },
+ },
+ showDefaultHeaderActionIcon: false,
+};
+
+const testDataCfg: S2DataConfig = {
+ meta: [
+ {
+ field: 'first',
+ name: '一级维度',
+ },
+ {
+ field: 'second',
+ name: '二级维度',
+ },
+ {
+ field: 'third',
+ name: '三级维度',
+ },
+ {
+ field: 'number',
+ name: '数值',
+ },
+ ],
+ fields: {
+ rows: ['first', 'second', 'third'],
+ columns: [],
+ values: ['number'],
+ valueInCols: true,
+ },
+ data: [
+ {
+ first: '总计',
+ number: 1732771,
+ },
+ {
+ first: '维值-1',
+ second: '维值-2',
+ third: '维度-3',
+ number: 172245,
+ },
+ {
+ first: '维值-1',
+ second: '维值-2',
+ third: '维度-3',
+ number: 12222,
+ },
+ {
+ first: '维值-1',
+ second: '维值-3',
+ third: '维值-3',
+ number: 11111,
+ },
+ {
+ first: '维值-1',
+ second: '维值-3',
+ third: '维度-3',
+ number: 11111,
+ },
+ {
+ first: '维值-1',
+ number: 456,
+ },
+ {
+ first: '测试-1',
+ second: '测试-2',
+ third: '维度-3',
+ number: 12,
+ },
+ {
+ first: '测试-1',
+ second: '测试-2',
+ third: '维度-3',
+ number: 4444567,
+ },
+ {
+ first: '测试-1',
+ second: '测试-3',
+ number: 111233,
+ },
+ {
+ first: '测试-1',
+ second: '测试-3',
+ number: 785222,
+ },
+ {
+ first: '测试-1',
+ second: '测试-4',
+ third: '维度-3',
+ number: 6455644,
+ },
+ {
+ first: '测试-1',
+ second: '测试-4',
+ number: 289898,
+ },
+ {
+ first: '测试-1',
+ second: '测试-5',
+ number: 2222,
+ },
+ {
+ first: '测试-1',
+ second: '测试-5',
+ third: '维度-3',
+ number: 1111,
+ },
+ {
+ first: '测试-1',
+ number: 125555,
+ },
+ {
+ first: '测试-6',
+ second: '测试-x',
+ number: 409090,
+ },
+ {
+ first: '测试-6',
+ second: '测试-x',
+ number: 111111,
+ },
+ {
+ first: '测试-6',
+ second: '测试-7',
+ number: 5555,
+ },
+ {
+ first: '测试-6',
+ second: '测试-7',
+ number: 67878,
+ },
+ {
+ first: '测试-6',
+ second: '测试-8',
+ number: 53445.464,
+ },
+ {
+ first: '测试-6',
+ second: '测试-8',
+ number: 456.464,
+ },
+ {
+ first: '测试-6',
+ number: 123.416,
+ },
+ ],
+};
+
+describe('Miss Dimension Values Tests', () => {
+ let s2: SpreadSheet;
+
+ beforeEach(async () => {
+ s2 = new PivotSheet(getContainer(), testDataCfg, s2Options);
+ await s2.render();
+ });
+
+ test('should get correctly empty dimension values', () => {
+ const emptyDimensionValueNode = s2.facet.getRowNodes()[0].children[0];
+
+ expect(emptyDimensionValueNode.value).toEqual(EMPTY_FIELD_VALUE);
+ expect(emptyDimensionValueNode.id).toEqual(
+ `root[&]总计[&]${EMPTY_FIELD_VALUE}`,
+ );
+ expect(emptyDimensionValueNode.belongsCell!.getActualText()).toEqual('-');
+ });
+
+ test('should get correctly empty dimension values and use custom placeholder text', async () => {
+ const placeholder = '*';
+
+ s2.setOptions({
+ placeholder,
+ });
+
+ await s2.render(false);
+
+ const emptyDimensionValueNode = s2.facet.getRowNodes()[0].children[0];
+
+ expect(emptyDimensionValueNode.belongsCell!.getActualText()).toEqual(
+ placeholder,
+ );
+ });
+
+ test('should generate correct query for empty node', () => {
+ const emptyDimensionValueNode1 = s2.facet.getRowNodes()[0];
+
+ expect(emptyDimensionValueNode1.query).toEqual({
+ first: '总计',
+ });
+
+ const emptyDimensionValueNode2 = s2.facet.getRowNodes()[1];
+
+ expect(emptyDimensionValueNode2.query).toEqual({
+ first: '总计',
+ });
+ });
+
+ test('should get correctly dimension data and ignore empty dimension value', () => {
+ const emptyDimensionValueNode = s2.facet.getRowNodes()[0].children[0];
+
+ const data = s2.dataSet.getCellMultiData({
+ query: emptyDimensionValueNode.query!,
+ });
+ const dimensionValues = s2.dataSet.getDimensionValues(
+ emptyDimensionValueNode.field,
+ );
+ const emptyDimensionDataCell = s2.facet.getDataCells()[0];
+
+ expect(emptyDimensionValueNode.query).toEqual(
+ emptyDimensionValueNode.parent!.query,
+ );
+ expect(emptyDimensionDataCell.getMeta().fieldValue).toEqual(1732771);
+ expect(data[0][ORIGIN_FIELD]).toMatchInlineSnapshot(`
+ Object {
+ "first": "总计",
+ "number": 1732771,
+ }
+ `);
+ expect(dimensionValues).toMatchInlineSnapshot(`
+ Array [
+ "维值-2",
+ "维值-3",
+ "测试-2",
+ "测试-3",
+ "测试-4",
+ "测试-5",
+ "测试-x",
+ "测试-7",
+ "测试-8",
+ ]
+ `);
+ });
+});
diff --git a/packages/s2-core/__tests__/spreadsheet/row-link-spec.ts b/packages/s2-core/__tests__/spreadsheet/row-link-spec.ts
index 41d7d61a62..18dd45ec8e 100644
--- a/packages/s2-core/__tests__/spreadsheet/row-link-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/row-link-spec.ts
@@ -1,7 +1,7 @@
import { getContainer } from 'tests/util/helpers';
import { noop } from 'lodash';
import { PivotSheet } from '@/sheet-type';
-import { S2Event, type S2Options } from '@/common';
+import { S2Event, type S2DataConfig, type S2Options } from '@/common';
const s2Options: S2Options = {
width: 400,
@@ -19,7 +19,7 @@ const s2Options: S2Options = {
},
};
-const s2DataCfg = {
+const s2DataCfg: S2DataConfig = {
fields: {
rows: ['province', 'city'],
columns: ['type'],
@@ -32,14 +32,7 @@ const s2DataCfg = {
city: '义乌1',
type: '笔',
price: 1,
- cost: 9,
- },
- {
- province: '浙江',
- city: '义乌1',
- type: '笔',
- price: 10,
- cost: 99,
+ cost: 2,
},
{
province: '浙江',
@@ -76,7 +69,7 @@ describe('Row Text Link Tests', () => {
let s2: PivotSheet;
const linkFieldJump = jest.fn();
- beforeAll(async () => {
+ beforeEach(async () => {
container = getContainer();
s2 = new PivotSheet(container, s2DataCfg, s2Options);
await s2.render();
@@ -122,15 +115,15 @@ describe('Row Text Link Tests', () => {
},
} as any);
- expect(linkFieldJump).toHaveBeenCalledWith({
+ expect(linkFieldJump).toHaveBeenLastCalledWith({
field: 'city',
cellData: rowNode,
record: {
province: '浙江',
city: '义乌1',
type: '笔',
- price: 10,
- cost: 99,
+ price: 1,
+ cost: 2,
rowIndex: 1,
},
});
diff --git a/packages/s2-core/__tests__/spreadsheet/scroll-spec.ts b/packages/s2-core/__tests__/spreadsheet/scroll-spec.ts
index 34a09bb472..33439bc201 100644
--- a/packages/s2-core/__tests__/spreadsheet/scroll-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/scroll-spec.ts
@@ -1,7 +1,8 @@
/* eslint-disable jest/no-conditional-expect */
import * as mockDataConfig from 'tests/data/simple-data.json';
import { createMockCellInfo, getContainer, sleep } from 'tests/util/helpers';
-import { ScrollType } from '../../src/ui/scrollbar';
+import { get } from 'lodash';
+import { ScrollBar, ScrollType } from '../../src/ui/scrollbar';
import type { CellScrollPosition } from './../../src/common/interface/scroll';
import { PivotSheet, SpreadSheet } from '@/sheet-type';
import type {
@@ -12,6 +13,7 @@ import type {
import {
InteractionStateName,
InterceptType,
+ LayoutWidthType,
OriginEventType,
S2Event,
ScrollbarPositionType,
@@ -381,6 +383,62 @@ describe('Scroll Tests', () => {
},
);
+ // https://github.com/antvis/S2/issues/2222
+ test.each([
+ {
+ type: 'horizontal',
+ offset: {
+ scrollX: 20,
+ scrollY: 0,
+ },
+ },
+ {
+ type: 'vertical',
+ offset: {
+ scrollX: 0,
+ scrollY: 20,
+ },
+ },
+ ])(
+ 'should trigger hover cells when hover cells after scroll by %o',
+ async ({ offset }) => {
+ s2.setOptions({
+ interaction: {
+ hoverAfterScroll: true,
+ },
+ });
+
+ s2.facet.cornerBBox.maxY = -9999;
+ s2.facet.panelBBox.minX = -9999;
+ s2.facet.panelBBox.minY = -9999;
+
+ const bbox = s2.getCanvasElement().getBoundingClientRect();
+ const mousemoveEvent = new MouseEvent(OriginEventType.POINTER_MOVE, {
+ clientX: bbox.left + 100,
+ clientY: bbox.top + 100,
+ });
+
+ canvas.dispatchEvent(mousemoveEvent);
+
+ s2.container.emit = jest.fn();
+
+ const wheelEvent = new WheelEvent('wheel', {
+ deltaX: offset.scrollX,
+ deltaY: offset.scrollY,
+ });
+
+ canvas.dispatchEvent(wheelEvent);
+
+ // wait requestAnimationFrame and debounce
+ await sleep(1000);
+
+ expect(s2.container.emit).toHaveBeenCalledWith(
+ OriginEventType.POINTER_MOVE,
+ expect.any(Object),
+ );
+ },
+ );
+
test('should not trigger scroll event on passive renders', async () => {
const sheet = new PivotSheet(getContainer(), mockDataConfig, {
...s2Options,
@@ -403,7 +461,7 @@ describe('Scroll Tests', () => {
scrollbarPosition: ScrollbarPositionType.CONTENT,
},
style: {
- layoutWidthType: 'compact',
+ layoutWidthType: LayoutWidthType.Compact,
},
});
s2.changeSheetSize(100, 1000); // 横向滚动条
@@ -414,7 +472,8 @@ describe('Scroll Tests', () => {
s2.changeSheetSize(1000, 150); // 纵向滚动条
await s2.render(false);
- expect(s2.facet.vScrollBar.getBBox().x).toBe(195);
+
+ expect(Math.floor(s2.facet.vScrollBar.getBBox().x)).toEqual(195);
s2.setOptions({
interaction: {
@@ -455,11 +514,11 @@ describe('Scroll Tests', () => {
const scrollBar = s2.facet[name];
- const positon = scrollBar['getCoordinatesWithBBoxExtraPadding']();
+ const position = scrollBar['getCoordinatesWithBBoxExtraPadding']();
expect(
Math.round(scrollBar.thumbShape.getBBox()[key] as number),
- ).toStrictEqual(Math.round(positon.end - positon.start));
+ ).toStrictEqual(Math.round(position.end - position.start));
},
);
@@ -492,7 +551,7 @@ describe('Scroll Tests', () => {
rowHeader: true,
},
style: {
- layoutWidthType: 'compact',
+ layoutWidthType: LayoutWidthType.Compact,
rowCell: {
width: 200,
},
@@ -639,13 +698,13 @@ describe('Scroll Tests', () => {
).toBeFalsy();
});
- test('should scroll horizontally when shift key is held', async () => {
+ test('should scroll horizontally when shift key is held on Windows', async () => {
s2.setOptions({
frozen: {
rowHeader: true,
},
style: {
- layoutWidthType: 'compact',
+ layoutWidthType: LayoutWidthType.Compact,
rowCell: {
width: 200,
},
@@ -676,11 +735,39 @@ describe('Scroll Tests', () => {
shiftKey: true,
});
+ Object.defineProperty(window.navigator, 'userAgent', {
+ value: 'Windows',
+ configurable: true,
+ writable: true,
+ });
+
canvas.dispatchEvent(wheelEvent);
+ await sleep(200);
+ expect(onScroll).toHaveBeenCalled();
+ });
- await sleep(1000);
+ test('should not scroll horizontally when shift key is held on macOS', async () => {
+ const onScroll = jest.fn((...args) => {
+ expect(args[0].rowHeaderScrollX).toBeGreaterThan(0);
+ expect(args[0].scrollX).toBe(0);
+ expect(args[0].scrollY).toBe(0);
+ });
- expect(onScroll).toHaveBeenCalled();
+ const wheelEvent = new WheelEvent('wheel', {
+ deltaX: 0,
+ deltaY: 20,
+ shiftKey: true,
+ });
+
+ Object.defineProperty(window.navigator, 'userAgent', {
+ value: 'Mac OS',
+ configurable: true,
+ writable: true,
+ });
+
+ canvas.dispatchEvent(wheelEvent);
+ await sleep(200);
+ expect(onScroll).not.toHaveBeenCalled();
});
it('should not change init body overscrollBehavior style when render and destroyed', async () => {
@@ -766,4 +853,92 @@ describe('Scroll Tests', () => {
expect(errorSpy).not.toHaveBeenCalled();
});
+
+ // https://github.com/antvis/S2/issues/2316
+ test('should not throw infinite error if spreadsheet is unmounted during scrolling', async () => {
+ s2.setOptions({
+ style: {
+ rowCell: {
+ width: 200,
+ },
+ dataCell: {
+ width: 30,
+ },
+ },
+ });
+
+ await s2.render(false);
+
+ const errorSpy = jest
+ .spyOn(console, 'error')
+ .mockImplementationOnce(() => {});
+
+ // 滚动时 unmount 表格实例
+ s2.facet.scrollWithAnimation(
+ {
+ offsetX: {
+ value: 10,
+ animate: true,
+ },
+ offsetY: {
+ value: 10,
+ animate: true,
+ },
+ },
+ 200,
+ );
+ s2.destroy();
+
+ await sleep(500);
+
+ expect(errorSpy).toHaveBeenCalledTimes(0);
+ });
+
+ // https://github.com/antvis/S2/issues/2376
+ test.each(['hScrollBar', 'hRowScrollBar'])(
+ 'should not reset interaction state after %s scrollbar thumb or track clicked',
+ (scrollbarName) => {
+ const isMatchElementSpy = jest
+ .spyOn(s2.interaction.eventController, 'isMatchElement')
+ .mockImplementation(() => true);
+
+ const reset = jest.fn();
+
+ const scrollbar = get(s2.facet, scrollbarName) as ScrollBar;
+ const colCell = s2.facet.getColLeafCells()[0]!;
+
+ s2.on(S2Event.GLOBAL_RESET, reset);
+ s2.interaction.selectHeaderCell({
+ cell: colCell,
+ });
+
+ expect(s2.interaction.isSelectedState()).toBeTruthy();
+
+ const { maxX, maxY } = s2.facet?.panelBBox || {};
+ const { x, y } = canvas.getBoundingClientRect() || {};
+
+ // 滚动条
+ window.dispatchEvent(
+ new MouseEvent('click', {
+ clientX: x + scrollbar.position.x,
+ // 在滚动条内点击
+ clientY: y + scrollbar.position.y + scrollbar!.theme!.size! - 2,
+ } as MouseEventInit),
+ );
+
+ // 滑动轨道
+ window.dispatchEvent(
+ new MouseEvent('click', {
+ // 右下角滑道点击
+ clientX: x + maxX - 2,
+ clientY: y + maxY + 2,
+ } as MouseEventInit),
+ );
+
+ expect(s2.interaction.isSelectedState()).toBeTruthy();
+ expect(reset).not.toHaveBeenCalled();
+
+ isMatchElementSpy.mockClear();
+ },
+ );
});
diff --git a/packages/s2-core/__tests__/spreadsheet/sort-by-order-spec.ts b/packages/s2-core/__tests__/spreadsheet/sort-by-order-spec.ts
index 33a238ffdc..ab07de4ac3 100644
--- a/packages/s2-core/__tests__/spreadsheet/sort-by-order-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/sort-by-order-spec.ts
@@ -73,12 +73,12 @@ describe('Manual Sort Tests', () => {
},
{
sortFieldId: 'type2',
- sortBy: ['整体访问', '小程序访问', '支付宝访问'],
+ sortBy: ['支付宝访问', '整体访问', '小程序访问'],
},
],
};
- beforeAll(async () => {
+ beforeEach(async () => {
const container = getContainer();
s2 = new PivotSheet(container, mockDataCfg, s2Options);
@@ -94,12 +94,12 @@ describe('Manual Sort Tests', () => {
s2.dataSet.getDimensionValues('type2', {
type1: '整体访问',
}),
- ).toEqual(['整体访问', '小程序访问', '支付宝访问']);
+ ).toEqual(['支付宝访问', '整体访问', '小程序访问']);
expect(
s2.dataSet.getDimensionValues('type2', {
type1: '小程序访问',
}),
- ).toEqual(['小程序访问', '整体访问', '支付宝访问']);
+ ).toEqual(['支付宝访问', '整体访问', '小程序访问']);
expect(
s2.dataSet.getDimensionValues('type2', {
type1: '支付宝访问',
diff --git a/packages/s2-core/__tests__/spreadsheet/spread-sheet-facet-layout-api-spec.ts b/packages/s2-core/__tests__/spreadsheet/spread-sheet-facet-layout-api-spec.ts
index d711058a39..da32d09082 100644
--- a/packages/s2-core/__tests__/spreadsheet/spread-sheet-facet-layout-api-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/spread-sheet-facet-layout-api-spec.ts
@@ -35,17 +35,17 @@ describe('Facet Layout API Tests', () => {
Array [
Object {
"field": "province",
- "id": "",
+ "id": "province",
"value": "province",
},
Object {
"field": "city",
- "id": "",
+ "id": "city",
"value": "city",
},
Object {
"field": "type",
- "id": "",
+ "id": "type",
"value": "type",
},
Object {
@@ -107,17 +107,17 @@ describe('Facet Layout API Tests', () => {
},
Object {
"field": "province",
- "id": "",
+ "id": "province",
"value": "province",
},
Object {
"field": "city",
- "id": "",
+ "id": "city",
"value": "city",
},
Object {
"field": "type",
- "id": "",
+ "id": "type",
"value": "type",
},
Object {
@@ -164,17 +164,17 @@ describe('Facet Layout API Tests', () => {
Array [
Object {
"field": "province",
- "id": "",
+ "id": "province",
"value": "province",
},
Object {
"field": "city",
- "id": "",
+ "id": "city",
"value": "city",
},
Object {
"field": "type",
- "id": "",
+ "id": "type",
"value": "type",
},
Object {
@@ -226,17 +226,17 @@ describe('Facet Layout API Tests', () => {
Array [
Object {
"field": "province",
- "id": "",
+ "id": "province",
"value": "province",
},
Object {
"field": "city",
- "id": "",
+ "id": "city",
"value": "city",
},
Object {
"field": "type",
- "id": "",
+ "id": "type",
"value": "type",
},
Object {
@@ -314,7 +314,7 @@ describe('Facet Layout API Tests', () => {
Array [
Object {
"field": "type",
- "id": "",
+ "id": "type",
"value": "type",
},
Object {
@@ -353,17 +353,17 @@ describe('Facet Layout API Tests', () => {
Array [
Object {
"field": "province",
- "id": "",
+ "id": "province",
"value": "province",
},
Object {
"field": "city",
- "id": "",
+ "id": "city",
"value": "city",
},
Object {
"field": "type",
- "id": "",
+ "id": "type",
"value": "type",
},
]
@@ -385,17 +385,17 @@ describe('Facet Layout API Tests', () => {
},
Object {
"field": "province",
- "id": "",
+ "id": "province",
"value": "province",
},
Object {
"field": "city",
- "id": "",
+ "id": "city",
"value": "city",
},
Object {
"field": "type",
- "id": "",
+ "id": "type",
"value": "type",
},
]
@@ -407,17 +407,17 @@ describe('Facet Layout API Tests', () => {
Array [
Object {
"field": "province",
- "id": "",
+ "id": "province",
"value": "province",
},
Object {
"field": "city",
- "id": "",
+ "id": "city",
"value": "city",
},
Object {
"field": "type",
- "id": "",
+ "id": "type",
"value": "type",
},
]
@@ -439,17 +439,17 @@ describe('Facet Layout API Tests', () => {
},
Object {
"field": "province",
- "id": "",
+ "id": "province",
"value": "province",
},
Object {
"field": "city",
- "id": "",
+ "id": "city",
"value": "city",
},
Object {
"field": "type",
- "id": "",
+ "id": "type",
"value": "type",
},
]
diff --git a/packages/s2-core/__tests__/spreadsheet/spread-sheet-resize-spec.ts b/packages/s2-core/__tests__/spreadsheet/spread-sheet-resize-spec.ts
index 198c0513c3..4c2abe2f06 100644
--- a/packages/s2-core/__tests__/spreadsheet/spread-sheet-resize-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/spread-sheet-resize-spec.ts
@@ -1,15 +1,15 @@
import * as mockDataConfig from 'tests/data/simple-data.json';
import { getContainer } from 'tests/util/helpers';
import type { Group } from '@antv/g';
-import { PivotSheet } from '@/sheet-type';
import {
- KEY_GROUP_COL_RESIZE_AREA,
- KEY_GROUP_CORNER_RESIZE_AREA,
- KEY_GROUP_ROW_RESIZE_AREA,
type S2Options,
-} from '@/common';
+ PivotSheet,
+ KEY_GROUP_ROW_RESIZE_AREA,
+ KEY_GROUP_CORNER_RESIZE_AREA,
+ KEY_GROUP_COL_RESIZE_AREA,
+} from '../../src';
-async function renderSheet(options: S2Options) {
+async function renderSheet(options?: S2Options) {
const s2 = new PivotSheet(getContainer(), mockDataConfig, {
height: 150,
...options,
@@ -22,6 +22,7 @@ async function renderSheet(options: S2Options) {
},
},
});
+
await s2.render();
return s2;
@@ -191,4 +192,31 @@ describe('SpreadSheet Resize Active Tests', () => {
expect(group.getElementById(KEY_GROUP_ROW_RESIZE_AREA)).toBeNull();
expect(group.getElementById(KEY_GROUP_CORNER_RESIZE_AREA)).toBeNull();
});
+
+ test('should render correctly layout when tree row width is invalid number', async () => {
+ const s2 = await renderSheet();
+
+ s2.setOptions({
+ hierarchyType: 'tree',
+ style: {
+ rowCell: {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ width: '@',
+ },
+ },
+ });
+
+ await s2.render(false);
+
+ const nodes = s2.facet.getRowNodes().map((node) => {
+ return {
+ id: node.id,
+ width: node.width,
+ height: node.height,
+ };
+ });
+
+ expect(nodes).toMatchSnapshot();
+ });
});
diff --git a/packages/s2-core/__tests__/spreadsheet/spread-sheet-series-number-spec.ts b/packages/s2-core/__tests__/spreadsheet/spread-sheet-series-number-spec.ts
index 6944013201..0573dc8232 100644
--- a/packages/s2-core/__tests__/spreadsheet/spread-sheet-series-number-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/spread-sheet-series-number-spec.ts
@@ -1,8 +1,6 @@
import * as mockDataConfig from 'tests/data/simple-data.json';
import { getContainer } from 'tests/util/helpers';
-import { PivotSheet } from '@/sheet-type';
-import type { S2Options } from '@/common';
-import type { SeriesNumberCell } from '@/cell';
+import { type S2Options, PivotSheet } from '../../src';
const s2Options: S2Options = {
width: 400,
@@ -23,14 +21,10 @@ describe('SpreadSheet Series Number Tests', () => {
await s2.render();
- const seriesNumberHeader = s2.facet.seriesNumberHeader;
+ const seriesNumberCell = s2.facet.getSeriesNumberCells();
- expect(seriesNumberHeader?.children).toHaveLength(1);
-
- const seriesNum1 = seriesNumberHeader?.children[0] as SeriesNumberCell;
-
- // @ts-ignore
- expect(seriesNum1.meta.height).toEqual(60);
+ expect(seriesNumberCell).toHaveLength(1);
+ expect(seriesNumberCell[0].getMeta().height).toEqual(60);
});
test("series number should contain root parent and it's all children in tree mode", async () => {
@@ -41,13 +35,9 @@ describe('SpreadSheet Series Number Tests', () => {
await s2.render();
- const seriesNumberHeader = s2.facet.seriesNumberHeader;
-
- expect(seriesNumberHeader?.children).toHaveLength(1);
-
- const seriesNum1 = seriesNumberHeader?.children[0] as SeriesNumberCell;
+ const seriesNumberCell = s2.facet.getSeriesNumberCells();
- // @ts-ignore
- expect(seriesNum1.meta.height).toEqual(90);
+ expect(seriesNumberCell).toHaveLength(1);
+ expect(seriesNumberCell[0].getMeta().height).toEqual(90);
});
});
diff --git a/packages/s2-core/__tests__/spreadsheet/spread-sheet-totals-spec.ts b/packages/s2-core/__tests__/spreadsheet/spread-sheet-totals-spec.ts
index eeb3b48ac8..666aff715c 100644
--- a/packages/s2-core/__tests__/spreadsheet/spread-sheet-totals-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/spread-sheet-totals-spec.ts
@@ -1,8 +1,7 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
-import { get, merge } from 'lodash';
+import { merge } from 'lodash';
import { assembleDataCfg, assembleOptions, TOTALS_OPTIONS } from 'tests/util';
import { getContainer } from 'tests/util/helpers';
-import { DataCell } from '@/cell';
import type { RawData, S2DataConfig, S2Options } from '@/common';
import type { Node } from '@/facet/layout/node';
import { PivotSheet } from '@/sheet-type';
@@ -147,30 +146,22 @@ describe('Spreadsheet Totals Tests', () => {
});
await spreadsheet.render();
- const grandTotal = spreadsheet.facet.panelScrollGroup.children.find(
- (child) =>
- child instanceof DataCell && get(child, 'meta.rowId') === 'root[&]总计',
- ) as DataCell;
+ const grandTotal = spreadsheet.facet
+ .getDataCells()
+ .find((cell) => cell.getMeta().rowId === 'root[&]总计')!;
- // @ts-ignore
- expect(grandTotal.textShape.attr('text')).toEqual('26193');
+ expect(grandTotal.getTextShape().attr('text')).toEqual('26193');
- const rowSubtotal1 = spreadsheet.facet.panelScrollGroup.children.find(
- (child) =>
- child instanceof DataCell &&
- get(child, 'meta.rowId') === 'root[&]浙江省',
- ) as DataCell;
+ const rowSubtotal1 = spreadsheet.facet
+ .getDataCells()
+ .find((cell) => cell.getMeta().rowId === 'root[&]浙江省')!;
- // @ts-ignore
- expect(rowSubtotal1.textShape).toBeUndefined();
+ expect(rowSubtotal1.getTextShape()).toBeUndefined();
- const rowSubtotal2 = spreadsheet.facet.panelScrollGroup.children.find(
- (child) =>
- child instanceof DataCell &&
- get(child, 'meta.rowId') === 'root[&]浙江省',
- ) as DataCell;
+ const rowSubtotal2 = spreadsheet.facet
+ .getDataCells()
+ .find((cell) => cell.getMeta().rowId === 'root[&]四川省')!;
- // @ts-ignore
- expect(rowSubtotal2.textShape).toBeUndefined();
+ expect(rowSubtotal2.getTextShape()).toBeUndefined();
});
});
diff --git a/packages/s2-core/__tests__/spreadsheet/spread-sheet-tree-mode-spec.ts b/packages/s2-core/__tests__/spreadsheet/spread-sheet-tree-mode-spec.ts
index ae94d02794..2861bae844 100644
--- a/packages/s2-core/__tests__/spreadsheet/spread-sheet-tree-mode-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/spread-sheet-tree-mode-spec.ts
@@ -1,5 +1,6 @@
import * as mockDataConfig from 'tests/data/simple-data.json';
import { createPivotSheet, getContainer } from 'tests/util/helpers';
+import { PivotSheet } from '../../src';
import type { S2DataConfig, S2Options } from '@/common';
const s2Options: S2Options = {
@@ -11,11 +12,11 @@ const s2Options: S2Options = {
describe('SpreadSheet Tree Mode Tests', () => {
let container: HTMLElement;
- beforeAll(() => {
+ beforeEach(() => {
container = getContainer();
});
- afterAll(() => {
+ afterEach(() => {
container?.remove();
});
@@ -51,5 +52,43 @@ describe('SpreadSheet Tree Mode Tests', () => {
rowsHierarchyWidth,
);
});
+
+ // https://github.com/antvis/S2/issues/2389
+ test('the corner should only have one line with action icon', async () => {
+ // 行头维度更改为较长的 name
+ const newDataCfg: S2DataConfig = {
+ ...mockDataConfig,
+ meta: [
+ {
+ field: 'province',
+ name: '省1234567890份',
+ },
+ {
+ field: 'city',
+ name: '城1234567890市',
+ },
+ ],
+ };
+
+ // 添加 icon
+ const newS2Options: S2Options = {
+ ...s2Options,
+ headerActionIcons: [
+ {
+ icons: ['SortDownSelected'],
+ belongsCell: 'cornerCell',
+ },
+ ],
+ };
+ const s2 = new PivotSheet(container, newDataCfg, newS2Options);
+
+ await s2.render();
+
+ // 检查文本是否只有一行
+ const cornerCell = s2.facet.getCornerCells()[0];
+
+ expect(cornerCell.getTextShapes()).toHaveLength(1);
+ expect(cornerCell.isMultiLineText()).toBeFalsy();
+ });
});
});
diff --git a/packages/s2-core/__tests__/spreadsheet/table-sheet-spec.ts b/packages/s2-core/__tests__/spreadsheet/table-sheet-spec.ts
index c9ae16ea22..19c04800dc 100644
--- a/packages/s2-core/__tests__/spreadsheet/table-sheet-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/table-sheet-spec.ts
@@ -1,20 +1,19 @@
-import { last } from 'lodash';
import { getContainer, getMockData, sleep } from 'tests/util/helpers';
import {
- ColCell,
DeviceType,
ResizeType,
TableSheet,
type RawData,
type S2DataConfig,
type S2Options,
+ LayoutWidthType,
} from '@/index';
const data = getMockData(
'../../../s2-react/__tests__/data/tableau-supermarket.csv',
) as RawData[];
-const columns = [
+const columns: string[] = [
'order_id',
'order_date',
'ship_date',
@@ -75,7 +74,7 @@ const options: S2Options = {
showSeriesNumber: true,
placeholder: '',
style: {
- layoutWidthType: 'compact',
+ layoutWidthType: LayoutWidthType.Compact,
dataCell: {
height: 32,
},
@@ -193,12 +192,11 @@ describe('TableSheet normal spec', () => {
await s2.render();
- const getLastColCell = () =>
- last(s2.facet.getColNodes())!.belongsCell as ColCell;
- const preColWidth = getLastColCell().getMeta().width;
-
await sleep(30);
+ let columnNodes = s2.facet.getColNodes();
+
+ const startCellWidth = columnNodes[columnNodes.length - 1].width;
const { x, width, top } = s2.getCanvasElement().getBoundingClientRect();
s2.getCanvasElement().dispatchEvent(
@@ -232,9 +230,10 @@ describe('TableSheet normal spec', () => {
await sleep(300);
- const currentColWidth = getLastColCell().getMeta().width;
+ columnNodes = s2.facet.getColNodes();
+ const endCellWidth = columnNodes[columnNodes.length - 1].width;
- expect(currentColWidth).toBeGreaterThanOrEqual(resizeLength + preColWidth);
+ expect(Math.floor(endCellWidth - startCellWidth)).toBe(140);
});
test('should render link shape', async () => {
diff --git a/packages/s2-core/__tests__/spreadsheet/theme-spec.ts b/packages/s2-core/__tests__/spreadsheet/theme-spec.ts
index 950807e4d7..2a9e180e62 100644
--- a/packages/s2-core/__tests__/spreadsheet/theme-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/theme-spec.ts
@@ -1,7 +1,5 @@
/* eslint-disable jest/expect-expect */
-import { Text, type Group } from '@antv/g';
-import { createPivotSheet } from 'tests/util/helpers';
-import type { RowCell } from '@/cell';
+import { createPivotSheet, createTableSheet } from 'tests/util/helpers';
import {
CellType,
EXTRA_COLUMN_FIELD,
@@ -62,11 +60,17 @@ describe('SpreadSheet Theme Tests', () => {
expect(s2.getThemeName()).toEqual('dark');
});
- test('should get default theme', () => {
+ test('should get pivot sheet default theme', () => {
expect(s2.theme).toMatchSnapshot();
expect(s2.theme).toEqual(s2.getTheme());
});
+ test('should get table sheet theme', () => {
+ const tableSheet = createTableSheet(null);
+
+ expect(tableSheet.theme).toMatchSnapshot();
+ });
+
test.each(['dark', 'gray', 'colorful', 'default'] as ThemeName[])(
'should get %s theme',
(name) => {
@@ -219,7 +223,7 @@ describe('SpreadSheet Theme Tests', () => {
s2.setThemeCfg(getRowCellThemeCfg(align));
await s2.render();
- const rowCell = s2.facet.rowHeader!.children[0] as RowCell;
+ const rowCell = s2.facet.getRowCells()[0];
const rowCellWidth = rowCell.getMeta().width;
const actionIcon = rowCell.getActionIcons()[0];
@@ -463,9 +467,6 @@ describe('SpreadSheet Theme Tests', () => {
});
describe('Series Cell Tests', () => {
- const getTextShape = (group: Group) =>
- group.children.find((child) => child instanceof Text) as Text;
-
test.each(['top', 'middle', 'bottom'] as TextBaseline[])(
'should render %s text align for column nodes',
async (textBaseline) => {
@@ -488,14 +489,19 @@ describe('SpreadSheet Theme Tests', () => {
await s2.render();
- const rowCell = s2.facet.rowHeader!.children[0] as Group; // 浙江省
- const textOfRowCell = getTextShape(rowCell);
+ // 浙江省
+ const rowCell = s2.facet.getRowCells()[0];
+ const rowCellTextShape = rowCell.getTextShape();
- const seriesCell = s2.facet.seriesNumberHeader!.children[0] as Group; // 序号1
- const textOfSeriesCell = getTextShape(seriesCell);
+ // 序号1
+ const seriesCell = s2.facet.getSeriesNumberCells()[0];
+ const seriesCellTextShape = seriesCell.getTextShape();
- expect(textOfRowCell?.attr('textBaseline')).toEqual(textBaseline);
- expect(textOfSeriesCell?.attr('textBaseline')).toEqual(textBaseline);
+ expect(rowCellTextShape?.attr('textBaseline')).toEqual(textBaseline);
+ expect(seriesCellTextShape?.attr('textBaseline')).toEqual(textBaseline);
+ expect(rowCellTextShape.attr('y')).toEqual(
+ seriesCellTextShape.attr('y'),
+ );
},
);
});
diff --git a/packages/s2-core/__tests__/spreadsheet/total-group-spec.ts b/packages/s2-core/__tests__/spreadsheet/total-group-spec.ts
new file mode 100644
index 0000000000..4505813244
--- /dev/null
+++ b/packages/s2-core/__tests__/spreadsheet/total-group-spec.ts
@@ -0,0 +1,332 @@
+import { getContainer } from 'tests/util/helpers';
+import { map } from 'lodash';
+import { s2Options, dataCfg } from '../data/total-group-data';
+import { CellData } from '../../src';
+import type { PivotFacet } from '../../src/facet';
+import { PivotSheet } from '@/sheet-type';
+import { type S2Options, ORIGIN_FIELD } from '@/common';
+
+describe('Total Group Dimension Test', () => {
+ let container: HTMLDivElement;
+
+ let s2: PivotSheet;
+
+ beforeEach(() => {
+ container = getContainer();
+ });
+
+ afterEach(() => {
+ // s2?.destroy();
+ });
+
+ test(`should get correct layout with row total group dimension 'type'`, async () => {
+ s2 = new PivotSheet(container, dataCfg, s2Options as S2Options);
+ await s2.render();
+
+ const facet = s2.facet as PivotFacet;
+ const { rowLeafNodes } = facet.getLayoutResult();
+
+ expect(map(rowLeafNodes, 'id')).toMatchInlineSnapshot(`
+ Array [
+ "root[&]总计[&]家具",
+ "root[&]总计[&]办公用品",
+ "root[&]浙江省[&]小计[&]家具",
+ "root[&]浙江省[&]小计[&]办公用品",
+ "root[&]浙江省[&]杭州市[&]家具",
+ "root[&]浙江省[&]杭州市[&]办公用品",
+ "root[&]浙江省[&]舟山市[&]家具",
+ "root[&]浙江省[&]舟山市[&]办公用品",
+ "root[&]四川省[&]小计[&]家具",
+ "root[&]四川省[&]小计[&]办公用品",
+ "root[&]四川省[&]成都市[&]家具",
+ "root[&]四川省[&]成都市[&]办公用品",
+ "root[&]四川省[&]绵阳市[&]家具",
+ "root[&]四川省[&]绵阳市[&]办公用品",
+ ]
+ `);
+
+ expect((facet.getCellMeta(0, 0)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ type: '家具',
+ price: 2000,
+ });
+ expect((facet.getCellMeta(1, 1)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ type: '办公用品',
+ cost: 1900,
+ });
+ });
+
+ test(`should get correct layout with row total group dimension 'city'`, async () => {
+ const newS2Options = {
+ ...s2Options,
+ totals: {
+ ...s2Options.totals,
+ row: {
+ ...s2Options.totals!.row!,
+ grandTotalsGroupDimensions: ['city'],
+ },
+ },
+ };
+
+ s2 = new PivotSheet(container, dataCfg, newS2Options as S2Options);
+ await s2.render();
+
+ const facet = s2.facet;
+ const { rowLeafNodes } = facet.getLayoutResult();
+
+ expect(map(rowLeafNodes, 'id')).toMatchInlineSnapshot(`
+ Array [
+ "root[&]总计[&]杭州市",
+ "root[&]总计[&]舟山市",
+ "root[&]总计[&]成都市",
+ "root[&]总计[&]绵阳市",
+ "root[&]浙江省[&]小计[&]家具",
+ "root[&]浙江省[&]小计[&]办公用品",
+ "root[&]浙江省[&]杭州市[&]家具",
+ "root[&]浙江省[&]杭州市[&]办公用品",
+ "root[&]浙江省[&]舟山市[&]家具",
+ "root[&]浙江省[&]舟山市[&]办公用品",
+ "root[&]四川省[&]小计[&]家具",
+ "root[&]四川省[&]小计[&]办公用品",
+ "root[&]四川省[&]成都市[&]家具",
+ "root[&]四川省[&]成都市[&]办公用品",
+ "root[&]四川省[&]绵阳市[&]家具",
+ "root[&]四川省[&]绵阳市[&]办公用品",
+ ]
+ `);
+
+ expect((facet.getCellMeta(0, 0)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ city: '杭州市',
+ price: 300,
+ });
+
+ expect((facet.getCellMeta(1, 0)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ city: '舟山市',
+ price: 800,
+ });
+
+ expect((facet.getCellMeta(2, 0)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ city: '成都市',
+ price: 1200,
+ });
+
+ expect((facet.getCellMeta(3, 0)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ city: '绵阳市',
+ price: 1600,
+ });
+ });
+
+ test(`should get correct layout with row sub group dimension 'type'`, async () => {
+ const newS2Options = {
+ ...s2Options,
+ totals: {
+ ...s2Options.totals,
+ row: {
+ ...s2Options.totals!.row,
+ // 总计分组下,city 城市维度会出现分组
+ grandTotalsGroupDimensions: ['city'],
+ subTotalsGroupDimensions: ['type'],
+ },
+ },
+ };
+
+ const newDataCfg = {
+ ...dataCfg,
+ fields: {
+ ...dataCfg.fields,
+ rows: ['province', 'city', 'type'],
+ columns: ['sub_type'],
+ values: ['price', 'cost'],
+ },
+ };
+
+ s2 = new PivotSheet(container, newDataCfg, newS2Options as S2Options);
+ await s2.render();
+
+ const facet = s2.facet;
+ const { rowLeafNodes } = facet.getLayoutResult();
+
+ expect(rowLeafNodes[4].id).toEqual('root[&]浙江省[&]小计[&]家具');
+ expect(rowLeafNodes[5].id).toEqual('root[&]浙江省[&]小计[&]办公用品');
+
+ expect((facet.getCellMeta(4, 0)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ province: '浙江省',
+ price: 600,
+ type: '家具',
+ });
+
+ expect((facet.getCellMeta(5, 0)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ province: '浙江省',
+ type: '办公用品',
+ price: 500,
+ });
+ });
+
+ test(`should get correct layout with col total group dimension 'type'`, async () => {
+ const newS2Options = {
+ ...s2Options,
+ totals: {
+ ...s2Options.totals,
+ col: {
+ ...s2Options.totals!.col,
+ grandTotalsGroupDimensions: ['type'],
+ },
+ },
+ };
+
+ const newDataCfg = {
+ ...dataCfg,
+ fields: {
+ ...dataCfg.fields,
+ rows: ['province'],
+ columns: ['city', 'type', 'sub_type'],
+ values: ['price', 'cost'],
+ },
+ };
+
+ s2 = new PivotSheet(container, newDataCfg, newS2Options as S2Options);
+ await s2.render();
+
+ const facet = s2.facet;
+
+ expect((facet.getCellMeta(0, 0)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ type: '家具',
+ price: 2000,
+ });
+
+ expect((facet.getCellMeta(0, 2)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ type: '办公用品',
+ price: 1900,
+ });
+ });
+
+ test(`should get correct layout with col total group dimension 'sub_type'`, async () => {
+ const newS2Options = {
+ ...s2Options,
+ totals: {
+ ...s2Options.totals,
+ col: {
+ ...s2Options.totals!.col,
+ grandTotalsGroupDimensions: ['sub_type'],
+ },
+ },
+ };
+
+ const newDataCfg = {
+ ...dataCfg,
+ fields: {
+ ...dataCfg.fields,
+ rows: ['province'],
+ columns: ['city', 'type', 'sub_type'],
+ values: ['price', 'cost'],
+ },
+ };
+
+ s2 = new PivotSheet(container, newDataCfg, newS2Options as S2Options);
+ await s2.render();
+
+ const facet = s2.facet;
+
+ expect((facet.getCellMeta(0, 0)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ sub_type: '桌子',
+ price: 1000,
+ });
+
+ expect((facet.getCellMeta(0, 2)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ sub_type: '沙发',
+ price: 1000,
+ });
+
+ expect((facet.getCellMeta(0, 4)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ sub_type: '笔',
+ price: 1000,
+ });
+
+ expect((facet.getCellMeta(0, 6)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ sub_type: '纸张',
+ price: 900,
+ });
+ });
+
+ test(`should get correct layout with col sub total group dimension 'sub_type'`, async () => {
+ const newS2Options = {
+ ...s2Options,
+ totals: {
+ ...s2Options.totals,
+ col: {
+ ...s2Options.totals!.col,
+ grandTotalsGroupDimensions: [],
+ subTotalsDimensions: ['city'],
+ subTotalsGroupDimensions: ['sub_type'],
+ },
+ },
+ };
+
+ const newDataCfg = {
+ ...dataCfg,
+ fields: {
+ ...dataCfg.fields,
+ rows: ['province'],
+ columns: ['city', 'type', 'sub_type'],
+ values: ['price', 'cost'],
+ },
+ };
+
+ s2 = new PivotSheet(container, newDataCfg, newS2Options as S2Options);
+ await s2.render();
+
+ const facet = s2.facet;
+
+ expect((facet.getCellMeta(0, 2)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ city: '杭州市',
+ sub_type: '桌子',
+ price: 100,
+ });
+
+ expect((facet.getCellMeta(0, 4)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ city: '杭州市',
+ sub_type: '沙发',
+ price: 100,
+ });
+
+ expect((facet.getCellMeta(0, 6)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ city: '杭州市',
+ sub_type: '笔',
+ price: 100,
+ });
+ });
+
+ test(`should get correct layout with giving total data`, async () => {
+ const newDataCfg = {
+ ...dataCfg,
+ data: dataCfg.data.concat([
+ {
+ type: '家具',
+ price: 6666,
+ cost: 6666,
+ },
+ {
+ type: '办公用品',
+ price: 9999,
+ cost: 9999,
+ },
+ ]),
+ };
+
+ s2 = new PivotSheet(container, newDataCfg, s2Options as S2Options);
+ await s2.render();
+
+ const facet = s2.facet;
+
+ expect((facet.getCellMeta(0, 0)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ type: '家具',
+ price: 6666,
+ cost: 6666,
+ });
+
+ expect((facet.getCellMeta(1, 0)!.data as CellData)[ORIGIN_FIELD]).toEqual({
+ type: '办公用品',
+ price: 9999,
+ cost: 9999,
+ });
+ });
+});
diff --git a/packages/s2-core/__tests__/unit/cell/col-cell-spec.ts b/packages/s2-core/__tests__/unit/cell/col-cell-spec.ts
index 9331a781d0..66be515b2d 100644
--- a/packages/s2-core/__tests__/unit/cell/col-cell-spec.ts
+++ b/packages/s2-core/__tests__/unit/cell/col-cell-spec.ts
@@ -1,13 +1,13 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
-import { get, set } from 'lodash';
+import { set } from 'lodash';
import { createFakeSpreadSheet, createPivotSheet } from 'tests/util/helpers';
import type { ColHeaderConfig } from '../../../src/facet/header';
import { getContainer } from './../../util/helpers';
-import type { Node } from '@/facet/layout/node';
-import { PivotDataSet } from '@/data-set';
-import { SpreadSheet, PivotSheet } from '@/sheet-type';
-import { EXTRA_FIELD, type Formatter, type TextAlign } from '@/common';
import { ColCell } from '@/cell';
+import { EXTRA_FIELD, type Formatter, type TextAlign } from '@/common';
+import { PivotDataSet } from '@/data-set';
+import type { Node } from '@/facet/layout/node';
+import { PivotSheet, SpreadSheet } from '@/sheet-type';
const MockPivotSheet = PivotSheet as unknown as jest.Mock;
const MockPivotDataSet = PivotDataSet as unknown as jest.Mock;
@@ -101,9 +101,7 @@ describe('Col Cell Tests', () => {
const colCell = new ColCell(node, s2, headerConfig);
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- expect(colCell.textShape.attr('text')).toEqual('test');
+ expect(colCell.getTextShape().attr('text')).toEqual('test');
});
});
@@ -125,7 +123,7 @@ describe('Col Cell Tests', () => {
test('should draw right condition text shape', async () => {
await s2.render();
- const colCell = s2.facet.columnHeader.children[0].children[1] as ColCell;
+ const colCell = s2.facet.getColCells()[1];
expect(colCell.getTextShape().parsedStyle.fill).toBeColor('#5083F5');
});
@@ -150,10 +148,13 @@ describe('Col Cell Tests', () => {
});
await s2.render();
- const colCell = s2.facet.columnHeader.children[0].children[0];
+ const colCell = s2.facet.getColCells()[0];
- expect(get(colCell, 'conditionIconShape.cfg.name')).toEqual('CellUp');
- expect(get(colCell, 'conditionIconShape.cfg.fill')).toEqual('red');
+ // @ts-ignore
+ expect(colCell.rightIconPosition).toEqual({
+ x: 152,
+ y: 10.5,
+ });
});
test('should draw right condition background shape', async () => {
@@ -171,10 +172,11 @@ describe('Col Cell Tests', () => {
],
},
});
+
await s2.render();
- const colCell = s2.facet.columnHeader.children[0].children[1];
+ const colCell = s2.facet.getColCells()[1];
- expect(get(colCell, 'backgroundShape.parsedStyle.fill')).toBeColor(
+ expect(colCell.getBackgroundShape().parsedStyle.fill).toBeColor(
'#F7B46F',
);
});
@@ -198,7 +200,7 @@ describe('Col Cell Tests', () => {
});
await s2.render();
- const colCell = s2.facet.columnHeader.children[0].children[0] as ColCell;
+ const colCell = s2.facet.getColCells()[0];
const { fill, fontSize, fontWeight } = colCell.getTextShape().attributes;
expect(fill).toEqual('red');
diff --git a/packages/s2-core/__tests__/unit/cell/corner-cell-spec.ts b/packages/s2-core/__tests__/unit/cell/corner-cell-spec.ts
index 76455c2c5e..1cd114bdcd 100644
--- a/packages/s2-core/__tests__/unit/cell/corner-cell-spec.ts
+++ b/packages/s2-core/__tests__/unit/cell/corner-cell-spec.ts
@@ -26,7 +26,6 @@ describe('Corner Cell Tests', () => {
});
const drawTextShapeSpy = jest
- // @ts-ignore
.spyOn(cornerCell, 'drawTextShape')
.mockImplementationOnce(() => true);
diff --git a/packages/s2-core/__tests__/unit/cell/custom-tree-corner-cell-spec.ts b/packages/s2-core/__tests__/unit/cell/custom-tree-corner-cell-spec.ts
index 5a4da7c8b1..68d3041791 100644
--- a/packages/s2-core/__tests__/unit/cell/custom-tree-corner-cell-spec.ts
+++ b/packages/s2-core/__tests__/unit/cell/custom-tree-corner-cell-spec.ts
@@ -4,10 +4,9 @@
import { customTreeNodes } from 'tests/data/custom-tree-nodes';
import { CustomTreeData } from 'tests/data/data-custom-tree';
import { getContainer } from 'tests/util/helpers';
-import { get } from 'lodash';
import type { S2DataConfig } from '@/common/interface';
import { PivotSheet, SpreadSheet } from '@/sheet-type';
-import { CornerCell, type S2Options } from '@/index';
+import { type S2Options } from '@/index';
describe('test for corner text', () => {
const values: string[] = [
@@ -44,21 +43,19 @@ describe('test for corner text', () => {
});
test('get correct default corner text when the corner label is empty', () => {
- const cornerCells = mockSheet.facet.cornerHeader.children;
+ const cornerCells = mockSheet.facet.getCornerCells();
- expect(get(cornerCells[0], 'actualText')).toEqual('自定义节点A/指标E/数值');
- expect(get(cornerCells[1], 'actualText')).toEqual('type');
+ expect(cornerCells[0].getActualText()).toEqual('自定义节点A/指标E/数值');
+ expect(cornerCells[1].getActualText()).toEqual('type');
});
test('get correct default corner text when set the cornerText.', async () => {
mockSheet.setOptions({ ...options, cornerText: 'test' });
await mockSheet.render();
- const cornerCells = mockSheet.facet.cornerHeader.children.filter(
- (v) => v instanceof CornerCell,
- );
+ const cornerCells = mockSheet.facet.getCornerCells();
- expect(get(cornerCells[0], 'actualText')).toEqual('test');
- expect(get(cornerCells[1], 'actualText')).toEqual('type');
+ expect(cornerCells[0].getActualText()).toEqual('test');
+ expect(cornerCells[1].getActualText()).toEqual('type');
});
});
diff --git a/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts b/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts
index 096ccf74bf..6ce23c12d3 100644
--- a/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts
+++ b/packages/s2-core/__tests__/unit/cell/data-cell-spec.ts
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import type { Rect } from '@antv/g';
-import { find, get } from 'lodash';
+import { find, get, keys } from 'lodash';
import { createPivotSheet, createTableSheet } from 'tests/util/helpers';
import { DataCell } from '@/cell';
import type { TextAlign } from '@/common';
@@ -13,11 +13,11 @@ import {
type S2CellType,
type ViewMeta,
} from '@/common';
-import { EXTRA_FIELD, VALUE_FIELD } from '@/common/constant/basic';
import {
DEFAULT_FONT_COLOR,
REVERSE_FONT_COLOR,
} from '@/common/constant/condition';
+import { EXTRA_FIELD, VALUE_FIELD } from '@/common/constant/field';
import { PivotDataSet } from '@/data-set';
import type { PivotFacet } from '@/facet';
import { PivotSheet, SpreadSheet } from '@/sheet-type';
@@ -28,11 +28,11 @@ const MockPivotDataSet = PivotDataSet as unknown as jest.Mock;
const findDataCell = (
s2: SpreadSheet,
valueField: 'price' | 'cost' | 'number',
-) =>
- s2.facet.panelGroup.children[0].find(
- (item) =>
- item instanceof DataCell && item.getMeta().valueField === valueField,
- );
+) => {
+ return s2.facet
+ .getDataCells()
+ .find((item) => item.getMeta().valueField === valueField);
+};
describe('Data Cell Tests', () => {
const meta = {
@@ -57,7 +57,7 @@ describe('Data Cell Tests', () => {
});
test.each([
- ['left', 311],
+ ['left', 312],
['center', 375],
['right', 438],
] as const)(
@@ -75,14 +75,13 @@ describe('Data Cell Tests', () => {
},
},
});
+
await s2.render();
- const panelBBoxInstance = s2.facet.panelGroup.children[0];
- const dataCell = panelBBoxInstance.children.find(
- (item) => item instanceof DataCell,
- ) as DataCell;
- const { left: minX, right: maxX } =
- dataCell['linkFieldShape'].getBBox();
+ const dataCell = s2.facet.getDataCells()[0];
+ const { left: minX, right: maxX } = dataCell
+ .getLinkFieldShape()
+ .getBBox();
// 宽度相当
const linkLength = maxX - minX;
@@ -100,7 +99,7 @@ describe('Data Cell Tests', () => {
});
describe('Data Cell Formatter & Method Tests', () => {
- beforeEach(() => {
+ beforeEach(async () => {
const container = document.createElement('div');
s2 = new MockPivotSheet(container);
@@ -110,7 +109,11 @@ describe('Data Cell Tests', () => {
s2.facet = {
getRowLeafNodes: () => [],
+ getRowLeafNodeByIndex: jest.fn(),
+ getCells: () => [],
} as unknown as PivotFacet;
+
+ await s2.render();
});
test('should pass complete data into formatter', () => {
@@ -207,7 +210,7 @@ describe('Data Cell Tests', () => {
fill: 'red',
});
- beforeEach(() => {
+ beforeEach(async () => {
const container = document.createElement('div');
s2 = new MockPivotSheet(container);
@@ -217,7 +220,11 @@ describe('Data Cell Tests', () => {
s2.facet = {
getRowLeafNodes: () => [],
+ getRowLeafNodeByIndex: jest.fn(),
+ getCells: () => [],
} as unknown as PivotFacet;
+
+ await s2.render();
});
test("shouldn't init when width or height is not positive", () => {
@@ -543,11 +550,12 @@ describe('Data Cell Tests', () => {
field: 'cost',
mapping(value, dataInfo) {
const originData = s2.dataSet.originData;
- const resultData = find(originData, dataInfo);
+ const resultData = find(originData, (item) =>
+ keys(item).every((key) => item[key] === dataInfo[key]),
+ );
- expect(resultData).toEqual(dataInfo);
- // @ts-ignore
- expect(value).toEqual(resultData.cost);
+ expect(value).toEqual(resultData?.['cost']);
+ expect(value).toEqual(dataInfo['cost']);
return {
fill: '#fffae6',
diff --git a/packages/s2-core/__tests__/unit/cell/header-cell-spec.ts b/packages/s2-core/__tests__/unit/cell/header-cell-spec.ts
index a86817ee4f..08e98afa71 100644
--- a/packages/s2-core/__tests__/unit/cell/header-cell-spec.ts
+++ b/packages/s2-core/__tests__/unit/cell/header-cell-spec.ts
@@ -49,6 +49,70 @@ describe('header cell formatter test', () => {
expect(rowCell.getFieldValue()).toBe('杭州1');
});
+ test('should not format pivot col and row total cell', () => {
+ const colNode = new Node({
+ id: `root[&]总计`,
+ field: '',
+ value: '总计',
+ parent: root,
+ isTotalRoot: true,
+ });
+ const rowNode = new Node({
+ id: `root[&]杭州[&]小计`,
+ field: '',
+ value: '小计',
+ parent: root,
+ isTotalRoot: true,
+ });
+
+ const formatter: Formatter = (value) => {
+ return `${value}1`;
+ };
+
+ jest.spyOn(s2.dataSet, 'getFieldFormatter').mockReturnValue(formatter);
+
+ const colCell = new ColCell(colNode, s2);
+ const rowCell = new RowCell(rowNode, s2);
+
+ expect(colCell.getFieldValue()).toBe('总计');
+ expect(rowCell.getFieldValue()).toBe('小计');
+ });
+
+ test('should not format pivot row grand total cell in tree mode', () => {
+ const rowGrandTotalNode = new Node({
+ id: `root[&]总计`,
+ field: '',
+ value: '总计',
+ parent: root,
+ isTotals: true,
+ isGrandTotals: true,
+ isTotalRoot: true,
+ });
+
+ const rowSubTotalNode = new Node({
+ id: `root[&]杭州`,
+ field: '',
+ value: '杭州',
+ parent: root,
+ isTotals: true,
+ isSubTotals: true,
+ isGrandTotals: false,
+ });
+
+ const formatter: Formatter = (value) => {
+ return `${value}1`;
+ };
+
+ jest.spyOn(s2.dataSet, 'getFieldFormatter').mockReturnValue(formatter);
+ jest.spyOn(s2, 'isHierarchyTreeType').mockReturnValue(true);
+
+ const grandTotalCell = new ColCell(rowGrandTotalNode, s2);
+ const subTotalCell = new RowCell(rowSubTotalNode, s2);
+
+ expect(grandTotalCell.getFieldValue()).toBe('总计');
+ expect(subTotalCell.getFieldValue()).toBe('杭州1');
+ });
+
test('pivot corner cell not formatter', () => {
const formatter: Formatter = (value) => `${value}1`;
diff --git a/packages/s2-core/__tests__/unit/cell/row-cell-spec.ts b/packages/s2-core/__tests__/unit/cell/row-cell-spec.ts
index c53885a731..e60a3c0a09 100644
--- a/packages/s2-core/__tests__/unit/cell/row-cell-spec.ts
+++ b/packages/s2-core/__tests__/unit/cell/row-cell-spec.ts
@@ -1,8 +1,6 @@
-import { get } from 'lodash';
import { createPivotSheet } from 'tests/util/helpers';
-import type { RowCell } from '@antv/s2';
-import type { SpreadSheet } from '@/sheet-type';
import type { TextAlign } from '@/common';
+import type { SpreadSheet } from '@/sheet-type';
describe('Row Cell Tests', () => {
describe('Link Shape Tests', () => {
@@ -15,8 +13,8 @@ describe('Row Cell Tests', () => {
test.each([
['left', 21],
- ['center', 75],
- ['right', 129],
+ ['center', 75.25],
+ ['right', 129.5],
] as [TextAlign, number][])(
'should align link shape with text by %o',
async (textAlign, textCenterX) => {
@@ -34,7 +32,7 @@ describe('Row Cell Tests', () => {
});
await s2.render();
- const provinceCell = s2.facet.rowHeader!.children[0] as RowCell;
+ const provinceCell = s2.facet.getRowCells()[0];
const { left: minX, right: maxX } = provinceCell
.getLinkFieldShape()
.getBBox();
@@ -72,9 +70,9 @@ describe('Row Cell Tests', () => {
test('should draw right condition text shape', async () => {
await s2.render();
- const rowCell = s2.facet.rowHeader!.children[1] as RowCell;
+ const rowCell = s2.facet.getRowCells()[1];
- expect(rowCell.getTextShape().parsedStyle.fill).toBeColor('#5083F5');
+ expect(rowCell.getTextShape().style.fill).toEqual('#5083F5');
});
test('should draw right condition icon shape', async () => {
@@ -93,11 +91,12 @@ describe('Row Cell Tests', () => {
],
},
});
+
await s2.render();
- const rowCell = s2.facet.rowHeader!.children[1];
+ const rowCell = s2.facet.getRowCells()[1];
- expect(get(rowCell, 'conditionIconShape.cfg.name')).toEqual('CellUp');
- expect(get(rowCell, 'conditionIconShape.cfg.fill')).toEqual('red');
+ // @ts-ignore
+ expect(rowCell.rightIconPosition).toEqual({ x: 186.5, y: 9.5 });
});
test('should draw right condition background shape', async () => {
@@ -115,12 +114,11 @@ describe('Row Cell Tests', () => {
],
},
});
+
await s2.render();
- const rowCell = s2.facet.rowHeader!.children[0];
+ const rowCell = s2.facet.getRowCells()[0];
- expect(get(rowCell, 'backgroundShape.parsedStyle.fill')).toBeColor(
- '#F7B46F',
- );
+ expect(rowCell.getBackgroundShape().style.fill).toEqual('#F7B46F');
});
test('should render text by text theme', async () => {
@@ -140,9 +138,10 @@ describe('Row Cell Tests', () => {
],
},
});
+
await s2.render();
- const rowCell = s2.facet.rowHeader!.children[1] as RowCell;
+ const rowCell = s2.facet.getRowCells()[1];
const { fill, fontSize, fontWeight } = rowCell.getTextShape().attributes;
expect(fill).toEqual('red');
@@ -150,4 +149,44 @@ describe('Row Cell Tests', () => {
expect(fontWeight).toEqual(800);
});
});
+
+ describe('Cross Background Color Tests', () => {
+ const s2 = createPivotSheet({
+ width: 800,
+ height: 600,
+ });
+
+ const crossColor = '#FFFFFF';
+ const defaultColor = '#F5F8FF';
+ const cellColorConfig = {
+ crossBackgroundColor: crossColor,
+ backgroundColor: defaultColor,
+ };
+
+ s2.setTheme({
+ rowCell: {
+ cell: cellColorConfig,
+ },
+ dataCell: {
+ cell: cellColorConfig,
+ },
+ });
+
+ test('should draw right condition background shape', async () => {
+ await s2.render();
+
+ const rowCell0 = s2.facet.getRowCells()[0];
+ const rowCell1 = s2.facet.getRowCells()[1];
+ const rowCell2 = s2.facet.getRowCells()[2];
+
+ expect(rowCell0.getActualText()).toEqual('浙江');
+ expect(rowCell0.getBackgroundShape().style.fill).toEqual(defaultColor);
+
+ expect(rowCell1.getActualText()).toEqual('义乌');
+ expect(rowCell1.getBackgroundShape().style.fill).toEqual(crossColor);
+
+ expect(rowCell2.getActualText()).toEqual('杭州');
+ expect(rowCell2.getBackgroundShape().style.fill).toEqual(defaultColor);
+ });
+ });
});
diff --git a/packages/s2-core/__tests__/unit/common/i18n/index-spec.ts b/packages/s2-core/__tests__/unit/common/i18n/index-spec.ts
index bad4ef936d..f4849f4766 100644
--- a/packages/s2-core/__tests__/unit/common/i18n/index-spec.ts
+++ b/packages/s2-core/__tests__/unit/common/i18n/index-spec.ts
@@ -19,7 +19,7 @@ describe('I18n Test', () => {
setLang('en_US');
expect(i18n('小计')).toEqual('Total');
expect(i18n('总计')).toEqual('Total');
- expect(i18n('总和')).toEqual('SUM');
+ expect(i18n('总和')).toEqual('(SUM)');
expect(i18n('项')).toEqual('items');
expect(i18n('已选择')).toEqual('selected');
expect(i18n('序号')).toEqual('Index');
@@ -27,13 +27,14 @@ describe('I18n Test', () => {
expect(i18n('数值')).toEqual('Measure');
expect(i18n('共计')).toEqual('Total');
expect(i18n('条')).toEqual('');
+ expect(i18n(',')).toEqual(', ');
});
test('should show Chinese text when set lang to zh', () => {
setLang('zh_CN');
expect(i18n('小计')).toEqual('小计');
expect(i18n('总计')).toEqual('总计');
- expect(i18n('总和')).toEqual('总和');
+ expect(i18n('总和')).toEqual('(总和)');
expect(i18n('项')).toEqual('项');
expect(i18n('已选择')).toEqual('已选择');
expect(i18n('序号')).toEqual('序号');
@@ -41,5 +42,6 @@ describe('I18n Test', () => {
expect(i18n('数值')).toEqual('数值');
expect(i18n('共计')).toEqual('共计');
expect(i18n('条')).toEqual('条');
+ expect(i18n(',')).toEqual(',');
});
});
diff --git a/packages/s2-core/__tests__/unit/data-process/pivot-spec.tsx b/packages/s2-core/__tests__/unit/data-process/pivot-spec.tsx
index c07d3637b5..c7d5d0493c 100644
--- a/packages/s2-core/__tests__/unit/data-process/pivot-spec.tsx
+++ b/packages/s2-core/__tests__/unit/data-process/pivot-spec.tsx
@@ -7,6 +7,7 @@ import { assembleDataCfg, assembleOptions } from '../../util';
import { getContainer } from '../../util/helpers';
import { data } from '../../data/mock-dataset.json';
import type { ViewMeta } from '../../../src/common';
+import type { CellData } from '../../../src';
import { VALUE_FIELD } from '@/common/constant';
import type { PivotDataSet } from '@/data-set/pivot-data-set';
import { PivotSheet, SpreadSheet } from '@/sheet-type';
@@ -49,48 +50,59 @@ describe('Pivot Table Core Data Process', () => {
});
test('should get correct indexes data', () => {
+ const prefix = 'province[&]city[&]type[&]sub_type';
+
const ds = s2.dataSet as PivotDataSet;
const indexesData = ds.indexesData;
- expect(flattenDeep(indexesData).filter(Boolean)).toHaveLength(
+ expect(flattenDeep(indexesData[prefix]).filter(Boolean)).toHaveLength(
data.length,
);
- expect(get(indexesData, '1.1.1.1')).toEqual({
+ // 左上角
+ expect(get(indexesData, [prefix, 1, 1, 1, 1, 1])).toEqual({
province: '浙江省',
city: '杭州市',
type: '家具',
sub_type: '桌子',
number: 7789,
- }); // 左上角
- expect(get(indexesData, '1.1.2.2')).toEqual({
+ });
+
+ // 右上角
+ expect(get(indexesData, [prefix, 1, 1, 2, 2, 1])).toEqual({
province: '浙江省',
city: '杭州市',
type: '办公用品',
sub_type: '纸张',
number: 1343,
- }); // 右上角
- expect(get(indexesData, '2.4.1.1')).toEqual({
+ });
+
+ // 左下角
+ expect(get(indexesData, [prefix, 2, 4, 1, 1, 1])).toEqual({
province: '四川省',
city: '乐山市',
type: '家具',
sub_type: '桌子',
number: 2330,
- }); // 左下角
- expect(get(indexesData, '2.4.2.2')).toEqual({
+ });
+
+ // 右下角
+ expect(get(indexesData, [prefix, 2, 4, 2, 2, 1])).toEqual({
province: '四川省',
city: '乐山市',
type: '办公用品',
sub_type: '纸张',
number: 352,
- }); // 右下角
- expect(get(indexesData, '1.4.2.1')).toEqual({
+ });
+
+ // 中间
+ expect(get(indexesData, [prefix, 1, 4, 2, 1, 1])).toEqual({
province: '浙江省',
city: '舟山市',
type: '办公用品',
sub_type: '笔',
number: 1432,
- }); // 中间
+ });
});
});
@@ -140,6 +152,7 @@ describe('Pivot Table Core Data Process', () => {
'南充市',
'乐山市',
]);
+
// 父子关系正确
const leavesNodes = rowsHierarchy.getLeaves();
const firstLeafNode = leavesNodes[0];
@@ -166,26 +179,26 @@ describe('Pivot Table Core Data Process', () => {
// 节点正确
expect(colsHierarchy.getIndexNodes()).toHaveLength(4);
- expect(colsHierarchy.getNodes()).toHaveLength(10); // 价格在列头 家具[&]桌子[&]number
+ expect(colsHierarchy.getNodes()).toHaveLength(10); // 价格在列头 家具[&]桌子[&]数量
// 叶子节点正确
expect(colsHierarchy.getLeaves().map((node) => node.value)).toEqual([
- 'number',
- 'number',
- 'number',
- 'number',
+ '数量',
+ '数量',
+ '数量',
+ '数量',
]);
// 层级正确
expect(colsHierarchy.getNodes().map((node) => node.value)).toEqual([
'家具',
'桌子',
- 'number',
+ '数量',
'沙发',
- 'number',
+ '数量',
'办公用品',
'笔',
- 'number',
+ '数量',
'纸张',
- 'number',
+ '数量',
]);
expect(colsHierarchy.getNodes(0).map((node) => node.value)).toEqual([
'家具',
@@ -198,16 +211,17 @@ describe('Pivot Table Core Data Process', () => {
'纸张',
]);
expect(colsHierarchy.getNodes(2).map((node) => node.value)).toEqual([
- 'number',
- 'number',
- 'number',
- 'number',
+ '数量',
+ '数量',
+ '数量',
+ '数量',
]);
+
// 父子关系正确
const leavesNodes = colsHierarchy.getLeaves();
const firstLeafNode = leavesNodes[0];
- expect(firstLeafNode.value).toEqual('number');
+ expect(firstLeafNode.value).toEqual('数量');
expect(firstLeafNode.parent!.value).toEqual('桌子');
expect(firstLeafNode.parent!.parent?.value).toEqual('家具');
expect(
@@ -215,7 +229,7 @@ describe('Pivot Table Core Data Process', () => {
).toEqual(['桌子', '沙发']);
const lastLeafNode = leavesNodes[leavesNodes.length - 1];
- expect(lastLeafNode.value).toEqual('number');
+ expect(lastLeafNode.value).toEqual('数量');
expect(lastLeafNode.parent!.value).toEqual('纸张');
expect(lastLeafNode.parent!.parent?.value).toEqual('办公用品');
expect(
@@ -228,25 +242,25 @@ describe('Pivot Table Core Data Process', () => {
test('should calc correct row & cell width', () => {
const { rowLeafNodes, colLeafNodes } = s2.facet.getLayoutResult();
- expect(rowLeafNodes[0].width).toEqual(99);
- expect(colLeafNodes[0].width).toEqual(100);
+ expect(rowLeafNodes[0].width).toEqual(99.66);
+ expect(colLeafNodes[0].width).toEqual(99.67);
});
test('should calc correct row node size and coordinate', () => {
const { dataCell } = s2.options.style!;
const { rowsHierarchy, rowLeafNodes } = s2.facet.getLayoutResult();
// all sample width.
- expect(rowsHierarchy.sampleNodesForAllLevels[0]?.width).toEqual(99);
- expect(rowsHierarchy.sampleNodesForAllLevels[1]?.width).toEqual(99);
+ expect(rowsHierarchy.sampleNodesForAllLevels[0]?.width).toEqual(99.66);
+ expect(rowsHierarchy.sampleNodesForAllLevels[1]?.width).toEqual(99.66);
// all width
expect(uniq(rowsHierarchy.getNodes().map((node) => node.width))).toEqual([
- 99,
+ 99.66,
]);
// leaf node
rowLeafNodes.forEach((node, index) => {
expect(node.height).toEqual(dataCell?.height!);
expect(node.y).toEqual(node.height * index);
- expect(node.x).toEqual(99);
+ expect(node.x).toEqual(99.66);
});
// level = 0
const provinceNodes = rowsHierarchy.getNodes(0);
@@ -284,7 +298,7 @@ describe('Pivot Table Core Data Process', () => {
colLeafNodes.forEach((node, index) => {
const width = Math.floor(node.width);
- expect(width).toEqual(100);
+ expect(width).toEqual(99);
expect(node.x).toEqual(node.width * index);
expect(node.y).toEqual(node.level * (colCell!.height as number));
});
@@ -316,7 +330,8 @@ describe('Pivot Table Core Data Process', () => {
describe('4、Calculate data cell info', () => {
test('should get correct data value', () => {
const { getCellMeta } = s2.facet;
- const getData = (meta: ViewMeta | null) => meta?.data?.[VALUE_FIELD];
+ const getData = (meta: ViewMeta | null) =>
+ (meta?.data as CellData)?.[VALUE_FIELD];
// 左上角
expect(getData(getCellMeta(0, 0))).toBe(7789);
diff --git a/packages/s2-core/__tests__/unit/data-set/__snapshots__/pivot-data-set-total-spec.ts.snap b/packages/s2-core/__tests__/unit/data-set/__snapshots__/pivot-data-set-total-spec.ts.snap
new file mode 100644
index 0000000000..fe05152534
--- /dev/null
+++ b/packages/s2-core/__tests__/unit/data-set/__snapshots__/pivot-data-set-total-spec.ts.snap
@@ -0,0 +1,133 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Pivot Dataset Total Test test for total with dimension group get correct MultiData when query need to be processed 1`] = `
+Array [
+ CellData {
+ "extraField": "number",
+ "raw": Object {
+ "city": "杭州市",
+ "number": 7789,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ },
+ CellData {
+ "extraField": "number",
+ "raw": Object {
+ "city": "绍兴市",
+ "number": 2367,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ },
+ CellData {
+ "extraField": "number",
+ "raw": Object {
+ "city": "宁波市",
+ "number": 3877,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ },
+ CellData {
+ "extraField": "number",
+ "raw": Object {
+ "city": "舟山市",
+ "number": 4342,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ },
+]
+`;
+
+exports[`Pivot Dataset Total Test test for total with dimension group get correct MultiData when query need to be processed 2`] = `Array []`;
+
+exports[`Pivot Dataset Total Test test for total with dimension group get correct MultiData when query need to be processed 3`] = `
+Array [
+ CellData {
+ "extraField": "number",
+ "raw": Object {
+ "city": "杭州市",
+ "number": 7789,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ },
+ CellData {
+ "extraField": "number",
+ "raw": Object {
+ "city": "绍兴市",
+ "number": 2367,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ },
+ CellData {
+ "extraField": "number",
+ "raw": Object {
+ "city": "宁波市",
+ "number": 3877,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ },
+ CellData {
+ "extraField": "number",
+ "raw": Object {
+ "city": "舟山市",
+ "number": 4342,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ },
+ CellData {
+ "extraField": "number",
+ "raw": Object {
+ "city": "成都市",
+ "number": 1723,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ },
+ CellData {
+ "extraField": "number",
+ "raw": Object {
+ "city": "绵阳市",
+ "number": 1822,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ },
+ CellData {
+ "extraField": "number",
+ "raw": Object {
+ "city": "南充市",
+ "number": 1943,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ },
+ CellData {
+ "extraField": "number",
+ "raw": Object {
+ "city": "乐山市",
+ "number": 2330,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ },
+]
+`;
diff --git a/packages/s2-core/__tests__/unit/data-set/__snapshots__/table-data-set-spec.ts.snap b/packages/s2-core/__tests__/unit/data-set/__snapshots__/table-data-set-spec.ts.snap
new file mode 100644
index 0000000000..13feac731e
--- /dev/null
+++ b/packages/s2-core/__tests__/unit/data-set/__snapshots__/table-data-set-spec.ts.snap
@@ -0,0 +1,1191 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Table Mode Dataset Test test for query data #getMultiData by empty query 1`] = `
+Array [
+ Object {
+ "city": "杭州市",
+ "number": 7789,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 2367,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 3877,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 4342,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 5343,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 632,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 7234,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 834,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 945,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 1304,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 1145,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 1432,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 1343,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 1354,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 1523,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 1634,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "成都市",
+ "number": 1723,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 1822,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "南充市",
+ "number": 1943,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2330,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "成都市",
+ "number": 2451,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 2244,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "南充市",
+ "number": 2333,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2445,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "成都市",
+ "number": 2335,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 245,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "南充市",
+ "number": 2457,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2458,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "成都市",
+ "number": 4004,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 3077,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "南充市",
+ "number": 3551,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 352,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 26193,
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "number": 49709,
+ "type": "家具",
+ },
+ Object {
+ "number": 23516,
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "number": 29159,
+ "type": "办公用品",
+ },
+ Object {
+ "number": 12321,
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 16838,
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 18375,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "number": 14043,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "number": 4826,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 5854,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 7818,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "number": 9473,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "number": 7495,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 10984,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 13132,
+ "province": "浙江省",
+ "type": "家具",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 2288,
+ "province": "浙江省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 15420,
+ "province": "浙江省",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 2999,
+ "province": "浙江省",
+ "type": "家具",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 2658,
+ "province": "浙江省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 5657,
+ "province": "浙江省",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 11111,
+ "province": "浙江省",
+ "type": "家具",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 2668,
+ "province": "浙江省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 13779,
+ "province": "浙江省",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 5176,
+ "province": "浙江省",
+ "type": "家具",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 3066,
+ "province": "浙江省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 8242,
+ "province": "浙江省",
+ },
+ Object {
+ "city": "成都市",
+ "number": 4174,
+ "province": "四川省",
+ "type": "家具",
+ },
+ Object {
+ "city": "成都市",
+ "number": 6339,
+ "province": "四川省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "成都市",
+ "number": 10513,
+ "province": "四川省",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 4066,
+ "province": "四川省",
+ "type": "家具",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 3322,
+ "province": "四川省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 7388,
+ "province": "四川省",
+ },
+ Object {
+ "city": "南充市",
+ "number": 4276,
+ "province": "四川省",
+ "type": "家具",
+ },
+ Object {
+ "city": "南充市",
+ "number": 6008,
+ "province": "四川省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "南充市",
+ "number": 10284,
+ "province": "四川省",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 4775,
+ "province": "四川省",
+ "type": "家具",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2810,
+ "province": "四川省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 7585,
+ "province": "四川省",
+ },
+ Object {
+ "number": 32418,
+ "province": "浙江省",
+ "type": "家具",
+ },
+ Object {
+ "number": 10680,
+ "province": "浙江省",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 43098,
+ "province": "浙江省",
+ },
+ Object {
+ "number": 17291,
+ "province": "四川省",
+ "type": "家具",
+ },
+ Object {
+ "number": 18479,
+ "province": "四川省",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 35770,
+ "province": "四川省",
+ },
+ Object {
+ "number": 78868,
+ },
+]
+`;
+
+exports[`Table Mode Dataset Test test for query data #getMultiData by field query 1`] = `
+Array [
+ "杭州市",
+ "绍兴市",
+ "宁波市",
+ "舟山市",
+ "杭州市",
+ "绍兴市",
+ "宁波市",
+ "舟山市",
+ "杭州市",
+ "绍兴市",
+ "宁波市",
+ "舟山市",
+ "杭州市",
+ "绍兴市",
+ "宁波市",
+ "舟山市",
+ "成都市",
+ "绵阳市",
+ "南充市",
+ "乐山市",
+ "成都市",
+ "绵阳市",
+ "南充市",
+ "乐山市",
+ "成都市",
+ "绵阳市",
+ "南充市",
+ "乐山市",
+ "成都市",
+ "绵阳市",
+ "南充市",
+ "乐山市",
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ "杭州市",
+ "杭州市",
+ "杭州市",
+ "绍兴市",
+ "绍兴市",
+ "绍兴市",
+ "宁波市",
+ "宁波市",
+ "宁波市",
+ "舟山市",
+ "舟山市",
+ "舟山市",
+ "成都市",
+ "成都市",
+ "成都市",
+ "绵阳市",
+ "绵阳市",
+ "绵阳市",
+ "南充市",
+ "南充市",
+ "南充市",
+ "乐山市",
+ "乐山市",
+ "乐山市",
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+]
+`;
+
+exports[`Table Mode Dataset Test test for query data #getMultiData by field query 2`] = `
+Array [
+ 7789,
+ 2367,
+ 3877,
+ 4342,
+ 5343,
+ 632,
+ 7234,
+ 834,
+ 945,
+ 1304,
+ 1145,
+ 1432,
+ 1343,
+ 1354,
+ 1523,
+ 1634,
+ 1723,
+ 1822,
+ 1943,
+ 2330,
+ 2451,
+ 2244,
+ 2333,
+ 2445,
+ 2335,
+ 245,
+ 2457,
+ 2458,
+ 4004,
+ 3077,
+ 3551,
+ 352,
+ 26193,
+ 49709,
+ 23516,
+ 29159,
+ 12321,
+ 16838,
+ 18375,
+ 14043,
+ 4826,
+ 5854,
+ 7818,
+ 9473,
+ 7495,
+ 10984,
+ 13132,
+ 2288,
+ 15420,
+ 2999,
+ 2658,
+ 5657,
+ 11111,
+ 2668,
+ 13779,
+ 5176,
+ 3066,
+ 8242,
+ 4174,
+ 6339,
+ 10513,
+ 4066,
+ 3322,
+ 7388,
+ 4276,
+ 6008,
+ 10284,
+ 4775,
+ 2810,
+ 7585,
+ 32418,
+ 10680,
+ 43098,
+ 17291,
+ 18479,
+ 35770,
+ 78868,
+]
+`;
+
+exports[`Table Mode Dataset Test test for query data #getMultiData by field query 3`] = `
+Array [
+ "桌子",
+ "桌子",
+ "桌子",
+ "桌子",
+ "沙发",
+ "沙发",
+ "沙发",
+ "沙发",
+ "笔",
+ "笔",
+ "笔",
+ "笔",
+ "纸张",
+ "纸张",
+ "纸张",
+ "纸张",
+ "桌子",
+ "桌子",
+ "桌子",
+ "桌子",
+ "沙发",
+ "沙发",
+ "沙发",
+ "沙发",
+ "笔",
+ "笔",
+ "笔",
+ "笔",
+ "纸张",
+ "纸张",
+ "纸张",
+ "纸张",
+ "桌子",
+ undefined,
+ "沙发",
+ undefined,
+ "笔",
+ "纸张",
+ "桌子",
+ "沙发",
+ "笔",
+ "纸张",
+ "桌子",
+ "沙发",
+ "笔",
+ "纸张",
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+]
+`;
+
+exports[`Table Mode Dataset Test test for query data #getMultiData by rowIndex query 2`] = `
+Array [
+ Object {
+ "city": "杭州市",
+ "number": 7789,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 2367,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 3877,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 4342,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 5343,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 632,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 7234,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 834,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 945,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 1304,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 1145,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 1432,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 1343,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 1354,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 1523,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 1634,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "成都市",
+ "number": 1723,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 1822,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "南充市",
+ "number": 1943,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2330,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "成都市",
+ "number": 2451,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 2244,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "南充市",
+ "number": 2333,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2445,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "成都市",
+ "number": 2335,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 245,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "南充市",
+ "number": 2457,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2458,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "成都市",
+ "number": 4004,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 3077,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "南充市",
+ "number": 3551,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 352,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 26193,
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "number": 49709,
+ "type": "家具",
+ },
+ Object {
+ "number": 23516,
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "number": 29159,
+ "type": "办公用品",
+ },
+ Object {
+ "number": 12321,
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 16838,
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 18375,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "number": 14043,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "number": 4826,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 5854,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 7818,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "number": 9473,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "number": 7495,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 10984,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 13132,
+ "province": "浙江省",
+ "type": "家具",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 2288,
+ "province": "浙江省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 15420,
+ "province": "浙江省",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 2999,
+ "province": "浙江省",
+ "type": "家具",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 2658,
+ "province": "浙江省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 5657,
+ "province": "浙江省",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 11111,
+ "province": "浙江省",
+ "type": "家具",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 2668,
+ "province": "浙江省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 13779,
+ "province": "浙江省",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 5176,
+ "province": "浙江省",
+ "type": "家具",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 3066,
+ "province": "浙江省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 8242,
+ "province": "浙江省",
+ },
+ Object {
+ "city": "成都市",
+ "number": 4174,
+ "province": "四川省",
+ "type": "家具",
+ },
+ Object {
+ "city": "成都市",
+ "number": 6339,
+ "province": "四川省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "成都市",
+ "number": 10513,
+ "province": "四川省",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 4066,
+ "province": "四川省",
+ "type": "家具",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 3322,
+ "province": "四川省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 7388,
+ "province": "四川省",
+ },
+ Object {
+ "city": "南充市",
+ "number": 4276,
+ "province": "四川省",
+ "type": "家具",
+ },
+ Object {
+ "city": "南充市",
+ "number": 6008,
+ "province": "四川省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "南充市",
+ "number": 10284,
+ "province": "四川省",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 4775,
+ "province": "四川省",
+ "type": "家具",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2810,
+ "province": "四川省",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 7585,
+ "province": "四川省",
+ },
+ Object {
+ "number": 32418,
+ "province": "浙江省",
+ "type": "家具",
+ },
+ Object {
+ "number": 10680,
+ "province": "浙江省",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 43098,
+ "province": "浙江省",
+ },
+ Object {
+ "number": 17291,
+ "province": "四川省",
+ "type": "家具",
+ },
+ Object {
+ "number": 18479,
+ "province": "四川省",
+ "type": "办公用品",
+ },
+ Object {
+ "number": 35770,
+ "province": "四川省",
+ },
+ Object {
+ "number": 78868,
+ },
+]
+`;
diff --git a/packages/s2-core/__tests__/unit/data-set/custom-tree-data-set-spec.ts b/packages/s2-core/__tests__/unit/data-set/custom-tree-data-set-spec.ts
index d4fc7554d9..34b2cc9a8c 100644
--- a/packages/s2-core/__tests__/unit/data-set/custom-tree-data-set-spec.ts
+++ b/packages/s2-core/__tests__/unit/data-set/custom-tree-data-set-spec.ts
@@ -5,7 +5,7 @@ import { get } from 'lodash';
import { customTreeNodes } from 'tests/data/custom-tree-nodes';
import { CustomTreeData } from 'tests/data/data-custom-tree';
import type { S2DataConfig } from '@/common/interface';
-import { EXTRA_FIELD } from '@/common/constant';
+import { EXTRA_FIELD, ORIGIN_FIELD } from '@/common/constant';
import { PivotSheet } from '@/sheet-type';
import { CustomTreePivotDataSet } from '@/data-set/custom-tree-pivot-data-set';
@@ -50,7 +50,7 @@ describe('Custom Tree Dataset Test', () => {
test('should get empty row pivot meta', () => {
const rowPivotMeta = dataSet.rowPivotMeta;
- expect([...rowPivotMeta.keys()]).toEqual([]);
+ expect([...rowPivotMeta.keys()]).toEqual(values);
});
test('should get correct col pivot meta', () => {
@@ -66,9 +66,10 @@ describe('Custom Tree Dataset Test', () => {
});
test('should get correct indexesData', () => {
+ const prefix = 'type[&]sub_type';
const indexesData = dataSet.indexesData;
- expect(get(indexesData, '1.1')).toEqual({
+ expect(get(indexesData, [prefix, 1, 1, 1])).toEqual({
type: '家具',
sub_type: '桌子',
'measure-a': 1,
@@ -78,7 +79,7 @@ describe('Custom Tree Dataset Test', () => {
'measure-e': 5,
'measure-f': 6,
});
- expect(get(indexesData, '1.2')).toEqual({
+ expect(get(indexesData, [prefix, 1, 1, 2])).toEqual({
type: '家具',
sub_type: '椅子',
'measure-a': 11,
@@ -94,27 +95,23 @@ describe('Custom Tree Dataset Test', () => {
describe('test for query data', () => {
test('getCellData function', () => {
expect(
- dataSet
- .getCellData({
- query: {
- type: '家具',
- sub_type: '桌子',
- [EXTRA_FIELD]: 'measure-a',
- },
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ type: '家具',
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'measure-a',
+ },
+ })?.[ORIGIN_FIELD],
).toContainEntries([['measure-a', 1]]);
expect(
- dataSet
- .getCellData({
- query: {
- type: '家具',
- sub_type: '椅子',
- [EXTRA_FIELD]: 'measure-e',
- },
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ type: '家具',
+ sub_type: '椅子',
+ [EXTRA_FIELD]: 'measure-e',
+ },
+ })?.[ORIGIN_FIELD],
).toContainEntries([['measure-e', 55]]);
});
});
diff --git a/packages/s2-core/__tests__/unit/data-set/pivot-data-set-row-value-spec.ts b/packages/s2-core/__tests__/unit/data-set/pivot-data-set-row-value-spec.ts
index 0c08e25cd5..40ba2a4ccf 100644
--- a/packages/s2-core/__tests__/unit/data-set/pivot-data-set-row-value-spec.ts
+++ b/packages/s2-core/__tests__/unit/data-set/pivot-data-set-row-value-spec.ts
@@ -4,7 +4,7 @@
import { get, keys } from 'lodash';
import { data } from 'tests/data/mock-dataset.json';
import { assembleDataCfg } from '../../util';
-import { EXTRA_FIELD } from '@/common/constant';
+import { EXTRA_FIELD, VALUE_FIELD } from '@/common/constant';
import type { S2DataConfig } from '@/common/interface';
import { PivotSheet } from '@/sheet-type';
import { PivotDataSet } from '@/data-set/pivot-data-set';
@@ -95,23 +95,24 @@ describe('Pivot Mode Test When Value In Row', () => {
});
test('should get correct indexesData', () => {
+ const prefix = 'province[&]city[&]type[&]sub_type';
const indexesData = dataSet.indexesData;
- expect(get(indexesData, '1.1.1.1')).toEqual({
+ expect(get(indexesData, [prefix, 1, 1, 1, 1, 1])).toEqual({
province: '浙江省',
city: '杭州市',
type: '家具',
sub_type: '桌子',
number: 7789,
});
- expect(get(indexesData, '1.2.2.1')).toEqual({
+ expect(get(indexesData, [prefix, 1, 2, 1, 1, 2])).toEqual({
province: '浙江省',
city: '绍兴市',
- type: '办公用品',
- sub_type: '笔',
- number: 1304,
+ type: '家具',
+ sub_type: '沙发',
+ number: 632,
});
- expect(get(indexesData, '2.1.1.2')).toEqual({
+ expect(get(indexesData, [prefix, 2, 1, 1, 1, 2])).toEqual({
province: '四川省',
city: '成都市',
type: '家具',
@@ -126,6 +127,7 @@ describe('Pivot Mode Test When Value In Row', () => {
expect([...keys(sortedDimensionValues)]).toEqual([
'province',
'city',
+ EXTRA_FIELD,
'type',
'sub_type',
]);
@@ -133,8 +135,98 @@ describe('Pivot Mode Test When Value In Row', () => {
getDimensionsWithoutPathPre(sortedDimensionValues['province']),
).toEqual(['浙江省', '四川省']);
expect(
- getDimensionsWithoutPathPre(sortedDimensionValues['city']),
- ).toEqual([
+ getDimensionsWithoutPathPre(sortedDimensionValues['sub_type']),
+ ).toEqual(['桌子', '沙发', '笔', '纸张']);
+ });
+ });
+
+ describe('test for query data', () => {
+ test('getCellData function', () => {
+ expect(
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ city: '杭州市',
+ type: '家具',
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'number',
+ },
+ })?.[VALUE_FIELD],
+ ).toEqual(7789);
+
+ expect(
+ dataSet.getCellData({
+ query: {
+ province: '四川省',
+ city: '乐山市',
+ type: '办公用品',
+ sub_type: '纸张',
+ [EXTRA_FIELD]: 'number',
+ },
+ })?.[VALUE_FIELD],
+ ).toEqual(352);
+ });
+
+ test('getMultiData function', () => {
+ const specialQuery = {
+ province: '浙江省',
+ city: '杭州市',
+ type: '家具',
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'number',
+ };
+
+ expect(dataSet.getCellMultiData({ query: specialQuery })).toHaveLength(1);
+ expect(
+ dataSet.getCellMultiData({ query: specialQuery })[0]?.[VALUE_FIELD],
+ ).toEqual(7789);
+
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ province: '浙江省',
+ type: '家具',
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'number',
+ },
+ }),
+ ).toHaveLength(4);
+
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ type: '家具',
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'number',
+ },
+ }),
+ ).toHaveLength(8);
+
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ type: '家具',
+ [EXTRA_FIELD]: 'number',
+ },
+ }),
+ ).toHaveLength(16);
+
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ [EXTRA_FIELD]: 'number',
+ },
+ }),
+ ).toHaveLength(32);
+ });
+
+ test('getDimensionValues function', () => {
+ // without query
+ expect(dataSet.getDimensionValues('province')).toEqual([
+ '浙江省',
+ '四川省',
+ ]);
+ expect(dataSet.getDimensionValues('city')).toEqual([
'杭州市',
'绍兴市',
'宁波市',
@@ -144,6 +236,19 @@ describe('Pivot Mode Test When Value In Row', () => {
'南充市',
'乐山市',
]);
+ expect(dataSet.getDimensionValues('type')).toEqual(['家具', '办公用品']);
+ expect(dataSet.getDimensionValues('sub_type')).toEqual([
+ '桌子',
+ '沙发',
+ '笔',
+ '纸张',
+ ]);
+
+ expect(dataSet.getDimensionValues('empty')).toEqual([]);
+
+ const sortedDimensionValues = dataSet.sortedDimensionValues;
+
+ // with query
expect(
getDimensionsWithoutPathPre(sortedDimensionValues['type']),
).toEqual(['家具', '办公用品']);
diff --git a/packages/s2-core/__tests__/unit/data-set/pivot-data-set-spec.ts b/packages/s2-core/__tests__/unit/data-set/pivot-data-set-spec.ts
index 929f98ca26..0e24c8451e 100644
--- a/packages/s2-core/__tests__/unit/data-set/pivot-data-set-spec.ts
+++ b/packages/s2-core/__tests__/unit/data-set/pivot-data-set-spec.ts
@@ -14,7 +14,7 @@ import type {
SortMethod,
CustomHeaderField,
} from '@/common/interface';
-import { EXTRA_FIELD, TOTAL_VALUE } from '@/common/constant';
+import { EXTRA_FIELD, ORIGIN_FIELD, TOTAL_VALUE } from '@/common/constant';
import type { S2DataConfig } from '@/common/interface';
import { PivotSheet } from '@/sheet-type';
import { PivotDataSet } from '@/data-set/pivot-data-set';
@@ -105,22 +105,23 @@ describe('Pivot Dataset Test', () => {
test('should get correct indexesData', () => {
const indexesData = dataSet.indexesData;
+ const prefix = 'province[&]city[&]type[&]sub_type';
- expect(get(indexesData, '1.1.1.1')).toEqual({
+ expect(get(indexesData, [prefix, 1, 1, 1, 1, 1])).toEqual({
province: '浙江省',
city: '杭州市',
type: '家具',
sub_type: '桌子',
number: 7789,
});
- expect(get(indexesData, '1.2.2.1')).toEqual({
+ expect(get(indexesData, [prefix, 1, 2, 2, 1, 1])).toEqual({
province: '浙江省',
city: '绍兴市',
type: '办公用品',
sub_type: '笔',
number: 1304,
});
- expect(get(indexesData, '2.1.1.2')).toEqual({
+ expect(get(indexesData, [prefix, 2, 1, 1, 2, 1])).toEqual({
province: '四川省',
city: '成都市',
type: '家具',
@@ -137,6 +138,7 @@ describe('Pivot Dataset Test', () => {
'city',
'type',
'sub_type',
+ EXTRA_FIELD,
]);
expect(
getDimensionsWithoutPathPre(sortedDimensionValues['province']),
@@ -160,6 +162,10 @@ describe('Pivot Dataset Test', () => {
getDimensionsWithoutPathPre(sortedDimensionValues['sub_type']),
).toEqual(['桌子', '沙发', '笔', '纸张']);
});
+
+ test('should get correctly empty dataset result', () => {
+ expect(dataSet.isEmpty()).toBeFalsy();
+ });
});
describe('test for query data', () => {
@@ -175,7 +181,7 @@ describe('Pivot Dataset Test', () => {
isTotals: true,
});
- expect(cell1!.getOrigin()).toContainEntries([['number', 7789]]);
+ expect(cell1?.[ORIGIN_FIELD]).toContainEntries([['number', 7789]]);
const cell2 = dataSet.getCellData({
query: {
@@ -188,7 +194,7 @@ describe('Pivot Dataset Test', () => {
isTotals: true,
});
- expect(cell2!.getOrigin()).toContainEntries([['number', 352]]);
+ expect(cell2?.[ORIGIN_FIELD]).toContainEntries([['number', 352]]);
});
describe('getCellMultiData function', () => {
@@ -208,89 +214,9 @@ describe('Pivot Dataset Test', () => {
1,
);
expect(
- dataSet.getCellMultiData({ query: specialQuery })[0].getOrigin(),
+ dataSet.getCellMultiData({ query: specialQuery })[0]?.[ORIGIN_FIELD],
).toContainEntries([['number', 7789]]);
});
-
- test('should get all detail data when child dimension is not specified', () => {
- expect(
- dataSet.getCellMultiData({
- query: {
- province: '浙江省',
- type: '家具',
- sub_type: '桌子',
- [EXTRA_FIELD]: 'number',
- },
- totals: {
- row: { totalDimensions: false },
- column: { totalDimensions: false },
- },
- }),
- ).toHaveLength(4);
-
- expect(
- dataSet.getCellMultiData({
- query: {
- type: '家具',
- sub_type: '桌子',
- [EXTRA_FIELD]: 'number',
- },
- totals: {
- row: { totalDimensions: false },
- column: { totalDimensions: false },
- },
- }),
- ).toHaveLength(8);
-
- expect(
- dataSet.getCellMultiData({
- query: {
- type: '家具',
- [EXTRA_FIELD]: 'number',
- },
- totals: {
- row: { totalDimensions: false },
- column: { totalDimensions: false },
- },
- }),
- ).toHaveLength(16);
-
- expect(
- dataSet.getCellMultiData({
- query: {
- [EXTRA_FIELD]: 'number',
- },
- totals: {
- row: { totalDimensions: false },
- column: { totalDimensions: false },
- },
- }),
- ).toHaveLength(32);
- });
-
- test('should only query grand total data', () => {
- expect(
- dataSet.getCellMultiData({
- query: { [EXTRA_FIELD]: 'number' },
- totals: {
- row: { grandTotalOnly: true },
- column: { grandTotalOnly: true },
- },
- }),
- ).toHaveLength(1);
- });
-
- test('should query all grand total and sub total data in columns for all cities', () => {
- expect(
- dataSet.getCellMultiData({
- query: { [EXTRA_FIELD]: 'number' },
- totals: {
- row: { totalDimensions: false },
- column: { grandTotalOnly: false, subTotalOnly: true },
- },
- }),
- ).toHaveLength(24);
- });
});
test('getDimensionValues function', () => {
diff --git a/packages/s2-core/__tests__/unit/data-set/pivot-data-set-total-spec.ts b/packages/s2-core/__tests__/unit/data-set/pivot-data-set-total-spec.ts
index f6261ede2a..cd8f4a4f03 100644
--- a/packages/s2-core/__tests__/unit/data-set/pivot-data-set-total-spec.ts
+++ b/packages/s2-core/__tests__/unit/data-set/pivot-data-set-total-spec.ts
@@ -2,19 +2,25 @@
* pivot mode base data-set test.
*/
import { get, keys } from 'lodash';
-import * as multiDataCfg from 'tests/data/simple-data.json';
import * as mockData from 'tests/data/mock-dataset.json';
-import { assembleDataCfg, TOTALS_OPTIONS } from '../../util';
+import * as multiDataCfg from 'tests/data/simple-data.json';
import type { Query } from '../../../src/data-set/interface';
-import { EXTRA_FIELD, TOTAL_VALUE, VALUE_FIELD } from '@/common/constant';
+import { TOTALS_OPTIONS, assembleDataCfg } from '../../util';
+import {
+ EXTRA_FIELD,
+ ORIGIN_FIELD,
+ QueryDataType,
+ TOTAL_VALUE,
+ VALUE_FIELD,
+} from '@/common/constant';
import {
- type S2DataConfig,
Aggregation,
type CalcTotals,
+ type S2DataConfig,
} from '@/common/interface';
-import { PivotSheet } from '@/sheet-type';
-import { PivotDataSet } from '@/data-set/pivot-data-set';
import { Store } from '@/common/store';
+import { PivotDataSet } from '@/data-set/pivot-data-set';
+import { PivotSheet } from '@/sheet-type';
import { getDimensionsWithoutPathPre } from '@/utils/dataset/pivot-data-set';
jest.mock('@/sheet-type');
@@ -78,6 +84,12 @@ describe('Pivot Dataset Total Test', () => {
TOTAL_VALUE,
]);
+ expect([...colPivotMeta.get('家具')!.children.keys()]).toEqual([
+ '桌子',
+ '沙发',
+ TOTAL_VALUE,
+ ]);
+
expect([...colPivotMeta.get('办公用品')!.children.keys()]).toEqual([
'笔',
'纸张',
@@ -88,24 +100,32 @@ describe('Pivot Dataset Total Test', () => {
test('should get correct indexesData', () => {
const indexesData = dataSet.indexesData;
- expect(get(indexesData, '1.1.0.0')).toEqual({
+ expect(
+ get(indexesData, ['province[&]city[&]type[&]sub_type', 1, 1, 0, 0, 1]),
+ ).toEqual({
province: '浙江省',
city: '杭州市',
number: 15420,
});
- expect(get(indexesData, '1.1.2.0')).toEqual({
+ expect(
+ get(indexesData, ['province[&]city[&]type[&]sub_type', 1, 1, 2, 0, 1]),
+ ).toEqual({
province: '浙江省',
city: '杭州市',
type: '办公用品',
number: 2288,
});
- expect(get(indexesData, '2.0.2.0')).toEqual({
+ expect(
+ get(indexesData, ['province[&]city[&]type[&]sub_type', 2, 0, 2, 0, 1]),
+ ).toEqual({
province: '四川省',
type: '办公用品',
number: 18479,
});
- expect(get(indexesData, '0.0.0.0')).toEqual({
+ expect(
+ get(indexesData, ['province[&]city[&]type[&]sub_type', 0, 0, 0, 0, 1]),
+ ).toEqual({
number: 78868,
});
});
@@ -118,10 +138,12 @@ describe('Pivot Dataset Total Test', () => {
'city',
'type',
'sub_type',
+ EXTRA_FIELD,
]);
expect(
getDimensionsWithoutPathPre(sortedDimensionValues['province']),
).toEqual(['浙江省', '四川省', TOTAL_VALUE]);
+
expect(
getDimensionsWithoutPathPre(sortedDimensionValues['city']),
).toEqual([
@@ -140,6 +162,9 @@ describe('Pivot Dataset Total Test', () => {
expect(
getDimensionsWithoutPathPre(sortedDimensionValues['type']),
).toEqual(['家具', '办公用品', TOTAL_VALUE]);
+ expect(
+ getDimensionsWithoutPathPre(sortedDimensionValues['type']),
+ ).toEqual(['家具', '办公用品', TOTAL_VALUE]);
expect(
getDimensionsWithoutPathPre(sortedDimensionValues['sub_type']),
).toEqual([
@@ -151,80 +176,79 @@ describe('Pivot Dataset Total Test', () => {
TOTAL_VALUE,
TOTAL_VALUE,
]);
+ expect(
+ getDimensionsWithoutPathPre(sortedDimensionValues[EXTRA_FIELD]),
+ ).toEqual([
+ 'number',
+ 'number',
+ 'number',
+ 'number',
+ 'number',
+ 'number',
+ 'number',
+ ]);
});
});
describe('test for query data', () => {
test('getCellData function', () => {
expect(
- dataSet
- .getCellData({
- query: {
- province: '浙江省',
- type: '家具',
- sub_type: '桌子',
- [EXTRA_FIELD]: 'number',
- },
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ type: '家具',
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'number',
+ },
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 18375]]);
expect(
- dataSet
- .getCellData({
- query: {
- type: '家具',
- sub_type: '桌子',
- [EXTRA_FIELD]: 'number',
- },
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ type: '家具',
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'number',
+ },
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 26193]]);
expect(
- dataSet
- .getCellData({
- query: {
- province: '浙江省',
- city: '杭州市',
- type: '家具',
- [EXTRA_FIELD]: 'number',
- },
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ city: '杭州市',
+ type: '家具',
+ [EXTRA_FIELD]: 'number',
+ },
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 13132]]);
expect(
- dataSet
- .getCellData({
- query: {
- province: '浙江省',
- city: '杭州市',
- [EXTRA_FIELD]: 'number',
- },
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ city: '杭州市',
+ [EXTRA_FIELD]: 'number',
+ },
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 15420]]);
expect(
- dataSet
- .getCellData({
- query: {
- type: '家具',
- [EXTRA_FIELD]: 'number',
- },
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ type: '家具',
+ [EXTRA_FIELD]: 'number',
+ },
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 49709]]);
expect(
- dataSet
- .getCellData({
- query: {
- [EXTRA_FIELD]: 'number',
- },
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ [EXTRA_FIELD]: 'number',
+ },
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 78868]]);
});
@@ -268,80 +292,68 @@ describe('Pivot Dataset Total Test', () => {
});
test('should get correct total cell data when calculated by aggregation', () => {
expect(
- dataSet
- .getCellData({
- query: {
- province: '浙江省',
- type: '家具',
- sub_type: '桌子',
- [EXTRA_FIELD]: 'number',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ type: '家具',
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 18375]]);
expect(
- dataSet
- .getCellData({
- query: {
- type: '家具',
- sub_type: '桌子',
- [EXTRA_FIELD]: 'number',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ type: '家具',
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 26193]]);
expect(
- dataSet
- .getCellData({
- query: {
- province: '浙江省',
- city: '杭州市',
- type: '家具',
- [EXTRA_FIELD]: 'number',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ city: '杭州市',
+ type: '家具',
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 13132]]);
expect(
- dataSet
- .getCellData({
- query: {
- province: '浙江省',
- city: '杭州市',
- [EXTRA_FIELD]: 'number',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ city: '杭州市',
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 15420]]);
expect(
- dataSet
- .getCellData({
- query: {
- type: '家具',
- [EXTRA_FIELD]: 'number',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ type: '家具',
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 49709]]);
expect(
- dataSet
- .getCellData({
- query: {
- [EXTRA_FIELD]: 'number',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 78868]]);
});
@@ -389,28 +401,24 @@ describe('Pivot Dataset Total Test', () => {
});
test('should get correct total cell data when calculated by aggregation and multi values', () => {
expect(
- dataSet
- .getCellData({
- query: {
- province: '浙江',
- type: '笔',
- [EXTRA_FIELD]: 'price',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ province: '浙江',
+ type: '笔',
+ [EXTRA_FIELD]: 'price',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['price', 2]]);
expect(
- dataSet
- .getCellData({
- query: {
- province: '浙江',
- type: '笔',
- [EXTRA_FIELD]: 'cost',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ province: '浙江',
+ type: '笔',
+ [EXTRA_FIELD]: 'cost',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['cost', 4]]);
});
});
@@ -473,82 +481,126 @@ describe('Pivot Dataset Total Test', () => {
dataSet = new PivotDataSet(mockSheet);
dataSet.setDataCfg(dataCfg);
});
+
+ test('should get correct total cell data when totals calculated by calcFunc and Existential dimension grouping', () => {
+ const totalStatus = {
+ isRowTotal: true,
+ isColTotal: true,
+ isRowSubTotal: true,
+ isColSubTotal: true,
+ };
+
+ expect(
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ totalStatus,
+ })?.[VALUE_FIELD],
+ ).toEqual(18375);
+
+ expect(
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ [EXTRA_FIELD]: 'number',
+ },
+ totalStatus,
+ isTotals: true,
+ })?.[VALUE_FIELD],
+ ).toEqual(43098);
+
+ expect(
+ dataSet.getCellData({
+ query: {
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'number',
+ },
+ totalStatus,
+ isTotals: true,
+ })?.[VALUE_FIELD],
+ ).toEqual(26193);
+
+ expect(
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ type: '家具',
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ totalStatus,
+ })?.[VALUE_FIELD],
+ ).toEqual(32418);
+ });
+
test('should get correct total cell data when totals calculated by calcFunc', () => {
expect(
- dataSet
- .getCellData({
- query: {
- province: '浙江省',
- type: '家具',
- sub_type: '桌子',
- [EXTRA_FIELD]: 'number',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ type: '家具',
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 18375]]);
expect(
- dataSet
- .getCellData({
- query: {
- type: '家具',
- sub_type: '桌子',
- [EXTRA_FIELD]: 'number',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ type: '家具',
+ sub_type: '桌子',
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 52386]]);
expect(
- dataSet
- .getCellData({
- query: {
- province: '浙江省',
- city: '杭州市',
- type: '家具',
- [EXTRA_FIELD]: 'number',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ city: '杭州市',
+ type: '家具',
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 26264]]);
expect(
- dataSet
- .getCellData({
- query: {
- province: '浙江省',
- city: '杭州市',
- [EXTRA_FIELD]: 'number',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ province: '浙江省',
+ city: '杭州市',
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 15420]]);
expect(
- dataSet
- .getCellData({
- query: {
- type: '家具',
- [EXTRA_FIELD]: 'number',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ type: '家具',
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 99418]]);
expect(
- dataSet
- .getCellData({
- query: {
- [EXTRA_FIELD]: 'number',
- },
- isTotals: true,
- })!
- .getOrigin(),
+ dataSet.getCellData({
+ query: {
+ [EXTRA_FIELD]: 'number',
+ },
+ isTotals: true,
+ })?.[ORIGIN_FIELD],
).toContainEntries([['number', 78868]]);
});
});
@@ -564,7 +616,7 @@ describe('Pivot Dataset Total Test', () => {
expect(dataSet.getCellMultiData({ query: specialQuery })).toHaveLength(1);
expect(
- dataSet.getCellMultiData({ query: specialQuery })[0].getOrigin(),
+ dataSet.getCellMultiData({ query: specialQuery })[0]?.[ORIGIN_FIELD],
).toContainEntries([['number', 7789]]);
expect(
dataSet.getCellMultiData({
@@ -721,4 +773,53 @@ describe('Pivot Dataset Total Test', () => {
expect(isColSubTotal4).toBeTrue();
});
});
+
+ describe('test for total with dimension group', () => {
+ beforeEach(() => {
+ MockPivotSheet.mockClear();
+ const mockSheet = new MockPivotSheet();
+
+ mockSheet.store = new Store();
+ mockSheet.isValueInCols = () => true;
+ dataSet = new PivotDataSet(mockSheet);
+
+ dataCfg = assembleDataCfg({
+ meta: [],
+ fields: {
+ rows: ['province', 'city', 'type', 'sub_type'],
+ columns: [],
+ },
+ });
+ dataSet.setDataCfg(dataCfg);
+ });
+
+ test('get correct MultiData when query need to be processed', () => {
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ province: '浙江省',
+ sub_type: '桌子',
+ },
+ queryType: QueryDataType.DetailOnly,
+ }),
+ ).toMatchSnapshot();
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ province: '浙江省',
+ sub_type: '杭州市',
+ },
+ queryType: QueryDataType.DetailOnly,
+ }),
+ ).toMatchSnapshot();
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ sub_type: '桌子',
+ },
+ queryType: QueryDataType.DetailOnly,
+ }),
+ ).toMatchSnapshot();
+ });
+ });
});
diff --git a/packages/s2-core/__tests__/unit/data-set/table-data-set-spec.ts b/packages/s2-core/__tests__/unit/data-set/table-data-set-spec.ts
index d3f6ab1f30..a96e5d399c 100644
--- a/packages/s2-core/__tests__/unit/data-set/table-data-set-spec.ts
+++ b/packages/s2-core/__tests__/unit/data-set/table-data-set-spec.ts
@@ -3,7 +3,7 @@
*/
import { assembleDataCfg } from 'tests/util';
import type { S2DataConfig } from '@/common/interface';
-import { TableSheet } from '@/sheet-type';
+import { SpreadSheet, TableSheet } from '@/sheet-type';
import { TableDataSet } from '@/data-set/table-data-set';
jest.mock('@/sheet-type');
@@ -11,7 +11,9 @@ jest.mock('@/facet/layout/node');
const MockTableSheet = TableSheet as any as jest.Mock;
describe('Table Mode Dataset Test', () => {
+ let s2: SpreadSheet;
let dataSet: TableDataSet;
+
const mockNumberFormatter = jest.fn().mockReturnValue('number');
const mockSubTypeFormatter = jest.fn().mockReturnValue('sub_type');
const mockTypeFormatter = jest.fn().mockReturnValue('type');
@@ -59,12 +61,14 @@ describe('Table Mode Dataset Test', () => {
beforeEach(() => {
MockTableSheet.mockClear();
- dataSet = new TableDataSet(new MockTableSheet());
+
+ s2 = new MockTableSheet();
+ dataSet = new TableDataSet(s2);
dataSet.setDataCfg(dataCfg);
});
- afterAll(() => {});
+ afterEach(() => {});
describe('meta config test', () => {
test.each`
@@ -100,10 +104,14 @@ describe('Table Mode Dataset Test', () => {
test('should get correct meta data', () => {
expect(dataSet.meta).toEqual(expect.objectContaining([]));
});
+
+ test('should get correctly empty dataset result', () => {
+ expect(dataSet.isEmpty()).toBeFalsy();
+ });
});
describe('test for query data', () => {
- test('getCellData function', () => {
+ test('#getCellData', () => {
expect(
dataSet.getCellData({
query: { rowIndex: 0 },
@@ -120,7 +128,7 @@ describe('Table Mode Dataset Test', () => {
dataSet.getCellData({
query: {
rowIndex: 0,
- col: 'city',
+ field: 'city',
},
}),
).toEqual('杭州市');
@@ -129,7 +137,7 @@ describe('Table Mode Dataset Test', () => {
dataSet.getCellData({
query: {
rowIndex: 2,
- col: 'number',
+ field: 'number',
},
}),
).toEqual(3877);
@@ -138,10 +146,97 @@ describe('Table Mode Dataset Test', () => {
dataSet.getCellData({
query: {
rowIndex: 5,
- col: 'sub_type',
+ field: 'sub_type',
},
}),
).toEqual('沙发');
});
+
+ test('#getMultiData by empty query', () => {
+ expect(dataSet.getCellMultiData({})).toMatchSnapshot();
+ });
+
+ test('#getMultiData by rowIndex query', () => {
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ rowIndex: 0,
+ },
+ }),
+ ).toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "city": "杭州市",
+ "number": 7789,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ ]
+ `);
+
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ rowIndex: -1,
+ },
+ }),
+ ).toMatchSnapshot();
+ });
+
+ test('#getMultiData by field query', () => {
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ field: 'city',
+ },
+ }),
+ ).toMatchSnapshot();
+
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ field: 'number',
+ },
+ }),
+ ).toMatchSnapshot();
+
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ field: 'sub_type',
+ },
+ }),
+ ).toMatchSnapshot();
+ });
+
+ test('#getMultiData by field and rowIndex query', () => {
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ field: 'city',
+ rowIndex: 0,
+ },
+ }),
+ ).toEqual(['杭州市']);
+
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ field: 'number',
+ rowIndex: 2,
+ },
+ }),
+ ).toEqual([3877]);
+
+ expect(
+ dataSet.getCellMultiData({
+ query: {
+ field: 'sub_type',
+ rowIndex: 3,
+ },
+ }),
+ ).toEqual(['桌子']);
+ });
});
});
diff --git a/packages/s2-core/__tests__/unit/dataset/__snapshots__/table-dataset-spec.ts.snap b/packages/s2-core/__tests__/unit/dataset/__snapshots__/table-dataset-spec.ts.snap
new file mode 100644
index 0000000000..b37ddaca28
--- /dev/null
+++ b/packages/s2-core/__tests__/unit/dataset/__snapshots__/table-dataset-spec.ts.snap
@@ -0,0 +1,459 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Table Mode Dataset Test test for sort and filter should asc sort by number field 1`] = `
+Array [
+ Object {
+ "city": "绵阳市",
+ "number": 245,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 352,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 632,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 834,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 945,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 1145,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 1304,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 1343,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 1354,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 1432,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 1523,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 1634,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "成都市",
+ "number": 1723,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 1822,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "南充市",
+ "number": 1943,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 2244,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2330,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "南充市",
+ "number": 2333,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "成都市",
+ "number": 2335,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 2367,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2445,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "成都市",
+ "number": 2451,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "南充市",
+ "number": 2457,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2458,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 3077,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "南充市",
+ "number": 3551,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 3877,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "成都市",
+ "number": 4004,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 4342,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 5343,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 7234,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 7789,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+]
+`;
+
+exports[`Table Mode Dataset Test test for sort and filter should desc sort by number field 1`] = `
+Array [
+ Object {
+ "city": "杭州市",
+ "number": 7789,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 7234,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 5343,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 4342,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "成都市",
+ "number": 4004,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 3877,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "南充市",
+ "number": 3551,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 3077,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2458,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "南充市",
+ "number": 2457,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "成都市",
+ "number": 2451,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2445,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 2367,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "成都市",
+ "number": 2335,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "南充市",
+ "number": 2333,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 2330,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 2244,
+ "province": "四川省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "南充市",
+ "number": 1943,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 1822,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "成都市",
+ "number": 1723,
+ "province": "四川省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 1634,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 1523,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 1432,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 1354,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 1343,
+ "province": "浙江省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 1304,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "宁波市",
+ "number": 1145,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "杭州市",
+ "number": 945,
+ "province": "浙江省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "舟山市",
+ "number": 834,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "绍兴市",
+ "number": 632,
+ "province": "浙江省",
+ "sub_type": "沙发",
+ "type": "家具",
+ },
+ Object {
+ "city": "乐山市",
+ "number": 352,
+ "province": "四川省",
+ "sub_type": "纸张",
+ "type": "办公用品",
+ },
+ Object {
+ "city": "绵阳市",
+ "number": 245,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ },
+]
+`;
diff --git a/packages/s2-core/__tests__/unit/dataset/table-dataset-spec.ts b/packages/s2-core/__tests__/unit/dataset/table-dataset-spec.ts
index 8089f50f50..07cc181f83 100644
--- a/packages/s2-core/__tests__/unit/dataset/table-dataset-spec.ts
+++ b/packages/s2-core/__tests__/unit/dataset/table-dataset-spec.ts
@@ -1,12 +1,12 @@
/**
* table mode data-set test.
*/
-import { orderBy, uniq } from 'lodash';
+import { first, last, orderBy, uniq } from 'lodash';
import { data } from 'tests/data/mock-dataset.json';
import { assembleDataCfg } from '../../util';
import type { S2DataConfig, SortParam } from '@/common/interface';
-import { TableSheet } from '@/sheet-type';
import { TableDataSet } from '@/data-set/table-data-set';
+import { TableSheet } from '@/sheet-type';
jest.mock('@/sheet-type');
jest.mock('@/facet/layout/node');
@@ -15,6 +15,7 @@ const MockTableSheet = TableSheet as any as jest.Mock;
describe('Table Mode Dataset Test', () => {
let dataSet: TableDataSet;
+
const dataCfg: S2DataConfig = {
...assembleDataCfg({}),
meta: [],
@@ -36,6 +37,10 @@ describe('Table Mode Dataset Test', () => {
dataSet.setDataCfg(dataCfg);
});
+ afterEach(() => {
+ MockTableSheet.mockClear();
+ });
+
describe('test base dataset structure', () => {
test('should get correct field data', () => {
expect(dataSet.fields.rows).toEqual(undefined);
@@ -60,7 +65,7 @@ describe('Table Mode Dataset Test', () => {
dataSet.getCellData({
query: {
rowIndex: 0,
- col: 'city',
+ field: 'city',
},
}),
).toEqual('杭州市');
@@ -69,7 +74,7 @@ describe('Table Mode Dataset Test', () => {
dataSet.getCellData({
query: {
rowIndex: 2,
- col: 'number',
+ field: 'number',
},
}),
).toEqual(3877);
@@ -78,7 +83,7 @@ describe('Table Mode Dataset Test', () => {
dataSet.getCellData({
query: {
rowIndex: 5,
- col: 'sub_type',
+ field: 'sub_type',
},
}),
).toEqual('沙发');
@@ -97,7 +102,7 @@ describe('Table Mode Dataset Test', () => {
expect(
emptyDataSet.getCellData({
query: {
- col: 'sub_type',
+ field: 'sub_type',
rowIndex: 0,
},
}),
@@ -120,11 +125,12 @@ describe('Table Mode Dataset Test', () => {
dataSet.getCellData({
query: {
rowIndex: 0,
- col: 'city',
+ field: 'city',
},
}),
).toEqual('成都市');
});
+
it('should getCellData with customFilter', () => {
dataSet.setDataCfg({
...dataCfg,
@@ -139,7 +145,7 @@ describe('Table Mode Dataset Test', () => {
dataSet.getCellData({
query: {
rowIndex: 0,
- col: 'city',
+ field: 'city',
},
}),
).toEqual('杭州市');
@@ -161,7 +167,7 @@ describe('Table Mode Dataset Test', () => {
dataSet.getCellData({
query: {
rowIndex: 0,
- col: 'city',
+ field: 'city',
},
}),
).toEqual('成都市');
@@ -181,7 +187,7 @@ describe('Table Mode Dataset Test', () => {
dataSet.getCellData({
query: {
rowIndex: 0,
- col: 'number',
+ field: 'number',
},
}),
).toEqual(245);
@@ -292,5 +298,118 @@ describe('Table Mode Dataset Test', () => {
dataSet.handleDimensionValuesSort();
expect([...result, ...rest]).toStrictEqual(dataSet.getDisplayDataSet());
});
+
+ it('should asc sort by number field', () => {
+ const sortFieldId = 'number';
+
+ dataSet.sortParams = [
+ {
+ sortFieldId,
+ sortMethod: 'asc',
+ },
+ ];
+
+ dataSet.handleDimensionValuesSort();
+
+ expect(dataSet.getDisplayDataSet()).toHaveLength(32);
+ expect(dataSet.getDisplayDataSet()).toMatchSnapshot();
+ });
+
+ it('should desc sort by number field', () => {
+ const sortFieldId = 'number';
+
+ dataSet.sortParams = [
+ {
+ sortFieldId,
+ sortMethod: 'desc',
+ },
+ ];
+
+ dataSet.handleDimensionValuesSort();
+
+ expect(dataSet.getDisplayDataSet()).toHaveLength(32);
+ expect(dataSet.getDisplayDataSet()).toMatchSnapshot();
+ });
+
+ // https://github.com/antvis/S2/issues/2388
+ it('should frozen correctly desc sorted data', () => {
+ const sortFieldId = 'number';
+
+ Object.defineProperty(dataSet.spreadsheet, 'options', {
+ value: {
+ frozenRowCount: 1,
+ frozenTrailingRowCount: 1,
+ },
+ });
+
+ dataSet.sortParams = [
+ {
+ sortFieldId,
+ sortMethod: 'desc',
+ },
+ ];
+
+ dataSet.handleDimensionValuesSort();
+
+ expect(dataSet.getDisplayDataSet()).toHaveLength(32);
+ expect(first(dataSet.getDisplayDataSet())).toMatchInlineSnapshot(`
+ Object {
+ "city": "杭州市",
+ "number": 7789,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ }
+ `);
+ expect(last(dataSet.getDisplayDataSet())).toMatchInlineSnapshot(`
+ Object {
+ "city": "绵阳市",
+ "number": 245,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ }
+ `);
+ });
+
+ it('should frozen correctly asc sorted data', () => {
+ const sortFieldId = 'number';
+
+ Object.defineProperty(dataSet.spreadsheet, 'options', {
+ value: {
+ frozenRowCount: 1,
+ frozenTrailingRowCount: 1,
+ },
+ });
+
+ dataSet.sortParams = [
+ {
+ sortFieldId,
+ sortMethod: 'asc',
+ },
+ ];
+
+ dataSet.handleDimensionValuesSort();
+
+ expect(dataSet.getDisplayDataSet()).toHaveLength(32);
+ expect(first(dataSet.getDisplayDataSet())).toMatchInlineSnapshot(`
+ Object {
+ "city": "绵阳市",
+ "number": 245,
+ "province": "四川省",
+ "sub_type": "笔",
+ "type": "办公用品",
+ }
+ `);
+ expect(last(dataSet.getDisplayDataSet())).toMatchInlineSnapshot(`
+ Object {
+ "city": "杭州市",
+ "number": 7789,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ }
+ `);
+ });
});
});
diff --git a/packages/s2-core/__tests__/unit/facet/__snapshots__/table-facet-spec.ts.snap b/packages/s2-core/__tests__/unit/facet/__snapshots__/table-facet-spec.ts.snap
new file mode 100644
index 0000000000..df5e1dc0ba
--- /dev/null
+++ b/packages/s2-core/__tests__/unit/facet/__snapshots__/table-facet-spec.ts.snap
@@ -0,0 +1,145 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Table Mode Facet Test With Adaptive Layout should get correct col layout col hierarchy coordinate with adaptive layout 1`] = `
+Array [
+ Object {
+ "height": 30,
+ "width": 119.8,
+ "x": 0,
+ "y": 0,
+ },
+ Object {
+ "height": 30,
+ "width": 119.8,
+ "x": 119.8,
+ "y": 0,
+ },
+ Object {
+ "height": 30,
+ "width": 119.8,
+ "x": 239.6,
+ "y": 0,
+ },
+ Object {
+ "height": 30,
+ "width": 119.8,
+ "x": 359.4,
+ "y": 0,
+ },
+ Object {
+ "height": 30,
+ "width": 119.8,
+ "x": 479.2,
+ "y": 0,
+ },
+]
+`;
+
+exports[`Table Mode Facet Test With Adaptive Layout should get correct col layout with seriesNumber col hierarchy coordinate with adaptive layout with seriesNumber 1`] = `
+Array [
+ Object {
+ "height": 30,
+ "width": 103.8,
+ "x": 80,
+ "y": 0,
+ },
+ Object {
+ "height": 30,
+ "width": 103.8,
+ "x": 183.8,
+ "y": 0,
+ },
+ Object {
+ "height": 30,
+ "width": 103.8,
+ "x": 287.6,
+ "y": 0,
+ },
+ Object {
+ "height": 30,
+ "width": 103.8,
+ "x": 391.40000000000003,
+ "y": 0,
+ },
+ Object {
+ "height": 30,
+ "width": 103.8,
+ "x": 495.20000000000005,
+ "y": 0,
+ },
+]
+`;
+
+exports[`Table Mode Facet With Column Grouping Frozen Test should get correct frozenInfo 1`] = `
+Object {
+ "frozenCol": Object {
+ "range": Array [
+ 0,
+ 0,
+ ],
+ "width": 199.66,
+ "x": 0,
+ },
+ "frozenRow": Object {
+ "height": 60,
+ "range": Array [
+ 0,
+ 1,
+ ],
+ "y": 0,
+ },
+ "frozenTrailingCol": Object {
+ "range": Array [
+ 2,
+ 2,
+ ],
+ "width": 199.66,
+ "x": 399.34000000000003,
+ },
+ "frozenTrailingRow": Object {
+ "height": 60,
+ "range": Array [
+ 30,
+ 31,
+ ],
+ "y": 502,
+ },
+}
+`;
+
+exports[`Table Mode Facet With Frozen Test should get correct frozenInfo 1`] = `
+Object {
+ "frozenCol": Object {
+ "range": Array [
+ 0,
+ 1,
+ ],
+ "width": 239.6,
+ "x": 0,
+ },
+ "frozenRow": Object {
+ "height": 60,
+ "range": Array [
+ 0,
+ 1,
+ ],
+ "y": 0,
+ },
+ "frozenTrailingCol": Object {
+ "range": Array [
+ 3,
+ 4,
+ ],
+ "width": 239.60000000000002,
+ "x": 359.4,
+ },
+ "frozenTrailingRow": Object {
+ "height": 60,
+ "range": Array [
+ 30,
+ 31,
+ ],
+ "y": 502,
+ },
+}
+`;
diff --git a/packages/s2-core/__tests__/unit/facet/bbox/cornerBBox-spec.ts b/packages/s2-core/__tests__/unit/facet/bbox/corner-bbox-spec.ts
similarity index 98%
rename from packages/s2-core/__tests__/unit/facet/bbox/cornerBBox-spec.ts
rename to packages/s2-core/__tests__/unit/facet/bbox/corner-bbox-spec.ts
index 6381e67460..229ef9cde7 100644
--- a/packages/s2-core/__tests__/unit/facet/bbox/cornerBBox-spec.ts
+++ b/packages/s2-core/__tests__/unit/facet/bbox/corner-bbox-spec.ts
@@ -1,5 +1,5 @@
import type { BaseFacet } from '@/facet/base-facet';
-import { CornerBBox } from '@/facet/bbox/cornerBBox';
+import { CornerBBox } from '@/facet/bbox/corner-bbox';
describe('cornerBBox test', () => {
let mockFacet: BaseFacet;
diff --git a/packages/s2-core/__tests__/unit/facet/bbox/panelBBox-spec.ts b/packages/s2-core/__tests__/unit/facet/bbox/panel-bbox-spec.ts
similarity index 98%
rename from packages/s2-core/__tests__/unit/facet/bbox/panelBBox-spec.ts
rename to packages/s2-core/__tests__/unit/facet/bbox/panel-bbox-spec.ts
index f758ee9ed0..e6635f0a66 100644
--- a/packages/s2-core/__tests__/unit/facet/bbox/panelBBox-spec.ts
+++ b/packages/s2-core/__tests__/unit/facet/bbox/panel-bbox-spec.ts
@@ -1,6 +1,6 @@
import type { S2Options, ThemeCfg } from '@/common';
import type { BaseFacet } from '@/facet/base-facet';
-import { PanelBBox } from '@/facet/bbox/panelBBox';
+import { PanelBBox } from '@/facet/bbox/panel-bbox';
describe('PanelBBox Tests', () => {
const layoutResult = {
diff --git a/packages/s2-core/__tests__/unit/facet/header/frozen-row-spec.ts b/packages/s2-core/__tests__/unit/facet/header/frozen-row-spec.ts
new file mode 100644
index 0000000000..43e038b1b0
--- /dev/null
+++ b/packages/s2-core/__tests__/unit/facet/header/frozen-row-spec.ts
@@ -0,0 +1,51 @@
+import { createPivotSheet } from 'tests/util/helpers';
+import { get } from 'lodash';
+import type { HierarchyType, RowHeader } from '../../../../src';
+import type { FrozenFacet } from '../../../../src/facet/frozen-facet';
+import { DEFAULT_OPTIONS, FrozenGroupType } from '@/common';
+import { RowCell } from '@/cell';
+
+const s2 = createPivotSheet(
+ {
+ ...DEFAULT_OPTIONS,
+ frozen: {
+ firstRow: true,
+ },
+ totals: { row: { showGrandTotals: true, reverseGrandTotalsLayout: true } },
+ showSeriesNumber: false,
+ },
+ { useSimpleData: false },
+);
+
+describe('Pivot Frozen Row Header Test', () => {
+ test.each(['grid', 'tree'] as HierarchyType[])(
+ 'frozen row header group api',
+ async (hierarchyType) => {
+ s2.setOptions({ hierarchyType });
+ await s2.render();
+
+ const rowHeader = s2.facet.rowHeader as RowHeader;
+
+ expect(rowHeader).toBeTruthy();
+ expect(rowHeader.frozenRowGroup).toBeTruthy();
+ expect(rowHeader.scrollGroup).toBeTruthy();
+
+ expect(rowHeader.frozenRowGroup.children).toHaveLength(1);
+ const frozenRowCell = rowHeader.frozenRowGroup.children[0];
+
+ expect(frozenRowCell instanceof RowCell).toBeTrue();
+ expect(get(frozenRowCell, 'meta.height')).toEqual(30);
+
+ expect(rowHeader.scrollGroup.getChildren()).toHaveLength(10);
+ const scrollCell = rowHeader.scrollGroup.getChildren()[0];
+
+ expect(scrollCell instanceof RowCell).toBeTrue();
+ expect(get(frozenRowCell, 'meta.height')).toEqual(30);
+
+ expect(
+ (s2.facet as FrozenFacet).frozenGroupInfo[FrozenGroupType.FROZEN_ROW]
+ .height,
+ ).toBe(30);
+ },
+ );
+});
diff --git a/packages/s2-core/__tests__/unit/facet/layout/col-node-width-spec.ts b/packages/s2-core/__tests__/unit/facet/layout/col-node-width-spec.ts
index 271b8c12de..b6d1e7fc98 100644
--- a/packages/s2-core/__tests__/unit/facet/layout/col-node-width-spec.ts
+++ b/packages/s2-core/__tests__/unit/facet/layout/col-node-width-spec.ts
@@ -2,7 +2,7 @@ import * as mockDataConfig from 'tests/data/simple-data.json';
import * as mockTableDataConfig from 'tests/data/simple-table-data.json';
import { getContainer } from 'tests/util/helpers';
import { PivotSheet, TableSheet } from '@/sheet-type';
-import type { S2DataConfig, S2Options } from '@/common';
+import { LayoutWidthType, type S2DataConfig, type S2Options } from '@/common';
const s2options: S2Options = {
width: 800,
@@ -35,7 +35,7 @@ describe('Col width Test', () => {
});
test('get correct width in layoutWidthType adaptive mode', () => {
- expect(s2.facet.getColLeafNodes()[0].width).toBe(200);
+ expect(s2.facet.getColLeafNodes()[0].width).toBe(199.5);
});
test('get correct width in layoutWidthType adaptive mode when enable series number', async () => {
@@ -44,7 +44,7 @@ describe('Col width Test', () => {
});
await s2.render();
- expect(s2.facet.getColLeafNodes()[0].width).toBe(180);
+ expect(s2.facet.getColLeafNodes()[0].width).toBe(179.5);
});
test('get correct width in layoutWidthType adaptive tree mode', async () => {
@@ -69,7 +69,7 @@ describe('Col width Test', () => {
test('get correct width in layoutWidthType compact mode', async () => {
s2.setOptions({
style: {
- layoutWidthType: 'compact',
+ layoutWidthType: LayoutWidthType.Compact,
},
});
await s2.render();
@@ -92,7 +92,7 @@ describe('Col width Test', () => {
});
s2.setOptions({
style: {
- layoutWidthType: 'compact',
+ layoutWidthType: LayoutWidthType.Compact,
},
});
await s2.render();
@@ -126,7 +126,7 @@ describe('Col width Test', () => {
test('get correct width in layoutWidthType compact mode', async () => {
s2.setOptions({
style: {
- layoutWidthType: 'compact',
+ layoutWidthType: LayoutWidthType.Compact,
},
});
await s2.render();
diff --git a/packages/s2-core/__tests__/unit/facet/layout/row-node-width-spec.ts b/packages/s2-core/__tests__/unit/facet/layout/row-node-width-spec.ts
index dc208af2d9..a2c2141155 100644
--- a/packages/s2-core/__tests__/unit/facet/layout/row-node-width-spec.ts
+++ b/packages/s2-core/__tests__/unit/facet/layout/row-node-width-spec.ts
@@ -1,7 +1,7 @@
import * as mockDataConfig from 'tests/data/data-issue-372.json';
import { getContainer } from 'tests/util/helpers';
import { PivotSheet } from '@/sheet-type';
-import type { S2Options } from '@/common';
+import { LayoutWidthType, type S2Options } from '@/common';
const s2options: S2Options = {
width: 800,
@@ -25,7 +25,7 @@ describe('Row width Test in grid mode', () => {
test('get the correct custom width of row nodes when the layoutWidthType equals colAdaptive', async () => {
s2.setOptions({
style: {
- layoutWidthType: 'compact',
+ layoutWidthType: LayoutWidthType.Compact,
rowCell: { width: 50 },
},
});
@@ -39,7 +39,7 @@ describe('Row width Test in grid mode', () => {
test('get the correct custom width of row nodes when the layoutWidthType equals compact', async () => {
s2.setOptions({
style: {
- layoutWidthType: 'compact',
+ layoutWidthType: LayoutWidthType.Compact,
rowCell: { width: 20 },
},
});
diff --git a/packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts b/packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts
index 83d37f218b..e24c1868fe 100644
--- a/packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts
+++ b/packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts
@@ -2,24 +2,29 @@
* pivot mode pivot test.
*/
import { Canvas, Group, Rect, type CanvasConfig } from '@antv/g';
-import { assembleDataCfg, assembleOptions } from 'tests/util';
-import { size, find } from 'lodash';
import { Renderer } from '@antv/g-canvas';
+import { find, size } from 'lodash';
+import { assembleDataCfg, assembleOptions } from 'tests/util';
+import { FrozenGroupType } from '../../../src';
+import { createFakeSpreadSheet } from '../../util/helpers';
import { getMockPivotMeta } from './util';
-import { Node } from '@/facet/layout/node';
-import { DEFAULT_TREE_ROW_CELL_WIDTH } from '@/common/constant/options';
-import type { PanelScrollGroup } from '@/group/panel-scroll-group';
-import { SpreadSheet } from '@/sheet-type';
-import { PivotDataSet } from '@/data-set/pivot-data-set';
-import { PivotFacet } from '@/facet/pivot-facet';
import { CornerCell, DataCell } from '@/cell';
+import {
+ DEFAULT_OPTIONS,
+ DEFAULT_STYLE,
+ DEFAULT_TREE_ROW_CELL_WIDTH,
+} from '@/common/constant/options';
+import type { ViewMeta } from '@/common/interface/basic';
import { Store } from '@/common/store';
-import { getTheme } from '@/theme';
-import { DEFAULT_OPTIONS, DEFAULT_STYLE } from '@/common/constant/options';
+import type { CellData } from '@/data-set/cell-data';
+import { PivotDataSet } from '@/data-set/pivot-data-set';
import { ColHeader, CornerHeader, Frame, RowHeader } from '@/facet/header';
-import type { ViewMeta } from '@/common/interface/basic';
+import { Node } from '@/facet/layout/node';
+import { PivotFacet } from '@/facet/pivot-facet';
+import type { PanelScrollGroup } from '@/group/panel-scroll-group';
import { RootInteraction } from '@/interaction/root';
-import type { CellData } from '@/data-set/cell-data';
+import { SpreadSheet } from '@/sheet-type';
+import { getTheme } from '@/theme';
jest.mock('@/interaction/root');
@@ -49,7 +54,9 @@ jest.mock('@/sheet-type', () => {
return {
dataCfg: assembleDataCfg(),
- options: assembleOptions(),
+ options: assembleOptions({
+ dataCell: (viewMeta) => new DataCell(viewMeta, viewMeta.spreadsheet),
+ }),
container,
theme: getTheme({}),
store: new Store(),
@@ -70,11 +77,20 @@ jest.mock('@/sheet-type', () => {
layoutResult: {
rowLeafNodes: [],
},
+ getLayoutResult: () => ({ rowLeafNodes: [], colLeafNodes: [] }),
getRowLeafNodes: () => [],
getRowNodes: () => [],
getColNodes: () => [],
getHiddenColumnsInfo: jest.fn(),
getCellMeta: jest.fn(),
+ getRowLeafNodeByIndex: () => [],
+ frozenGroupInfo: {
+ [FrozenGroupType.FROZEN_ROW]: {},
+ [FrozenGroupType.FROZEN_COL]: {},
+ [FrozenGroupType.FROZEN_TRAILING_ROW]: {},
+ [FrozenGroupType.FROZEN_TRAILING_COL]: {},
+ },
+ cornerBBox: {},
},
getCanvasElement: () =>
container.getContextService().getDomElement() as HTMLCanvasElement,
@@ -103,12 +119,17 @@ jest.mock('@/data-set/pivot-data-set', () => {
sortedDimensionValues,
moreThanOneValue: jest.fn(),
getField: jest.fn(),
+ transformIndexesData: actualPivotDataSet.prototype.transformIndexesData,
+ getExistValuesByDataItem:
+ actualPivotDataSet.prototype.getExistValuesByDataItem,
getFieldFormatter: actualDataSet.prototype.getFieldFormatter,
getFieldMeta: (field: string, meta: ViewMeta) => find(meta, { field }),
getFieldName: actualPivotDataSet.prototype.getFieldName,
getCellData: actualPivotDataSet.prototype.getCellData,
getCellMultiData: jest.fn(),
getDimensionValues: actualPivotDataSet.prototype.getDimensionValues,
+ getFieldsAndPivotMetaByField:
+ actualPivotDataSet.prototype.getFieldsAndPivotMetaByField,
};
}),
};
@@ -130,13 +151,16 @@ describe('Pivot Mode Facet Test', () => {
s2.options = assembleOptions({
dataCell: (viewMeta) => new DataCell(viewMeta, s2),
});
+ const facet = new PivotFacet(s2);
- const facet: PivotFacet = new PivotFacet(s2);
-
- beforeAll(async () => {
+ beforeEach(async () => {
await s2.container.ready;
});
+ afterEach(() => {
+ facet.destroy();
+ });
+
describe('should get correct hierarchy', () => {
const { dataCell, colCell } = s2.options.style!;
const { rowsHierarchy, colsHierarchy, colLeafNodes } =
@@ -155,9 +179,9 @@ describe('Pivot Mode Facet Test', () => {
expect(rowsHierarchy.getNodes(0)).toHaveLength(2);
rowsHierarchy.getLeaves().forEach((node, index) => {
- expect(node.width).toBe(99);
+ expect(Math.floor(node.width)).toBeCloseTo(99);
expect(node.height).toBe(dataCell!.height!);
- expect(node.x).toBe(99 * node.level);
+ expect(Math.floor(node.x)).toBeCloseTo(99 * node.level);
expect(node.y).toBe(node.height * index);
});
@@ -181,9 +205,9 @@ describe('Pivot Mode Facet Test', () => {
expect(colsHierarchy.getNodes(0)).toHaveLength(2);
colsHierarchy.getLeaves().forEach((node, index) => {
- expect(node.width).toBe(width);
+ expect(Math.ceil(node.width)).toBeCloseTo(width);
expect(node.height).toBe(colCell!.height);
- expect(node.x).toBe(width * index);
+ expect(Math.ceil(node.x)).toBe(width * index);
expect(node.y).toBe(node.height * node.level);
});
@@ -219,22 +243,18 @@ describe('Pivot Mode Facet Test', () => {
});
describe('should get correct result when tree mode', () => {
- s2.isHierarchyTreeType = jest.fn().mockReturnValue(true);
- s2.options = assembleOptions({
- hierarchyType: 'tree',
- });
- // 小于 DEFAULT_TREE_ROW_WIDTH
- const spy = jest.spyOn(s2, 'measureTextWidth').mockReturnValue(30);
-
- s2.dataSet = new MockPivotDataSet(s2);
- const treeFacet = new PivotFacet(s2);
- const { rowsHierarchy } = treeFacet.getLayoutResult();
+ test('row hierarchy when tree mode', () => {
+ s2.isHierarchyTreeType = jest.fn().mockReturnValue(true);
+ s2.options = assembleOptions({
+ hierarchyType: 'tree',
+ });
+ // 小于 DEFAULT_TREE_ROW_WIDTH
+ const spy = jest.spyOn(s2, 'measureTextWidth').mockReturnValue(30);
- afterAll(() => {
- spy.mockRestore();
- });
+ s2.dataSet = new MockPivotDataSet(s2);
+ const treeFacet = new PivotFacet(s2);
+ const { rowsHierarchy } = treeFacet.getLayoutResult();
- test('row hierarchy when tree mode', () => {
const { dataCell, rowCell } = s2.options.style!;
expect(rowsHierarchy.getLeaves()).toHaveLength(8);
@@ -248,31 +268,33 @@ describe('Pivot Mode Facet Test', () => {
expect(node.x).toBe(0);
expect(node.y).toBe(node.height * index);
});
+
+ spy.mockRestore();
});
});
describe('should get correct layer after render', () => {
- beforeAll(() => {
+ beforeEach(() => {
facet.render();
});
- afterAll(() => {
+ afterEach(() => {
facet.destroy();
});
test('get header after render', () => {
const { rowHeader, cornerHeader, columnHeader, centerFrame } = facet;
- expect(rowHeader instanceof RowHeader).toBeTrue();
- expect(rowHeader!.children).toHaveLength(10);
+ expect(rowHeader).toBeInstanceOf(RowHeader);
+ expect(rowHeader!.children[0].children).toHaveLength(10);
expect(rowHeader!.parsedStyle.visibility).not.toEqual('hidden');
- expect(cornerHeader instanceof CornerHeader).toBeTrue();
- expect(cornerHeader.children.length).toBe(3);
+ expect(cornerHeader).toBeInstanceOf(CornerHeader);
+ expect(cornerHeader.children).toHaveLength(2);
expect(cornerHeader.parsedStyle.visibility).not.toEqual('hidden');
- expect(columnHeader instanceof ColHeader).toBeTrue();
- expect(centerFrame instanceof Frame).toBeTrue();
+ expect(columnHeader).toBeInstanceOf(ColHeader);
+ expect(centerFrame).toBeInstanceOf(Frame);
});
test('get background after render', () => {
@@ -287,24 +309,13 @@ describe('Pivot Mode Facet Test', () => {
});
describe('should get correct result when enable series number', () => {
- const mockDataSet = new MockPivotDataSet(s2);
+ test('render correct corner header', () => {
+ const s2 = createFakeSpreadSheet();
- s2.options = assembleOptions({
- showSeriesNumber: true,
- dataCell: (fct) => new DataCell(fct, s2),
- });
- s2.dataSet = mockDataSet;
- const seriesNumberFacet = new PivotFacet(s2);
+ s2.dataSet = new MockPivotDataSet(s2);
+ const seriesNumberFacet = new PivotFacet(s2);
- beforeAll(() => {
seriesNumberFacet.render();
- });
-
- afterAll(() => {
- seriesNumberFacet.destroy();
- });
-
- test('render correct corner header', () => {
const { cornerHeader } = seriesNumberFacet;
expect(cornerHeader instanceof CornerHeader).toBeTrue();
@@ -320,7 +331,7 @@ describe('Pivot Mode Facet Test', () => {
});
it.each(['updateScrollOffset', 'scrollWithAnimation', 'scrollImmediately'])(
- 'should not throw "Cannot read property \'value\' of undefined" error if called with single offset config',
+ 'should not throw "Cannot read property \'value\' of undefined" error if called with single offset config by %s',
(method) => {
const onlyOffsetYFn = () => {
// @ts-ignore
diff --git a/packages/s2-core/__tests__/unit/facet/table-facet-spec.ts b/packages/s2-core/__tests__/unit/facet/table-facet-spec.ts
index 7a8f38966f..c5b621d547 100644
--- a/packages/s2-core/__tests__/unit/facet/table-facet-spec.ts
+++ b/packages/s2-core/__tests__/unit/facet/table-facet-spec.ts
@@ -4,15 +4,17 @@
import { Canvas, Group, type CanvasConfig } from '@antv/g';
import { Renderer } from '@antv/g-canvas';
import { assembleDataCfg, assembleOptions } from 'tests/util';
+import { pick } from 'lodash';
import { data } from '../../data/mock-dataset.json';
-import { ROOT_NODE_ID } from '@/common/constant';
+import { createFakeSpreadSheet } from '../../util/helpers';
+import { LayoutWidthType, ROOT_NODE_ID } from '@/common/constant';
import { Store } from '@/common/store';
import { TableDataSet } from '@/data-set/table-data-set';
import { TableFacet } from '@/facet/table-facet';
import { getFrozenLeafNodesCount } from '@/facet/utils';
import {
- customMerge,
Node,
+ customMerge,
type HiddenColumnsInfo,
type S2DataConfig,
type S2Options,
@@ -20,6 +22,10 @@ import {
import { SpreadSheet } from '@/sheet-type';
import { getTheme } from '@/theme';
+const actualDataSet = jest.requireActual(
+ '@/data-set/base-data-set',
+).BaseDataSet;
+
jest.mock('@/sheet-type', () => {
return {
SpreadSheet: jest.fn().mockImplementation(() => {
@@ -54,6 +60,9 @@ jest.mock('@/sheet-type', () => {
getHiddenColumnsInfo: jest.fn(),
getColNodeHeight: jest.fn(),
},
+ dataSet: {
+ isEmpty: jest.fn(),
+ },
isHierarchyTreeType: jest.fn(),
getCanvasElement: () =>
container.getContextService().getDomElement() as HTMLCanvasElement,
@@ -89,8 +98,10 @@ jest.mock('@/data-set/table-data-set', () => {
getFieldName: jest.fn(),
getDimensionValues: jest.fn(),
getDisplayDataSet: jest.fn(() => data),
- getFieldFormatter: jest.fn(),
getCellData: () => 1,
+ getFieldMeta: jest.fn(),
+ getFieldFormatter: actualDataSet.prototype.getFieldFormatter,
+ isEmpty: jest.fn(),
};
}),
};
@@ -118,6 +129,8 @@ const createMockTableFacet = (
),
});
s2.dataSet = new MockTableDataSet(s2);
+ // @ts-ignore
+ s2.dataSet.getField = jest.fn();
s2.dataSet.fields = s2.dataCfg.fields;
const facet = new TableFacet(s2);
@@ -156,38 +169,73 @@ describe('Table Mode Facet Test', () => {
expect(facet.getColLeafNodes()[0].value).toEqual(seriesNumberText);
});
+
+ describe('should get none layer when dataCfg.fields is empty', () => {
+ const spreadsheet = createFakeSpreadSheet({
+ s2DataConfig: {
+ fields: {
+ rows: [],
+ columns: [],
+ values: [],
+ },
+ },
+ });
+ const mockDataSet = new MockTableDataSet(spreadsheet);
+
+ spreadsheet.dataSet = mockDataSet;
+
+ const newFacet: TableFacet = new TableFacet(spreadsheet);
+
+ beforeEach(() => {
+ newFacet.render();
+ });
+
+ afterEach(() => {
+ newFacet.destroy();
+ });
+
+ test('can not get header after render in table sheet', () => {
+ const { rowHeader, cornerHeader, columnHeader, centerFrame } = newFacet;
+
+ expect(rowHeader).toBeFalsy();
+ expect(cornerHeader).toBeFalsy();
+ expect(columnHeader).toBeFalsy();
+ expect(centerFrame).toBeFalsy();
+ });
+
+ test('can not get series number after render in table sheet', () => {
+ const { backgroundGroup } = newFacet;
+ const rect = backgroundGroup.children[0];
+
+ expect(rect).toBeFalsy();
+ });
+ });
});
describe('Table Mode Facet Test With Adaptive Layout', () => {
describe('should get correct col layout', () => {
- const { facet, s2 } = createMockTableFacet({
- showSeriesNumber: false,
- });
- const { colCell } = s2.options.style!;
-
test('col hierarchy coordinate with adaptive layout', () => {
- const adaptiveWith = 119;
-
- facet.getColLeafNodes().forEach((node, index) => {
- expect(node.y).toBe(0);
- expect(node.x).toBe(index * adaptiveWith);
- expect(Math.round(node.width)).toBe(adaptiveWith);
- expect(node.height).toBe(colCell!.height);
+ const { facet } = createMockTableFacet({
+ showSeriesNumber: false,
});
+
+ expect(
+ facet
+ .getColLeafNodes()
+ .map((node) => pick(node, ['x', 'y', 'width', 'height'])),
+ ).toMatchSnapshot();
});
});
describe('should get correct col layout with seriesNumber', () => {
- const { facet, s2 } = createMockTableFacet({
- showSeriesNumber: true,
- });
- const { colCell } = s2.options.style!;
-
test('col hierarchy coordinate with adaptive layout with seriesNumber', () => {
+ const { facet, s2 } = createMockTableFacet({
+ showSeriesNumber: true,
+ });
+ const { colCell } = s2.options.style!;
const colLeafNodes = facet.getColLeafNodes();
const seriesNumberWidth = facet.getSeriesNumberWidth();
- const adaptiveWith = 103;
const seriesNumberNode = colLeafNodes[0];
@@ -196,12 +244,11 @@ describe('Table Mode Facet Test With Adaptive Layout', () => {
expect(seriesNumberNode.width).toBe(seriesNumberWidth);
expect(seriesNumberNode.height).toBe(colCell!.height);
- colLeafNodes.slice(1).forEach((node, index) => {
- expect(node.y).toBe(0);
- expect(node.x).toBe(index * adaptiveWith + seriesNumberWidth);
- expect(node.width).toBe(adaptiveWith);
- expect(node.height).toBe(colCell!.height);
- });
+ expect(
+ colLeafNodes
+ .slice(1)
+ .map((node) => pick(node, ['x', 'y', 'width', 'height'])),
+ ).toMatchSnapshot();
});
});
});
@@ -233,7 +280,7 @@ describe('Table Mode Facet Test With Compact Layout', () => {
},
undefined,
(spreadsheet) => {
- spreadsheet.getLayoutWidthType = () => 'compact';
+ spreadsheet.getLayoutWidthType = () => LayoutWidthType.Compact;
spreadsheet.measureTextWidth =
mockMeasureFunc as unknown as SpreadSheet['measureTextWidth'];
spreadsheet.measureTextWidthRoughly = mockMeasureFunc;
@@ -280,7 +327,7 @@ describe('Table Mode Facet Test With Compact Layout', () => {
},
undefined,
(spreadsheet) => {
- spreadsheet.getLayoutWidthType = () => 'compact';
+ spreadsheet.getLayoutWidthType = () => LayoutWidthType.Compact;
spreadsheet.measureTextWidth =
mockMeasureFunc as unknown as SpreadSheet['measureTextWidth'];
spreadsheet.measureTextWidthRoughly = mockMeasureFunc;
@@ -318,38 +365,7 @@ describe('Table Mode Facet With Frozen Test', () => {
test('should get correct frozenInfo', () => {
facet.calculateFrozenGroupInfo();
- expect(facet.frozenGroupInfo).toMatchInlineSnapshot(`
- Object {
- "frozenCol": Object {
- "range": Array [
- 0,
- 1,
- ],
- "width": 238,
- },
- "frozenRow": Object {
- "height": 60,
- "range": Array [
- 0,
- 1,
- ],
- },
- "frozenTrailingCol": Object {
- "range": Array [
- 3,
- 4,
- ],
- "width": 238,
- },
- "frozenTrailingRow": Object {
- "height": 60,
- "range": Array [
- 30,
- 31,
- ],
- },
- }
- `);
+ expect(facet.frozenGroupInfo).toMatchSnapshot();
});
test('should get correct xy indexes with frozen', () => {
@@ -378,8 +394,8 @@ describe('Table Mode Facet With Frozen Test', () => {
.getColLeafNodes()
.slice(-colCount)
.reverse()
- .map((node) => node.x),
- ).toEqual([481, 362]);
+ .map((node) => Math.floor(node.x)),
+ ).toEqual([479, 359]);
});
test('should get correct cell layout with frozenTrailingCol', () => {
@@ -390,8 +406,8 @@ describe('Table Mode Facet With Frozen Test', () => {
.getColLeafNodes()
.slice(-trailingColCount!)
.reverse()
- .map((node) => node.x),
- ).toEqual([481, 362]);
+ .map((node) => Math.floor(node.x)),
+ ).toEqual([479, 359]);
});
test('should get correct cell layout with frozenTrailingRow', () => {
@@ -643,38 +659,7 @@ describe('Table Mode Facet With Column Grouping Frozen Test', () => {
test('should get correct frozenInfo', () => {
facet.calculateFrozenGroupInfo();
- expect(facet.frozenGroupInfo).toMatchInlineSnapshot(`
- Object {
- "frozenCol": Object {
- "range": Array [
- 0,
- 0,
- ],
- "width": 199,
- },
- "frozenRow": Object {
- "height": 60,
- "range": Array [
- 0,
- 1,
- ],
- },
- "frozenTrailingCol": Object {
- "range": Array [
- 2,
- 2,
- ],
- "width": 199,
- },
- "frozenTrailingRow": Object {
- "height": 60,
- "range": Array [
- 30,
- 31,
- ],
- },
- }
- `);
+ expect(facet.frozenGroupInfo).toMatchSnapshot();
});
test('should get correct col layout with frozen col', () => {
@@ -704,12 +689,8 @@ describe('Table Mode Facet With Column Grouping Frozen Test', () => {
.getColLeafNodes()
.slice(-trailingColCount)
.reverse()
- .map((node) => node.x),
- ).toMatchInlineSnapshot(`
- Array [
- 401,
- ]
- `);
+ .map((node) => Math.floor(node.x)),
+ ).toEqual([399]);
});
test('should get correct cell layout with frozenTrailingRow', () => {
@@ -722,12 +703,7 @@ describe('Table Mode Facet With Column Grouping Frozen Test', () => {
.slice(-trailingRowCount!)
.reverse()
.map((_, idx) => getCellMeta(displayData.length - 1 - idx, 1)!.y),
- ).toMatchInlineSnapshot(`
- Array [
- 532,
- 502,
- ]
- `);
+ ).toEqual([532, 502]);
});
test('should get correct viewCellHeights result', () => {
diff --git a/packages/s2-core/__tests__/unit/facet/util.ts b/packages/s2-core/__tests__/unit/facet/util.ts
index 8df105b473..45aed17f8c 100644
--- a/packages/s2-core/__tests__/unit/facet/util.ts
+++ b/packages/s2-core/__tests__/unit/facet/util.ts
@@ -1,6 +1,8 @@
import { assembleDataCfg } from 'tests/util';
-import type { RawData } from '../../../src/common';
-import { transformIndexesData } from '@/utils/dataset/pivot-data-set';
+import {
+ getExistValues,
+ transformIndexesData,
+} from '@/utils/dataset/pivot-data-set';
/**
* 获取 Mock 数据
@@ -9,17 +11,20 @@ export function getMockPivotMeta() {
const sortedDimensionValues = {};
const rawRowPivotMeta = new Map();
const rawColPivotMeta = new Map();
- const rawIndexesData: RawData[][] | RawData[] = [];
+
const { fields, data } = assembleDataCfg();
+ const rawIndexesData = {};
return transformIndexesData({
- rows: fields.rows,
- columns: fields.columns,
- values: fields.values,
- originData: data,
+ rows: fields.rows as string[],
+ columns: fields.columns as string[],
+ values: fields.values as string[],
+ data,
indexesData: rawIndexesData,
sortedDimensionValues,
rowPivotMeta: rawRowPivotMeta,
colPivotMeta: rawColPivotMeta,
+ valueInCols: true,
+ getExistValuesByDataItem: getExistValues,
});
}
diff --git a/packages/s2-core/__tests__/unit/interaction/base-interaction/click/data-cell-click-spec.ts b/packages/s2-core/__tests__/unit/interaction/base-interaction/click/data-cell-click-spec.ts
index e8fdcc89f3..a8823d2063 100644
--- a/packages/s2-core/__tests__/unit/interaction/base-interaction/click/data-cell-click-spec.ts
+++ b/packages/s2-core/__tests__/unit/interaction/base-interaction/click/data-cell-click-spec.ts
@@ -3,8 +3,6 @@ import {
createMockCellInfo,
sleep,
} from 'tests/util/helpers';
-import type { GEvent } from '@/index';
-import type { SpreadSheet } from '@/sheet-type';
import {
HOVER_FOCUS_DURATION,
InteractionName,
@@ -12,7 +10,10 @@ import {
InterceptType,
S2Event,
} from '@/common/constant';
+import type { InteractionCellHighlightOptions } from '@/common/interface';
import { CustomRect } from '@/engine';
+import type { GEvent } from '@/index';
+import type { SpreadSheet } from '@/sheet-type';
jest.mock('@/interaction/event-controller');
@@ -84,9 +85,30 @@ describe('Interaction Data Cell Click Tests', () => {
s2.emit(S2Event.DATA_CELL_CLICK, {
stopPropagation() {},
} as unknown as GEvent);
+
expect(selected).toHaveBeenCalledWith([mockCellInfo.mockCell]);
});
+ // https://github.com/antvis/S2/issues/2447
+ test('should emit cell selected event when cell unselected', () => {
+ jest
+ .spyOn(s2.interaction, 'isSelectedCell')
+ .mockImplementationOnce(() => true);
+
+ const selected = jest.fn();
+
+ s2.on(S2Event.GLOBAL_SELECTED, selected);
+
+ s2.emit(S2Event.DATA_CELL_CLICK, {
+ stopPropagation() {},
+ originalEvent: {
+ detail: 1,
+ },
+ } as unknown as GEvent);
+
+ expect(selected).toHaveBeenCalledWith([]);
+ });
+
test('should emit link field jump event when link field text click and not show tooltip', () => {
const linkFieldJump = jest.fn();
@@ -172,4 +194,66 @@ describe('Interaction Data Cell Click Tests', () => {
expect(s2.interaction.isHoverFocusState()).toBeFalsy();
expect(clearHoverTimerSpy).toHaveBeenCalledTimes(2);
});
+
+ test('should highlight the column header cell and row header cell when data cell clicked', () => {
+ const headerCellId0 = 'header-0';
+ const headerCellId1 = 'header-1';
+ const columnNode: Node[] = [
+ {
+ belongsCell: {
+ getMeta: () => ({
+ id: headerCellId0,
+ colIndex: -1,
+ rowIndex: -1,
+ }),
+ } as any,
+ id: headerCellId0,
+ } as unknown as Node,
+ {
+ belongsCell: {
+ getMeta: () => ({
+ id: headerCellId1,
+ colIndex: -1,
+ rowIndex: -1,
+ }),
+ } as any,
+ id: headerCellId1,
+ } as unknown as Node,
+ ];
+
+ s2.facet.getColNodes = jest.fn(() => columnNode) as any;
+ s2.facet.getRowNodes = jest.fn(() => []);
+
+ const firstDataCellInfo = createMockCellInfo(
+ `${headerCellId0}[&]first-data-cell`,
+ );
+
+ s2.getCell = () => firstDataCellInfo.mockCell as any;
+
+ s2.setOptions({
+ interaction: {
+ selectedCellHighlight: {
+ colHeader: true,
+ rowHeader: true,
+ } as InteractionCellHighlightOptions,
+ },
+ });
+
+ s2.interaction.updateCells = jest.fn();
+ s2.facet.getColCells = jest.fn();
+ s2.facet.getRowCells = jest.fn();
+
+ s2.emit(S2Event.DATA_CELL_CLICK, {
+ stopPropagation() {},
+ } as unknown as GEvent);
+
+ expect(s2.interaction.getState()).toEqual({
+ cells: [firstDataCellInfo.mockCellMeta],
+ stateName: InteractionStateName.SELECTED,
+ onUpdateCells: expect.any(Function),
+ });
+ expect(s2.interaction.updateCells).toHaveBeenCalled();
+ expect(s2.facet.getColCells).toHaveBeenCalled();
+ expect(s2.facet.getRowCells).toHaveBeenCalled();
+ });
});
diff --git a/packages/s2-core/__tests__/unit/interaction/base-interaction/click/row-column-click-spec.ts b/packages/s2-core/__tests__/unit/interaction/base-interaction/click/row-column-click-spec.ts
index b911a822af..52bcd2b273 100644
--- a/packages/s2-core/__tests__/unit/interaction/base-interaction/click/row-column-click-spec.ts
+++ b/packages/s2-core/__tests__/unit/interaction/base-interaction/click/row-column-click-spec.ts
@@ -9,7 +9,12 @@ import type {
ViewMeta,
} from '@/common/interface';
import type { SpreadSheet } from '@/sheet-type';
-import { InteractionStateName, S2Event } from '@/common/constant';
+import {
+ InteractionKeyboardKey,
+ InteractionStateName,
+ InterceptType,
+ S2Event,
+} from '@/common/constant';
import type { Node } from '@/facet/layout/node';
import { CustomRect } from '@/engine';
@@ -85,6 +90,42 @@ describe('Interaction Row & Column Cell Click Tests', () => {
expect(rowColumnClick.bindEvents).toBeDefined();
});
+ test.each([InteractionKeyboardKey.META, InteractionKeyboardKey.CONTROL])(
+ 'should add click intercept when %s keydown',
+ (key) => {
+ s2.emit(S2Event.GLOBAL_KEYBOARD_DOWN, {
+ key,
+ } as KeyboardEvent);
+
+ expect(s2.interaction.hasIntercepts([InterceptType.CLICK])).toBeTruthy();
+ },
+ );
+
+ test.each([InteractionKeyboardKey.META, InteractionKeyboardKey.CONTROL])(
+ 'should remove click intercept when %s keyup',
+ (key) => {
+ s2.interaction.addIntercepts([InterceptType.CLICK]);
+ s2.emit(S2Event.GLOBAL_KEYBOARD_UP, {
+ key,
+ } as KeyboardEvent);
+
+ expect(s2.interaction.hasIntercepts([InterceptType.CLICK])).toBeFalsy();
+ },
+ );
+
+ test.each([InteractionKeyboardKey.META, InteractionKeyboardKey.CONTROL])(
+ 'should remove click intercept when %s released',
+ () => {
+ Object.defineProperty(rowColumnClick, 'isMultiSelection', {
+ value: true,
+ });
+ s2.interaction.addIntercepts([InterceptType.CLICK]);
+ s2.emit(S2Event.GLOBAL_MOUSE_MOVE, {} as MouseEvent);
+
+ expect(s2.interaction.hasIntercepts([InterceptType.CLICK])).toBeFalsy();
+ },
+ );
+
// https://github.com/antvis/S2/issues/1243
test.each([S2Event.ROW_CELL_CLICK, S2Event.COL_CELL_CLICK])(
'should selected cell when %s cell clicked',
@@ -108,6 +149,7 @@ describe('Interaction Row & Column Cell Click Tests', () => {
});
expect(s2.showTooltipWithInfo).toHaveBeenCalled();
expect(selected).toHaveBeenCalled();
+ expect(s2.interaction.hasIntercepts([InterceptType.HOVER])).toBeTrue();
isSelectedCellSpy.mockRestore();
},
@@ -139,6 +181,7 @@ describe('Interaction Row & Column Cell Click Tests', () => {
expect(s2.interaction.getState().cells).toEqual([]);
expect(s2.showTooltipWithInfo).toHaveBeenCalled();
expect(selected).toHaveBeenCalled();
+ expect(s2.interaction.hasIntercepts([InterceptType.HOVER])).toBeFalse();
getInteractedCellsSpy.mockRestore();
},
diff --git a/packages/s2-core/__tests__/unit/interaction/base-interaction/hover-spec.ts b/packages/s2-core/__tests__/unit/interaction/base-interaction/hover-spec.ts
index 42bfa5ec4d..53a5c36dc8 100644
--- a/packages/s2-core/__tests__/unit/interaction/base-interaction/hover-spec.ts
+++ b/packages/s2-core/__tests__/unit/interaction/base-interaction/hover-spec.ts
@@ -32,6 +32,7 @@ describe('Interaction Hover Tests', () => {
const mockTooltipParams = [
[{ value: undefined, valueField: undefined }],
{
+ enableFormat: true,
hideSummary: true,
isTotals: undefined,
onlyShowCellText: true,
@@ -77,7 +78,7 @@ describe('Interaction Hover Tests', () => {
mockCellUpdate.mockReset();
});
- afterAll(() => {
+ afterEach(() => {
mockCellUpdate.mockRestore();
});
@@ -86,6 +87,15 @@ describe('Interaction Hover Tests', () => {
});
test('should trigger data cell hover', async () => {
+ const interactionGetHoverHighlightSpy = jest
+ .spyOn(s2.interaction, 'getHoverHighlight')
+ .mockImplementationOnce(() => ({
+ rowHeader: true,
+ colHeader: true,
+ currentRow: true,
+ currentCol: true,
+ }));
+
s2.emit(S2Event.DATA_CELL_HOVER, { target: {} } as GEvent);
expect(s2.interaction.getState()).toEqual({
cells: [mockCellMeta],
@@ -99,6 +109,37 @@ describe('Interaction Hover Tests', () => {
stateName: InteractionStateName.HOVER_FOCUS,
});
expect(s2.showTooltipWithInfo).toHaveBeenCalled();
+ expect(interactionGetHoverHighlightSpy).toHaveBeenCalled();
+ });
+
+ test('should trigger data cell hover depend on separate config', async () => {
+ s2.facet.getColCells = jest.fn();
+ s2.facet.getRowCells = jest.fn();
+
+ s2.setOptions({
+ interaction: {
+ hoverHighlight: {
+ colHeader: true,
+ rowHeader: false,
+ },
+ },
+ });
+
+ s2.emit(S2Event.DATA_CELL_HOVER, { target: {} } as GEvent);
+ expect(s2.interaction.getState()).toEqual({
+ cells: [mockCellMeta],
+ stateName: InteractionStateName.HOVER,
+ });
+
+ await sleep(1000);
+
+ expect(s2.interaction.getState()).toEqual({
+ cells: [mockCellMeta],
+ stateName: InteractionStateName.HOVER_FOCUS,
+ });
+
+ expect(s2.facet.getColCells).toHaveBeenCalled();
+ expect(s2.facet.getRowCells).not.toHaveBeenCalled();
});
test('should not trigger data cell hover when hover cell not change', () => {
@@ -283,6 +324,7 @@ describe('Interaction Hover Tests', () => {
await sleep(HOVER_FOCUS_DURATION + 200);
expect(s2.showTooltipWithInfo).toHaveBeenCalled();
+ expect(s2.hideTooltip).toHaveBeenCalled();
},
);
diff --git a/packages/s2-core/__tests__/unit/interaction/brush-selection/base-brush-selection-spec.ts b/packages/s2-core/__tests__/unit/interaction/brush-selection/base-brush-selection-spec.ts
index f1b5b92ee5..2ca03ad8d0 100644
--- a/packages/s2-core/__tests__/unit/interaction/brush-selection/base-brush-selection-spec.ts
+++ b/packages/s2-core/__tests__/unit/interaction/brush-selection/base-brush-selection-spec.ts
@@ -59,7 +59,15 @@ describe('Interaction Base Cell Brush Selection Tests', () => {
s2 = new PivotSheet(getContainer(), null as unknown as S2DataConfig, null);
await s2.render();
+
mockRootInteraction = new MockRootInteraction(s2);
+ mockRootInteraction.getBrushSelection = () => {
+ return {
+ dataCell: true,
+ rowCell: true,
+ colCell: true,
+ };
+ };
s2.getCell = jest.fn(() => startBrushDataCell) as any;
s2.facet.foregroundGroup = new Group();
s2.showTooltipWithInfo = jest.fn();
diff --git a/packages/s2-core/__tests__/unit/interaction/brush-selection/col-brush-selection-spec.ts b/packages/s2-core/__tests__/unit/interaction/brush-selection/col-brush-selection-spec.ts
index fae5b8fdfd..99b88feadd 100644
--- a/packages/s2-core/__tests__/unit/interaction/brush-selection/col-brush-selection-spec.ts
+++ b/packages/s2-core/__tests__/unit/interaction/brush-selection/col-brush-selection-spec.ts
@@ -68,11 +68,19 @@ describe('Interaction Col Cell Brush Selection Tests', () => {
},
},
});
+ await s2.render();
+
s2.showTooltipWithInfo = jest.fn();
mockRootInteraction = new MockRootInteraction(s2);
s2.getCell = jest.fn(() => startBrushColCell) as any;
+ mockRootInteraction.getBrushSelection = () => {
+ return {
+ dataCell: true,
+ rowCell: true,
+ colCell: true,
+ };
+ };
s2.interaction = mockRootInteraction;
- await s2.render();
brushSelectionInstance = new ColCellBrushSelection(s2);
brushSelectionInstance.brushSelectionStage =
@@ -203,4 +211,30 @@ describe('Interaction Col Cell Brush Selection Tests', () => {
expect(selectedFn).toHaveBeenCalledTimes(1);
expect(brushSelectionFn).toHaveBeenCalledTimes(1);
});
+
+ test('should not emit brush secletion event', () => {
+ mockRootInteraction.getBrushSelection = () => ({
+ dataCell: true,
+ rowCell: true,
+ colCell: false,
+ });
+
+ const brushSelectionFn = jest.fn();
+
+ s2.on(S2Event.COL_CELL_BRUSH_SELECTION, brushSelectionFn);
+
+ // ================== mouse down ==================
+ emitEvent(S2Event.COL_CELL_MOUSE_DOWN, { x: 200, y: 0 });
+
+ // ================== mouse move ==================
+ emitEvent(S2Event.COL_CELL_MOUSE_MOVE, {
+ clientX: 600,
+ clientY: 90,
+ });
+
+ // ================== mouse up ==================
+ emitEvent(S2Event.GLOBAL_MOUSE_UP, {});
+ // emit event
+ expect(brushSelectionFn).toHaveBeenCalledTimes(0);
+ });
});
diff --git a/packages/s2-core/__tests__/unit/interaction/brush-selection/data-brush-selection-spec.ts b/packages/s2-core/__tests__/unit/interaction/brush-selection/data-brush-selection-spec.ts
index 4aed4c4dd2..e088960cf2 100644
--- a/packages/s2-core/__tests__/unit/interaction/brush-selection/data-brush-selection-spec.ts
+++ b/packages/s2-core/__tests__/unit/interaction/brush-selection/data-brush-selection-spec.ts
@@ -115,6 +115,8 @@ describe('Interaction Data Cell Brush Selection Tests', () => {
null as unknown as S2DataConfig,
null as unknown as S2Options,
);
+ await s2.render();
+
mockRootInteraction = new MockRootInteraction(s2);
s2.getCell = jest.fn(() => startBrushDataCell) as any;
s2.showTooltipWithInfo = jest.fn();
@@ -126,8 +128,14 @@ describe('Interaction Data Cell Brush Selection Tests', () => {
currentCol: false,
};
};
+ mockRootInteraction.getBrushSelection = () => {
+ return {
+ dataCell: true,
+ rowCell: true,
+ colCell: true,
+ };
+ };
s2.interaction = mockRootInteraction;
- await s2.render();
s2.facet.getDataCells = () => panelGroupAllDataCells;
s2.facet.getLayoutResult = () =>
({
@@ -462,15 +470,23 @@ describe('Interaction Data Cell Brush Selection Tests', () => {
(facet as TableFacet).frozenGroupInfo = {
[FrozenGroupType.FROZEN_COL]: {
width: 100,
+ x: 0,
+ range: [],
},
[FrozenGroupType.FROZEN_TRAILING_COL]: {
width: 100,
+ x: 0,
+ range: [],
},
[FrozenGroupType.FROZEN_ROW]: {
height: 0,
+ y: 0,
+ range: [],
},
[FrozenGroupType.FROZEN_TRAILING_ROW]: {
height: 0,
+ y: 0,
+ range: [],
},
};
@@ -488,16 +504,24 @@ describe('Interaction Data Cell Brush Selection Tests', () => {
(facet as TableFacet).frozenGroupInfo = {
[FrozenGroupType.FROZEN_COL]: {
+ x: 0,
width: 0,
+ range: [],
},
[FrozenGroupType.FROZEN_TRAILING_COL]: {
+ x: 0,
width: 0,
+ range: [],
},
[FrozenGroupType.FROZEN_ROW]: {
+ y: 0,
+ range: [],
height: 100,
},
[FrozenGroupType.FROZEN_TRAILING_ROW]: {
height: 100,
+ y: 0,
+ range: [],
},
};
expect(getScrollOffsetForRow(7, ScrollDirection.SCROLL_UP, s2)).toBe(600);
@@ -519,15 +543,23 @@ describe('Interaction Data Cell Brush Selection Tests', () => {
(s2.facet as TableFacet).frozenGroupInfo = {
[FrozenGroupType.FROZEN_COL]: {
+ width: 0,
+ x: 0,
range: [0, 1],
},
[FrozenGroupType.FROZEN_TRAILING_COL]: {
+ width: 0,
+ x: 0,
range: [8, 9],
},
[FrozenGroupType.FROZEN_ROW]: {
+ y: 0,
+ height: 0,
range: [0, 1],
},
[FrozenGroupType.FROZEN_TRAILING_ROW]: {
+ y: 0,
+ height: 0,
range: [8, 9],
},
};
@@ -541,4 +573,30 @@ describe('Interaction Data Cell Brush Selection Tests', () => {
expect(validateXIndex(8)).toBe(null);
expect(validateXIndex(7)).toBe(7);
});
+
+ test('should not emit brush selection event', () => {
+ mockRootInteraction.getBrushSelection = () => ({
+ dataCell: false,
+ rowCell: true,
+ colCell: true,
+ });
+
+ const brushSelectionFn = jest.fn();
+
+ s2.on(S2Event.DATA_CELL_BRUSH_SELECTION, brushSelectionFn);
+
+ // ================== mouse down ==================
+ emitEvent(S2Event.DATA_CELL_MOUSE_DOWN, { x: 10, y: 20 });
+
+ // ================== mouse move ==================
+ emitGlobalEvent(S2Event.GLOBAL_MOUSE_MOVE, {
+ clientX: 100,
+ clientY: 200,
+ });
+
+ // ================== mouse up ==================
+ emitEvent(S2Event.GLOBAL_MOUSE_UP, {});
+ // emit event
+ expect(brushSelectionFn).toHaveBeenCalledTimes(0);
+ });
});
diff --git a/packages/s2-core/__tests__/unit/interaction/brush-selection/row-brush-selection-spec.ts b/packages/s2-core/__tests__/unit/interaction/brush-selection/row-brush-selection-spec.ts
index 797ba740a1..d36a16a44b 100644
--- a/packages/s2-core/__tests__/unit/interaction/brush-selection/row-brush-selection-spec.ts
+++ b/packages/s2-core/__tests__/unit/interaction/brush-selection/row-brush-selection-spec.ts
@@ -68,11 +68,19 @@ describe('Interaction Row Cell Brush Selection Tests', () => {
},
});
+ await s2.render();
+
s2.showTooltipWithInfo = jest.fn();
s2.getCell = jest.fn(() => startBrushRowCell) as any;
mockRootInteraction = new MockRootInteraction(s2);
+ mockRootInteraction.getBrushSelection = () => {
+ return {
+ dataCell: true,
+ rowCell: true,
+ colCell: true,
+ };
+ };
s2.interaction = mockRootInteraction;
- await s2.render();
brushSelectionInstance = new RowCellBrushSelection(s2);
brushSelectionInstance.brushSelectionStage =
@@ -250,4 +258,28 @@ describe('Interaction Row Cell Brush Selection Tests', () => {
// get brush range selected cells
expect(brushSelectionInstance.brushRangeCells.length).toEqual(8);
});
+
+ test('should not emit brush secletion event', () => {
+ mockRootInteraction.getBrushSelection = () => ({
+ dataCell: true,
+ rowCell: false,
+ colCell: true,
+ });
+
+ const brushSelectionFn = jest.fn();
+
+ s2.on(S2Event.ROW_CELL_BRUSH_SELECTION, brushSelectionFn);
+
+ // ================== mouse down ==================
+ emitEvent(S2Event.ROW_CELL_MOUSE_DOWN, { x: 10, y: 90 });
+
+ s2.getCell = jest.fn(() => endBrushRowCell) as any;
+ // ================== mouse move ==================
+ emitEvent(S2Event.GLOBAL_MOUSE_MOVE, { clientX: 180, clientY: 400 });
+
+ // ================== mouse up ==================
+ emitEvent(S2Event.GLOBAL_MOUSE_UP, {});
+ // emit event
+ expect(brushSelectionFn).toHaveBeenCalledTimes(0);
+ });
});
diff --git a/packages/s2-core/__tests__/unit/interaction/data-cell-multi-selection-spec.ts b/packages/s2-core/__tests__/unit/interaction/data-cell-multi-selection-spec.ts
index b546e9ca74..31ce8676bf 100644
--- a/packages/s2-core/__tests__/unit/interaction/data-cell-multi-selection-spec.ts
+++ b/packages/s2-core/__tests__/unit/interaction/data-cell-multi-selection-spec.ts
@@ -40,7 +40,7 @@ describe('Interaction Data Cell Multi Selection Tests', () => {
});
test.each([InteractionKeyboardKey.META, InteractionKeyboardKey.CONTROL])(
- 'should add click intercept when keydown',
+ 'should add click intercept when %s keydown',
(key) => {
s2.emit(S2Event.GLOBAL_KEYBOARD_DOWN, {
key,
@@ -51,8 +51,9 @@ describe('Interaction Data Cell Multi Selection Tests', () => {
);
test.each([InteractionKeyboardKey.META, InteractionKeyboardKey.CONTROL])(
- 'should remove click intercept when keyup',
+ 'should remove click intercept when %s keyup',
(key) => {
+ s2.interaction.addIntercepts([InterceptType.CLICK]);
s2.emit(S2Event.GLOBAL_KEYBOARD_UP, {
key,
} as KeyboardEvent);
@@ -61,6 +62,19 @@ describe('Interaction Data Cell Multi Selection Tests', () => {
},
);
+ test.each([InteractionKeyboardKey.META, InteractionKeyboardKey.CONTROL])(
+ 'should remove click intercept when %s released',
+ () => {
+ Object.defineProperty(dataCellMultiSelection, 'isMultiSelection', {
+ value: true,
+ });
+ s2.interaction.addIntercepts([InterceptType.CLICK]);
+ s2.emit(S2Event.GLOBAL_MOUSE_MOVE, {} as MouseEvent);
+
+ expect(s2.interaction.hasIntercepts([InterceptType.CLICK])).toBeFalsy();
+ },
+ );
+
test.each([InteractionKeyboardKey.META, InteractionKeyboardKey.CONTROL])(
'should select multiple data cell',
(key) => {
diff --git a/packages/s2-core/__tests__/unit/interaction/event-controller-spec.ts b/packages/s2-core/__tests__/unit/interaction/event-controller-spec.ts
index ba67172c53..0eb3b690ac 100644
--- a/packages/s2-core/__tests__/unit/interaction/event-controller-spec.ts
+++ b/packages/s2-core/__tests__/unit/interaction/event-controller-spec.ts
@@ -125,12 +125,11 @@ describe('Interaction Event Controller Tests', () => {
renderer: new Renderer() as unknown as CanvasConfig['renderer'],
});
spreadsheet.facet = {
+ ...spreadsheet.facet,
panelBBox: {
maxX: s2Options.width,
maxY: s2Options.height,
} as BBox,
- getDataCells: jest.fn(),
- getCells: jest.fn(),
} as unknown as BaseFacet;
spreadsheet.interaction = new RootInteraction(
spreadsheet as unknown as SpreadSheet,
@@ -549,14 +548,18 @@ describe('Interaction Event Controller Tests', () => {
test('should reset if current mouse inside the canvas container, but outside the panel facet', () => {
spreadsheet.facet = {
+ ...spreadsheet.facet,
panelBBox: {
maxX: 100,
maxY: 100,
} as BBox,
} as BaseFacet;
+
+ const selected = jest.fn();
const reset = jest.fn();
spreadsheet.on(S2Event.GLOBAL_RESET, reset);
+ spreadsheet.on(S2Event.GLOBAL_SELECTED, selected);
const pointInCanvas = spreadsheet.container.viewport2Client({
x: 120,
@@ -571,25 +574,31 @@ describe('Interaction Event Controller Tests', () => {
} as MouseEventInit),
);
+ expect(selected).toHaveBeenCalledWith([]);
expect(reset).toHaveBeenCalled();
expect(spreadsheet.interaction.reset).toHaveBeenCalled();
});
test('should reset if press ecs', () => {
spreadsheet.facet = {
+ ...spreadsheet.facet,
panelBBox: {
maxX: 100,
maxY: 100,
} as BBox,
} as BaseFacet;
+
+ const selected = jest.fn();
const reset = jest.fn();
spreadsheet.on(S2Event.GLOBAL_RESET, reset);
+ spreadsheet.on(S2Event.GLOBAL_SELECTED, selected);
window.dispatchEvent(
new KeyboardEvent('keydown', { key: InteractionKeyboardKey.ESC }),
);
+ expect(selected).toHaveBeenCalledWith([]);
expect(reset).toHaveBeenCalled();
expect(spreadsheet.interaction.reset).toHaveBeenCalled();
});
@@ -664,6 +673,7 @@ describe('Interaction Event Controller Tests', () => {
test('should disable reset if autoResetSheetStyle set to false', () => {
spreadsheet.facet = {
+ ...spreadsheet.facet,
panelBBox: {
maxX: 100,
maxY: 100,
diff --git a/packages/s2-core/__tests__/unit/interaction/range-selection-spec.ts b/packages/s2-core/__tests__/unit/interaction/range-selection-spec.ts
index 89ad7f4935..20da43616f 100644
--- a/packages/s2-core/__tests__/unit/interaction/range-selection-spec.ts
+++ b/packages/s2-core/__tests__/unit/interaction/range-selection-spec.ts
@@ -10,10 +10,12 @@ import {
S2Event,
} from '@/common/constant';
import { RangeSelection } from '@/interaction/range-selection';
+import { getCellMeta } from '@/utils';
jest.mock('@/utils/tooltip');
jest.mock('@/interaction/event-controller');
jest.mock('@/interaction/base-interaction/click/data-cell-click');
+jest.mock('@/interaction/base-interaction/click/row-column-click');
describe('Interaction Range Selection Tests', () => {
let rangeSelection: RangeSelection;
@@ -47,6 +49,7 @@ describe('Interaction Range Selection Tests', () => {
});
test('should remove click intercept when shift keyup', () => {
+ s2.interaction.addIntercepts([InterceptType.CLICK]);
s2.emit(S2Event.GLOBAL_KEYBOARD_UP, {
key: InteractionKeyboardKey.SHIFT,
} as KeyboardEvent);
@@ -54,6 +57,16 @@ describe('Interaction Range Selection Tests', () => {
expect(s2.interaction.hasIntercepts([InterceptType.CLICK])).toBeFalsy();
});
+ test('should remove click intercept when shift released', () => {
+ Object.defineProperty(rangeSelection, 'isRangeSelection', {
+ value: true,
+ });
+ s2.interaction.addIntercepts([InterceptType.CLICK]);
+ s2.emit(S2Event.GLOBAL_MOUSE_MOVE, {} as MouseEvent);
+
+ expect(s2.interaction.hasIntercepts([InterceptType.CLICK])).toBeFalsy();
+ });
+
test('should set last clicked cell', () => {
s2.interaction.changeState({
cells: [],
@@ -70,6 +83,28 @@ describe('Interaction Range Selection Tests', () => {
expect(s2.store.get('lastClickedCell')).toEqual(mockCell00.mockCell);
});
+ test('should remove hover intercepts when col cell unselected', () => {
+ const mockCell00 = createMockCellInfo('3-3', { rowIndex: 3, colIndex: 3 });
+
+ s2.getCell = () => mockCell00.mockCell as any;
+
+ s2.interaction.addIntercepts([InterceptType.HOVER]);
+
+ // 有选中时,不应清理 hover 拦截
+ s2.interaction.getCells = () => [getCellMeta(mockCell00.mockCell)];
+ s2.emit(S2Event.COL_CELL_CLICK, {
+ stopPropagation() {},
+ } as unknown as GEvent);
+ expect(s2.interaction.hasIntercepts([InterceptType.HOVER])).toBeTrue();
+
+ // 无选中时,应清理拦截
+ s2.interaction.getCells = () => [];
+ s2.emit(S2Event.COL_CELL_CLICK, {
+ stopPropagation() {},
+ } as unknown as GEvent);
+ expect(s2.interaction.hasIntercepts([InterceptType.HOVER])).toBeFalse();
+ });
+
// should use data cell click interaction for single cell select
test('should not hide tooltip and change single data cell state', () => {
s2.store.set('lastClickedCell', null);
diff --git a/packages/s2-core/__tests__/unit/interaction/root-spec.ts b/packages/s2-core/__tests__/unit/interaction/root-spec.ts
index e35b3123e0..683b673589 100644
--- a/packages/s2-core/__tests__/unit/interaction/root-spec.ts
+++ b/packages/s2-core/__tests__/unit/interaction/root-spec.ts
@@ -1,13 +1,15 @@
import type { Canvas } from '@antv/g';
-import { createMockCellInfo, sleep } from 'tests/util/helpers';
import { get } from 'lodash';
+import { createMockCellInfo, sleep } from 'tests/util/helpers';
import type { PivotFacet } from '../../../src/facet';
import { Store } from '@/common/store';
import {
BaseEvent,
CellType,
+ ColCellBrushSelection,
CornerCellClick,
DataCell,
+ DataCellBrushSelection,
DataCellClick,
DataCellMultiSelection,
GuiIcon,
@@ -17,17 +19,15 @@ import {
InterceptType,
MergedCell,
MergedCellClick,
+ Node,
RangeSelection,
+ RowCellBrushSelection,
RowColumnClick,
RowColumnResize,
RowTextClick,
- type S2Options,
SelectedCellMove,
SpreadSheet,
- Node,
- DataCellBrushSelection,
- ColCellBrushSelection,
- RowCellBrushSelection,
+ type S2Options,
} from '@/index';
import { RootInteraction } from '@/interaction/root';
import { mergeCell, unmergeCell } from '@/utils/interaction/merge-cell';
@@ -68,7 +68,7 @@ describe('RootInteraction Tests', () => {
},
}) as unknown as DataCell;
- beforeAll(() => {
+ beforeEach(() => {
MockSpreadSheet.mockClear();
panelGroupAllDataCells = Array.from({ length: 10 }).map(
(_, idx) => getMockCell(idx),
@@ -100,6 +100,10 @@ describe('RootInteraction Tests', () => {
mockSpreadSheetInstance.interaction = rootInteraction;
});
+ afterEach(() => {
+ rootInteraction.destroy();
+ });
+
test('should get default interaction state', () => {
expect(rootInteraction.getState()).toEqual({
cells: [],
@@ -174,9 +178,9 @@ describe('RootInteraction Tests', () => {
// https://github.com/antvis/S2/issues/1243
test('should multi selected header cells', () => {
- const isEqualStateNameSpy = jest
+ jest
.spyOn(rootInteraction, 'isEqualStateName')
- .mockImplementation(() => false);
+ .mockImplementationOnce(() => false);
const mockCellA = createMockCellInfo('test-A').mockCell;
const mockCellB = createMockCellInfo('test-B').mockCell;
@@ -187,10 +191,7 @@ describe('RootInteraction Tests', () => {
isMultiSelection: true,
});
- expect(rootInteraction.getState().cells).toEqual([
- getCellMeta(mockCell),
- getCellMeta(mockCellA),
- ]);
+ expect(rootInteraction.getState().cells).toEqual([getCellMeta(mockCellA)]);
// 选中 cellB
rootInteraction.selectHeaderCell({
@@ -199,7 +200,6 @@ describe('RootInteraction Tests', () => {
});
expect(rootInteraction.getState().cells).toEqual([
- getCellMeta(mockCell),
getCellMeta(mockCellA),
getCellMeta(mockCellB),
]);
@@ -211,12 +211,7 @@ describe('RootInteraction Tests', () => {
});
// 取消选中
- expect(rootInteraction.getState().cells).toEqual([
- getCellMeta(mockCell),
- getCellMeta(mockCellA),
- ]);
-
- isEqualStateNameSpy.mockRestore();
+ expect(rootInteraction.getState().cells).toEqual([getCellMeta(mockCellA)]);
});
test('should call merge cells', () => {
@@ -515,7 +510,9 @@ describe('RootInteraction Tests', () => {
InterceptType.CLICK,
]),
).toBeTruthy();
+
rootInteraction.removeIntercepts([InterceptType.CLICK]);
+
expect(rootInteraction.hasIntercepts([InterceptType.CLICK])).toBeFalsy();
expect(rootInteraction.hasIntercepts([InterceptType.HOVER])).toBeTruthy();
});
@@ -671,16 +668,20 @@ describe('RootInteraction Tests', () => {
});
});
- test('should reset interaction when visibilitychange', () => {
- rootInteraction = new RootInteraction(mockSpreadSheetInstance);
- mockSpreadSheetInstance.interaction = rootInteraction;
- rootInteraction.interactions.forEach((interaction) => {
- interaction.reset = jest.fn();
- });
+ // eslint-disable-next-line jest/no-disabled-tests
+ test.skip('should reset interaction when visibilitychange', () => {
+ const resetSpyList = [...rootInteraction.interactions.values()].map(
+ (interaction) => {
+ return jest
+ .spyOn(interaction, 'reset')
+ .mockImplementationOnce(() => {});
+ },
+ );
+
window.dispatchEvent(new Event('visibilitychange'));
- rootInteraction.interactions.forEach((interaction) => {
- expect(interaction.reset).toHaveBeenCalled();
+ resetSpyList.forEach((resetSpy) => {
+ expect(resetSpy).toHaveBeenCalledTimes(1);
});
});
});
diff --git a/packages/s2-core/__tests__/unit/interaction/row-column-resize-spec.ts b/packages/s2-core/__tests__/unit/interaction/row-column-resize-spec.ts
index 26b133a534..8953d35524 100644
--- a/packages/s2-core/__tests__/unit/interaction/row-column-resize-spec.ts
+++ b/packages/s2-core/__tests__/unit/interaction/row-column-resize-spec.ts
@@ -226,6 +226,8 @@ describe('Interaction Row Column Resize Tests', () => {
{
offsetX: 10,
offsetY: 20,
+ clientX: 10,
+ clientY: 20,
},
resizeInfo,
);
@@ -233,6 +235,7 @@ describe('Interaction Row Column Resize Tests', () => {
expect(s2.store.get('resized')).toBeFalsy();
expect(rowColumnResizeInstance.resizeStartPosition).toStrictEqual({
offsetX: 10,
+ clientX: 10,
});
expect(getStartGuideLine().attr('path')).toStrictEqual([
['M', 3.5, 2],
@@ -356,12 +359,15 @@ describe('Interaction Row Column Resize Tests', () => {
{
offsetX: 10,
offsetY: 20,
+ clientX: 10,
+ clientY: 20,
},
resizeInfo,
);
expect(rowColumnResizeInstance.resizeStartPosition).toStrictEqual({
offsetY: 20,
+ clientY: 20,
});
expect(getStartGuideLine().attr('path')).toStrictEqual([
['M', 2, 3.5],
@@ -750,6 +756,8 @@ describe('Interaction Row Column Resize Tests', () => {
{
offsetX: 10,
offsetY: 20,
+ clientX: 10,
+ clientY: 20,
},
resizeInfo,
);
@@ -759,6 +767,8 @@ describe('Interaction Row Column Resize Tests', () => {
{
offsetX: 20,
offsetY: 20,
+ clientX: 20,
+ clientY: 20,
},
resizeInfo,
);
diff --git a/packages/s2-core/__tests__/unit/sheet-type/pivot-sheet-spec.ts b/packages/s2-core/__tests__/unit/sheet-type/pivot-sheet-spec.ts
index 35f4efca83..1a62ea9e86 100644
--- a/packages/s2-core/__tests__/unit/sheet-type/pivot-sheet-spec.ts
+++ b/packages/s2-core/__tests__/unit/sheet-type/pivot-sheet-spec.ts
@@ -1,6 +1,6 @@
// eslint-disable-next-line max-classes-per-file
import { Canvas, CanvasEvent } from '@antv/g';
-import { cloneDeep, get, last } from 'lodash';
+import { cloneDeep, last } from 'lodash';
import dataCfg from 'tests/data/simple-data.json';
import { waitForRender } from 'tests/util';
import { createPivotSheet, getContainer, sleep } from 'tests/util/helpers';
@@ -33,7 +33,6 @@ import {
type S2Options,
type TooltipShowOptions,
} from '@/common';
-import type { CornerCell } from '@/cell/corner-cell';
jest.mock('@/utils/hide-columns');
@@ -67,14 +66,15 @@ describe('PivotSheet Tests', () => {
let container: HTMLDivElement;
- beforeAll(async () => {
+ beforeEach(async () => {
setLang('zh_CN');
+
container = getContainer();
s2 = new PivotSheet(container, dataCfg, s2Options);
await s2.render();
});
- afterAll(() => {
+ afterEach(() => {
container?.remove();
s2?.destroy();
});
@@ -130,7 +130,7 @@ describe('PivotSheet Tests', () => {
s2.tooltip.destroy();
// remove container
- expect(s2.tooltip.container).toBe(null);
+ expect(s2.tooltip.container).toBeFalsy();
// reset position
expect(s2.tooltip.position).toEqual({
x: 0,
@@ -478,6 +478,53 @@ describe('PivotSheet Tests', () => {
expect(s2.options.showSeriesNumber).toBeTruthy();
});
+ test('should init new tooltip', () => {
+ const tooltipDestroySpy = jest
+ .spyOn(s2.tooltip, 'destroy')
+ .mockImplementationOnce(() => {});
+
+ class CustomTooltip extends BaseTooltip {}
+
+ s2.setOptions({
+ tooltip: {
+ render: (spreadsheet) => new CustomTooltip(spreadsheet),
+ },
+ });
+
+ expect(tooltipDestroySpy).toHaveBeenCalled();
+ expect(s2.tooltip).toBeInstanceOf(CustomTooltip);
+ });
+
+ test('should refresh brush selection info', () => {
+ s2.setOptions({
+ interaction: {
+ brushSelection: true,
+ },
+ });
+
+ expect(s2.interaction.getBrushSelection()).toStrictEqual({
+ dataCell: true,
+ rowCell: true,
+ colCell: true,
+ });
+
+ s2.setOptions({
+ interaction: {
+ brushSelection: {
+ dataCell: true,
+ rowCell: false,
+ colCell: false,
+ },
+ },
+ });
+
+ expect(s2.interaction.getBrushSelection()).toStrictEqual({
+ dataCell: true,
+ rowCell: false,
+ colCell: false,
+ });
+ });
+
test('should render sheet', async () => {
const facetRenderSpy = jest
.spyOn(s2, 'buildFacet' as any)
@@ -610,7 +657,7 @@ describe('PivotSheet Tests', () => {
expect(s2.facet.foregroundGroup.children).toHaveLength(9);
// panel scroll group
- expect(s2.facet.panelGroup.children).toHaveLength(1);
+ expect(s2.facet.panelGroup.children).toHaveLength(7);
expect(
s2.facet.panelGroup.getElementsByName(KEY_GROUP_PANEL_SCROLL),
).toHaveLength(1);
@@ -726,7 +773,7 @@ describe('PivotSheet Tests', () => {
const clearDrillDownDataSpy = jest
.spyOn(s2.dataSet, 'clearDrillDownData' as any)
- .mockImplementation(() => {});
+ .mockImplementation(() => true);
s2.clearDrillDownData();
@@ -742,6 +789,22 @@ describe('PivotSheet Tests', () => {
renderSpy.mockRestore();
});
+ test(`shouldn't rerender without drill down data`, () => {
+ const renderSpy = jest
+ .spyOn(s2, 'render')
+ .mockImplementationOnce(() => Promise.resolve());
+
+ const clearDrillDownDataSpy = jest
+ .spyOn(s2.dataSet, 'clearDrillDownData' as any)
+ .mockImplementation(() => false);
+
+ s2.clearDrillDownData();
+
+ expect(clearDrillDownDataSpy).toHaveBeenCalledTimes(1);
+ // rerender
+ expect(renderSpy).toHaveBeenCalledTimes(0);
+ });
+
test('should get extra field text', async () => {
const pivotSheet = new PivotSheet(
container,
@@ -754,11 +817,9 @@ describe('PivotSheet Tests', () => {
);
await pivotSheet.render();
- const extraField = last(
- pivotSheet.facet.cornerHeader.children,
- ) as CornerCell;
+ const extraField = last(pivotSheet.facet.getCornerCells());
- expect(get(extraField, 'actualText')).toEqual('数值');
+ expect(extraField?.getActualText()).toEqual('数值');
});
// https://github.com/antvis/S2/issues/1212
@@ -780,11 +841,9 @@ describe('PivotSheet Tests', () => {
await pivotSheet.render();
- const extraField = last(
- pivotSheet.facet.cornerHeader.children,
- ) as CornerCell;
+ const extraField = last(pivotSheet.facet.getCornerCells());
- expect(get(extraField, 'actualText')).toEqual(cornerExtraFieldText);
+ expect(extraField?.getActualText()).toEqual(cornerExtraFieldText);
});
describe('Tree Collapse Tests', () => {
@@ -994,7 +1053,7 @@ describe('PivotSheet Tests', () => {
{
query: undefined,
sortByMeasure: nodeMeta.value,
- sortFieldId: 'field',
+ sortFieldId: 'city',
sortMethod: 'asc',
},
]);
@@ -1010,7 +1069,7 @@ describe('PivotSheet Tests', () => {
{
query: undefined,
sortByMeasure: nodeMeta.value,
- sortFieldId: 'field',
+ sortFieldId: 'city',
sortMethod: 'desc',
},
]);
@@ -1042,7 +1101,7 @@ describe('PivotSheet Tests', () => {
{
query: { $$extra$$: 'price', type: '笔' },
sortByMeasure: 'price',
- sortFieldId: 'field',
+ sortFieldId: 'city',
sortMethod: 'asc',
},
]);
@@ -1063,7 +1122,11 @@ describe('PivotSheet Tests', () => {
s2.store.set('test', 111);
// restore mock...
- (s2.tooltip.show as jest.Mock).mockRestore();
+ const tooltipShowSpy = jest
+ .spyOn(s2.tooltip, 'show')
+ .mockImplementationOnce(() => {});
+
+ tooltipShowSpy.mockRestore();
s2.showTooltip({
position: {
x: 10,
diff --git a/packages/s2-core/__tests__/unit/sheet-type/table-sheet-spec.ts b/packages/s2-core/__tests__/unit/sheet-type/table-sheet-spec.ts
index ed8e336f0b..f3ca32b9dc 100644
--- a/packages/s2-core/__tests__/unit/sheet-type/table-sheet-spec.ts
+++ b/packages/s2-core/__tests__/unit/sheet-type/table-sheet-spec.ts
@@ -23,16 +23,16 @@ describe('TableSheet Tests', () => {
let container: HTMLDivElement;
- beforeAll(async () => {
+ beforeEach(async () => {
container = getContainer();
s2 = new TableSheet(container, dataCfg, s2Options);
await s2.render();
s2.store.set('sortMethodMap', null);
});
- afterAll(() => {
- container?.remove();
- s2?.destroy();
+ afterEach(() => {
+ // container?.remove();
+ // s2?.destroy();
});
describe('TableSheet Sort Tests', () => {
@@ -95,15 +95,10 @@ describe('TableSheet Tests', () => {
s2.groupSortByMethod('desc', node);
expect(s2.store.get('sortMethodMap')).toEqual({
- city: 'asc',
cost: 'desc',
});
expect(s2.getMenuDefaultSelectedKeys(node.id)).toEqual(['desc']);
expect(s2.dataCfg.sortParams).toEqual([
- {
- sortFieldId: 'city',
- sortMethod: 'asc',
- },
{
sortFieldId: 'cost',
sortMethod: 'desc',
@@ -267,4 +262,8 @@ describe('TableSheet Tests', () => {
expect(sheet.facet).toBeInstanceOf(TableFacet);
expect(mockRender).toHaveBeenCalledTimes(1);
});
+
+ test('should get content height', () => {
+ expect(s2.getContentHeight()).toEqual(120);
+ });
});
diff --git a/packages/s2-core/__tests__/unit/utils/__snapshots__/sort-action-spec.tsx.snap b/packages/s2-core/__tests__/unit/utils/__snapshots__/sort-action-spec.tsx.snap
new file mode 100644
index 0000000000..831f4bd7ae
--- /dev/null
+++ b/packages/s2-core/__tests__/unit/utils/__snapshots__/sort-action-spec.tsx.snap
@@ -0,0 +1,22 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`total group dimension sort test should sort by col total with group 1`] = `
+Array [
+ CellData {
+ "extraField": "price",
+ "raw": Object {
+ "city": "杭州",
+ "price": "666",
+ "type": "笔",
+ },
+ },
+ CellData {
+ "extraField": "price",
+ "raw": Object {
+ "city": "杭州",
+ "price": "999",
+ "type": "纸张",
+ },
+ },
+]
+`;
diff --git a/packages/s2-core/__tests__/unit/utils/data-set-operate-spec.tsx b/packages/s2-core/__tests__/unit/utils/data-set-operate-spec.tsx
index 5fd2938768..70efb9d846 100644
--- a/packages/s2-core/__tests__/unit/utils/data-set-operate-spec.tsx
+++ b/packages/s2-core/__tests__/unit/utils/data-set-operate-spec.tsx
@@ -1,11 +1,11 @@
import { set } from 'lodash';
+import { flattenIndexesData } from '../../../src/utils/dataset/pivot-data-set';
+import { QueryDataType, type FlattingIndexesData } from '../../../src';
+import { Aggregation } from '@/common/interface';
import {
- getListBySorted,
getAggregationAndCalcFuncByQuery,
- flattenIndexesData,
+ getListBySorted,
} from '@/utils/data-set-operate';
-import { Aggregation, type FlattingIndexesData } from '@/common/interface';
-import { DataSelectType } from '@/common/constant/total';
describe('Data Set Operate Test', () => {
const data: FlattingIndexesData = [];
@@ -27,18 +27,12 @@ describe('Data Set Operate Test', () => {
});
test('flatten out all data with all select type', () => {
- expect(flattenIndexesData(data, DataSelectType.All)).toBeArrayOfSize(6);
- });
-
- test('flatten out total data with total only type', () => {
- expect(
- flattenIndexesData(data, DataSelectType.TotalOnly),
- ).toBeArrayOfSize(2);
+ expect(flattenIndexesData(data, QueryDataType.All)).toBeArrayOfSize(6);
});
test('flatten out detail data with detail only type', () => {
expect(
- flattenIndexesData(data, DataSelectType.DetailOnly),
+ flattenIndexesData(data, QueryDataType.DetailOnly),
).toBeArrayOfSize(4);
});
});
diff --git a/packages/s2-core/__tests__/unit/utils/dataset/pivot-data-set-spec.ts b/packages/s2-core/__tests__/unit/utils/dataset/pivot-data-set-spec.ts
index 029c730360..418a6753cf 100644
--- a/packages/s2-core/__tests__/unit/utils/dataset/pivot-data-set-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/dataset/pivot-data-set-spec.ts
@@ -1,212 +1,643 @@
-import { assembleDataCfg } from 'tests/util';
-import { get } from 'lodash';
-import { data } from 'tests/data/mock-dataset.json';
+import { MULTI_VALUE } from '@/common/constant/field';
+import type { PivotMeta, SortedDimensionValues } from '@/data-set/interface';
import {
- deleteMetaById,
- transformIndexesData,
- transformDimensionsValues,
- getDataPath,
- getDimensionsWithoutPathPre,
- getDimensionsWithParentPath,
+ existDimensionTotalGroup,
+ flattenDimensionValues,
} from '@/utils/dataset/pivot-data-set';
-import type { S2DataConfig } from '@/common/interface';
-import { CellData } from '@/data-set/cell-data';
-describe('PivotDataSet util test', () => {
- const dataCfg: S2DataConfig = assembleDataCfg({
- data,
- meta: [],
- });
+describe('pivot-data-set utils test', () => {
+ let fields: string[];
+ let sortedDimensionValues: SortedDimensionValues;
+ let pivotMeta: PivotMeta;
+
+ beforeEach(() => {
+ fields = ['province', 'city', 'type', 'subType'];
- test('for deleteMetaById function', () => {
- const childrenMeta = {
- level: 0,
- children: new Map(),
- childField: 'country',
+ sortedDimensionValues = {
+ province: ['浙江省', '四川省', '$$total$$'],
+ city: [
+ '$$total$$[&]$$total$$',
+ '四川省[&]$$total$$',
+ '四川省[&]成[&]都[&]市',
+ '四川省[&]绵阳市',
+ '浙江省[&]$$total$$',
+ '浙江省[&]杭州市',
+ '浙江省[&]舟山市',
+ ],
+ type: [
+ '$$total$$[&]$$total$$[&]$$total$$',
+ '四川省[&]$$total$$[&]$$total$$',
+ '四川省[&]成[&]都[&]市[&]$$total$$',
+ '四川省[&]成[&]都[&]市[&]家具',
+ '四川省[&]成[&]都[&]市[&]办公用品',
+ '四川省[&]绵阳市[&]$$total$$',
+ '四川省[&]绵阳市[&]家具',
+ '四川省[&]绵阳市[&]办公用品',
+ '浙江省[&]$$total$$[&]$$total$$',
+ '浙江省[&]杭州市[&]$$total$$',
+ '浙江省[&]杭州市[&]家具',
+ '浙江省[&]杭州市[&]办公用品',
+ '浙江省[&]舟山市[&]$$total$$',
+ '浙江省[&]舟山市[&]家具',
+ '浙江省[&]舟山市[&]办公用品',
+ ],
+
+ subType: [
+ '$$total$$[&]$$total$$[&]$$total$$[&]$$total$$',
+ '四川省[&]$$total$$[&]$$total$$[&]$$total$$',
+ '四川省[&]成[&]都[&]市[&]$$total$$[&]$$total$$',
+ '四川省[&]成[&]都[&]市[&]家具[&]$$total$$',
+ '四川省[&]成[&]都[&]市[&]家具[&]桌子',
+ '四川省[&]成[&]都[&]市[&]家具[&]沙发',
+ '四川省[&]成[&]都[&]市[&]办公用品[&]$$total$$',
+ '四川省[&]成[&]都[&]市[&]办公用品[&]笔',
+ '四川省[&]成[&]都[&]市[&]办公用品[&]纸张',
+ '四川省[&]绵阳市[&]$$total$$[&]$$total$$',
+ '四川省[&]绵阳市[&]家具[&]$$total$$',
+ '四川省[&]绵阳市[&]家具[&]桌子',
+ '四川省[&]绵阳市[&]家具[&]沙发',
+ '四川省[&]绵阳市[&]办公用品[&]$$total$$',
+ '四川省[&]绵阳市[&]办公用品[&]笔',
+ '四川省[&]绵阳市[&]办公用品[&]纸张',
+ '浙江省[&]$$total$$[&]$$total$$[&]$$total$$',
+ '浙江省[&]杭州市[&]$$total$$[&]$$total$$',
+ '浙江省[&]杭州市[&]家具[&]$$total$$',
+ '浙江省[&]杭州市[&]家具[&]桌子',
+ '浙江省[&]杭州市[&]家具[&]沙发',
+ '浙江省[&]杭州市[&]办公用品[&]$$total$$',
+ '浙江省[&]杭州市[&]办公用品[&]笔',
+ '浙江省[&]杭州市[&]办公用品[&]纸张',
+ '浙江省[&]舟山市[&]$$total$$[&]$$total$$',
+ '浙江省[&]舟山市[&]家具[&]$$total$$',
+ '浙江省[&]舟山市[&]家具[&]桌子',
+ '浙江省[&]舟山市[&]家具[&]沙发',
+ '浙江省[&]舟山市[&]办公用品[&]$$total$$',
+ '浙江省[&]舟山市[&]办公用品[&]笔',
+ '浙江省[&]舟山市[&]办公用品[&]纸张',
+ ],
};
- const meta = new Map().set('浙江省', {
- level: 0,
- children: new Map().set('杭州市', childrenMeta),
- childField: 'city',
- });
- deleteMetaById(meta, 'root[&]浙江省');
- const result = meta.get('浙江省');
+ pivotMeta = new Map([
+ [
+ '四川省',
+ {
+ childField: 'city',
+ level: 1,
+ id: '四川省',
+ dimensions: ['四川省'],
+ children: new Map([
+ [
+ '成[&]都[&]市',
+ {
+ childField: 'type',
+ level: 1,
+ id: '四川省[&]成[&]都[&]市',
+ dimensions: ['四川省', '成[&]都[&]市'],
+ children: new Map([
+ [
+ '家具',
+ {
+ childField: 'subType',
+ level: 1,
+ id: '四川省[&]成[&]都[&]市[&]家具',
+ dimensions: ['四川省', '成[&]都[&]市', '家具'],
+ children: new Map([
+ [
+ '桌子',
+ {
+ childFiled: null,
+ id: '四川省[&]成[&]都[&]市[&]家具[&]桌子',
+ dimensions: [
+ '四川省',
+ '成[&]都[&]市',
+ '家具',
+ '桌子',
+ ],
- expect(result.childField).toBeUndefined();
- expect(result.children).toBeEmpty();
+ level: 1,
+ children: new Map(),
+ },
+ ],
+ [
+ '沙发',
+ {
+ childFiled: null,
+ level: 2,
+ id: '四川省[&]成[&]都[&]市[&]家具[&]沙发',
+ dimensions: [
+ '四川省',
+ '成[&]都[&]市',
+ '家具',
+ '沙发',
+ ],
+ children: new Map(),
+ },
+ ],
+ ]),
+ },
+ ],
+ [
+ '办公用品',
+ {
+ childField: 'subType',
+ level: 2,
+ id: '四川省[&]成[&]都[&]市[&]办公用品',
+ dimensions: ['四川省', '成[&]都[&]市', '办公用品'],
+ children: new Map([
+ [
+ '笔',
+ {
+ childFiled: null,
+ level: 1,
+ id: '四川省[&]成[&]都[&]市[&]办公用品[&]笔',
+ dimensions: [
+ '四川省',
+ '成[&]都[&]市',
+ '办公用品',
+ '笔',
+ ],
+ children: new Map(),
+ },
+ ],
+ [
+ '纸张',
+ {
+ childFiled: null,
+ level: 2,
+ id: '四川省[&]成[&]都[&]市[&]办公用品[&]纸张',
+ dimensions: [
+ '四川省',
+ '成[&]都[&]市',
+ '办公用品',
+ '纸张',
+ ],
+ children: new Map(),
+ },
+ ],
+ ]),
+ },
+ ],
+ ]),
+ },
+ ],
+ [
+ '绵阳市',
+ {
+ childField: 'type',
+ level: 2,
+ id: '四川省[&]绵阳市',
+ dimensions: ['四川省', '绵阳市'],
+ children: new Map([
+ [
+ '家具',
+ {
+ childField: 'subType',
+ level: 1,
+ id: '四川省[&]绵阳市[&]家具',
+ dimensions: ['四川省', '绵阳市', '家具'],
+ children: new Map([
+ [
+ '桌子',
+ {
+ childFiled: null,
+ level: 1,
+ id: '四川省[&]绵阳市[&]家具[&]桌子',
+ dimensions: ['四川省', '绵阳市', '家具', '桌子'],
+ children: new Map(),
+ },
+ ],
+ [
+ '沙发',
+ {
+ childFiled: null,
+ level: 2,
+ id: '四川省[&]绵阳市[&]家具[&]沙发',
+ dimensions: ['四川省', '绵阳市', '家具', '沙发'],
+ children: new Map(),
+ },
+ ],
+ ]),
+ },
+ ],
+ [
+ '办公用品',
+ {
+ childField: 'subType',
+ level: 2,
+ id: '四川省[&]绵阳市[&]办公用品',
+ dimensions: ['四川省', '绵阳市', '办公用品'],
+ children: new Map([
+ [
+ '笔',
+ {
+ childFiled: null,
+ level: 1,
+ id: '四川省[&]绵阳市[&]办公用品[&]笔',
+ dimensions: ['四川省', '绵阳市', '办公用品', '笔'],
+ children: new Map(),
+ },
+ ],
+ [
+ '纸张',
+ {
+ childFiled: null,
+ level: 2,
+ id: '四川省[&]绵阳市[&]办公用品[&]纸张',
+ dimensions: [
+ '四川省',
+ '绵阳市',
+ '办公用品',
+ '纸张',
+ ],
+ children: new Map(),
+ },
+ ],
+ ]),
+ },
+ ],
+ ]),
+ },
+ ],
+ ]),
+ },
+ ],
+ [
+ '浙江省',
+ {
+ childField: 'city',
+ level: 2,
+ id: '浙江省',
+ dimensions: ['浙江省'],
+ children: new Map([
+ [
+ '杭州市',
+ {
+ childField: 'type',
+ level: 1,
+ id: '浙江省[&]杭州市',
+ dimensions: ['浙江省', '杭州市'],
+ children: new Map([
+ [
+ '家具',
+ {
+ childField: 'subType',
+ level: 1,
+ id: '浙江省[&]杭州市[&]家具',
+ dimensions: ['浙江省', '杭州市', '家具'],
+ children: new Map([
+ [
+ '桌子',
+ {
+ childFiled: null,
+ level: 1,
+ id: '浙江省[&]杭州市[&]家具[&]桌子',
+ dimensions: ['浙江省', '杭州市', '家具', '桌子'],
+ children: new Map(),
+ },
+ ],
+ [
+ '沙发',
+ {
+ childFiled: null,
+ level: 2,
+ id: '浙江省[&]杭州市[&]家具[&]沙发',
+ dimensions: ['浙江省', '杭州市', '家具', '沙发'],
+ children: new Map(),
+ },
+ ],
+ ]),
+ },
+ ],
+ [
+ '办公用品',
+ {
+ childField: 'subType',
+ level: 2,
+ id: '浙江省[&]杭州市[&]办公用品',
+ dimensions: ['浙江省', '杭州市'],
+ children: new Map([
+ [
+ '笔',
+ {
+ childFiled: null,
+ level: 1,
+ id: '浙江省[&]杭州市[&]办公用品[&]笔',
+ dimensions: ['浙江省', '杭州市', '办公用品', '笔'],
+ children: new Map(),
+ },
+ ],
+ [
+ '纸张',
+ {
+ childFiled: null,
+ level: 2,
+ id: '浙江省[&]杭州市[&]办公用品[&]纸张',
+ dimensions: [
+ '浙江省',
+ '杭州市',
+ '办公用品',
+ '纸张',
+ ],
+ children: new Map(),
+ },
+ ],
+ ]),
+ },
+ ],
+ ]),
+ },
+ ],
+ [
+ '舟山市',
+ {
+ childField: 'type',
+ level: 2,
+ id: '浙江省[&]舟山市',
+ dimensions: ['浙江省', '舟山市'],
+ children: new Map([
+ [
+ '家具',
+ {
+ childField: 'subType',
+ level: 1,
+ id: '浙江省[&]舟山市[&]家具',
+ dimensions: ['浙江省', '舟山市', '家具'],
+ children: new Map([
+ [
+ '桌子',
+ {
+ childFiled: null,
+ level: 1,
+ id: '浙江省[&]舟山市[&]家具[&]桌子',
+ dimensions: ['浙江省', '舟山市', '家具', '桌子'],
+ children: new Map(),
+ },
+ ],
+ [
+ '沙发',
+ {
+ childFiled: null,
+ level: 2,
+ id: '浙江省[&]舟山市[&]家具[&]沙发',
+ dimensions: ['浙江省', '舟山市', '家具', '沙发'],
+ children: new Map(),
+ },
+ ],
+ ]),
+ },
+ ],
+ [
+ '办公用品',
+ {
+ childField: 'subType',
+ level: 2,
+ id: '浙江省[&]舟山市[&]办公用品',
+ dimensions: ['浙江省', '舟山市', '办公用品'],
+ children: new Map([
+ [
+ '笔',
+ {
+ childFiled: null,
+ level: 1,
+ id: '浙江省[&]舟山市[&]办公用品[&]笔',
+ dimensions: ['浙江省', '舟山市', '办公用品', '笔'],
+ children: new Map(),
+ },
+ ],
+ [
+ '纸张',
+ {
+ childFiled: null,
+ level: 2,
+ id: '浙江省[&]舟山市[&]办公用品[&]纸张',
+ dimensions: [
+ '浙江省',
+ '舟山市',
+ '办公用品',
+ '纸张',
+ ],
+ children: new Map(),
+ },
+ ],
+ ]),
+ },
+ ],
+ ]),
+ },
+ ],
+ ]),
+ },
+ ],
+ ]) as unknown as PivotMeta;
});
- test('for transformIndexesData function', () => {
- const { rows, columns, values } = dataCfg.fields;
- const sortedDimensionValues = {};
- const rowPivotMeta = new Map();
- const colPivotMeta = new Map();
- const result = transformIndexesData({
- rows,
- values,
- columns: columns as string[],
- originData: dataCfg.data,
- indexesData: [],
- sortedDimensionValues,
- rowPivotMeta,
- colPivotMeta,
- });
-
- expect(result.indexesData).toHaveLength(3);
- expect(result.paths).toHaveLength(32);
- expect(get(result.indexesData, result.paths[0])).toEqual({
- city: '杭州市',
- number: 7789,
- province: '浙江省',
- sub_type: '桌子',
- type: '家具',
- });
- expect(result.colPivotMeta?.has('家具')).toBeTrue();
- expect(result.rowPivotMeta?.has('浙江省')).toBeTrue();
+ test(`should return false if doesn't exist total group`, () => {
expect(
- getDimensionsWithoutPathPre(result.sortedDimensionValues['province']),
- ).toEqual(['浙江省', '四川省']);
- });
+ existDimensionTotalGroup(['家具', '纸张', MULTI_VALUE, MULTI_VALUE]),
+ ).toBeFalse();
- test('for transformDimensionsValues function', () => {
- const rows = ['province', 'city'];
- const data = {
- city: '杭州市',
- number: 7789,
- province: '浙江省',
- sub_type: '桌子',
- type: '家具',
- };
- const result = transformDimensionsValues(data, rows);
+ expect(
+ existDimensionTotalGroup([
+ MULTI_VALUE,
+ MULTI_VALUE,
+ MULTI_VALUE,
+ MULTI_VALUE,
+ ]),
+ ).toBeFalse();
- expect(result).toEqual(['浙江省', '杭州市']);
+ expect(
+ existDimensionTotalGroup(['四川省', '成[&]都[&]市', '办公用品', '纸张']),
+ ).toBeFalse();
});
- test('for return type of transformDimensionsValues function', () => {
- const rows = ['row0', 'row1'];
- const data = {
- row0: 0,
- number: 7789,
- row1: 1,
- sub_type: '桌子',
- type: '家具',
- };
- const result = transformDimensionsValues(data, rows);
+ test('should return true if exist total group', () => {
+ expect(
+ existDimensionTotalGroup(['四川省', MULTI_VALUE, '家具', MULTI_VALUE]),
+ ).toBeTrue();
- expect(result).toEqual(['0', '1']);
- });
+ expect(
+ existDimensionTotalGroup([MULTI_VALUE, MULTI_VALUE, '家具', MULTI_VALUE]),
+ ).toBeTrue();
- test('for getDataPath function', () => {
- const rowDimensionValues = ['浙江省', '杭州市'];
- const colDimensionValues = ['家具', '桌子'];
- const rows = ['province', 'city'];
- const columns = ['type', 'sub_type'];
- const values = ['value'];
- const rowPivotMeta = new Map();
- const colPivotMeta = new Map();
-
- const result = getDataPath({
- rowDimensionValues,
- colDimensionValues,
- rowPivotMeta,
- colPivotMeta,
- shouldCreateOrUpdate: true,
- rows,
- columns,
- values,
- });
-
- expect(result).toEqual([1, 1, 1, 1]);
+ expect(
+ existDimensionTotalGroup([MULTI_VALUE, MULTI_VALUE, MULTI_VALUE, '纸张']),
+ ).toBeTrue();
});
- test('for getDataPath function when not createIfNotExist and without rows or columns', () => {
- const rowDimensionValues = ['浙江省', '杭州市'];
- const colDimensionValues = ['家具', '桌子'];
- const rowPivotMeta = new Map();
- const colPivotMeta = new Map();
-
- getDataPath({
- rowDimensionValues,
- colDimensionValues,
- rowPivotMeta,
- colPivotMeta,
- });
- expect(rowPivotMeta.size).toEqual(0);
- expect(colPivotMeta.size).toEqual(0);
- });
+ test(`should return flatten dimension values if doesn't exist total group`, () => {
+ expect(
+ flattenDimensionValues({
+ fields,
+ pivotMeta,
+ sortedDimensionValues,
+ dimensionValues: ['四川省', '成[&]都[&]市', '办公用品', '纸张'],
+ }),
+ ).toEqual([['四川省', '成[&]都[&]市', '办公用品', '纸张']]);
- test('for getDataPath function when createIfNotExist and without rows or columns', () => {
- const rowDimensionValues = ['浙江省', '杭州市'];
- const colDimensionValues = ['家具', '桌子'];
- const rowPivotMeta = new Map();
- const colPivotMeta = new Map();
-
- getDataPath({
- rowDimensionValues,
- colDimensionValues,
- rowPivotMeta,
- colPivotMeta,
- shouldCreateOrUpdate: true,
- });
- expect(rowPivotMeta.get(rowDimensionValues[0]).childField).toBeUndefined();
- expect(colPivotMeta.get(colDimensionValues[0]).childField).toBeUndefined();
+ expect(
+ flattenDimensionValues({
+ fields,
+ pivotMeta,
+ sortedDimensionValues,
+ dimensionValues: ['四川省', '成[&]都[&]市', MULTI_VALUE, MULTI_VALUE],
+ }),
+ ).toEqual([['四川省', '成[&]都[&]市', MULTI_VALUE, MULTI_VALUE]]);
});
- test('for getDataPath function when createIfNotExist and with rows or columns', () => {
- const rowDimensionValues = ['浙江省', '杭州市'];
- const colDimensionValues = ['家具', '桌子'];
- const rows = ['province', 'city'];
- const columns = ['type', 'sub_type'];
- const rowPivotMeta = new Map();
- const colPivotMeta = new Map();
-
- getDataPath({
- rowDimensionValues,
- colDimensionValues,
- rowPivotMeta,
- colPivotMeta,
- shouldCreateOrUpdate: true,
- rows,
- columns,
- });
- expect(rowPivotMeta.get(rowDimensionValues[0]).childField).toEqual('city');
- expect(colPivotMeta.get(colDimensionValues[0]).childField).toEqual(
- 'sub_type',
- );
- });
+ test(`should return flatten dimension values if exist total group`, () => {
+ expect(
+ flattenDimensionValues({
+ fields,
+ pivotMeta,
+ sortedDimensionValues,
+ dimensionValues: [MULTI_VALUE, '成[&]都[&]市', MULTI_VALUE, '纸张'],
+ }),
+ ).toMatchInlineSnapshot(`
+ Array [
+ Array [
+ "四川省",
+ "成[&]都[&]市",
+ "办公用品",
+ "纸张",
+ ],
+ ]
+ `);
- test('for getDimensionsWithoutPathPre function', () => {
- const dimensions = ['芜湖市[&]家具[&]椅子', '芜湖市[&]家具', '芜湖市'];
+ expect(
+ flattenDimensionValues({
+ fields,
+ pivotMeta,
+ sortedDimensionValues,
+ dimensionValues: [
+ MULTI_VALUE,
+ '成[&]都[&]市',
+ MULTI_VALUE,
+ MULTI_VALUE,
+ ],
+ }),
+ ).toMatchInlineSnapshot(`
+ Array [
+ Array [
+ "四川省",
+ "成[&]都[&]市",
+ "家具",
+ "桌子",
+ ],
+ Array [
+ "四川省",
+ "成[&]都[&]市",
+ "家具",
+ "沙发",
+ ],
+ Array [
+ "四川省",
+ "成[&]都[&]市",
+ "办公用品",
+ "笔",
+ ],
+ Array [
+ "四川省",
+ "成[&]都[&]市",
+ "办公用品",
+ "纸张",
+ ],
+ ]
+ `);
- expect(getDimensionsWithoutPathPre(dimensions)).toEqual([
- '椅子',
- '家具',
- '芜湖市',
- ]);
- });
+ expect(
+ flattenDimensionValues({
+ fields,
+ pivotMeta,
+ sortedDimensionValues,
+ dimensionValues: [MULTI_VALUE, MULTI_VALUE, '办公用品', MULTI_VALUE],
+ }),
+ ).toMatchInlineSnapshot(`
+ Array [
+ Array [
+ "四川省",
+ "成[&]都[&]市",
+ "办公用品",
+ "笔",
+ ],
+ Array [
+ "四川省",
+ "成[&]都[&]市",
+ "办公用品",
+ "纸张",
+ ],
+ Array [
+ "四川省",
+ "绵阳市",
+ "办公用品",
+ "笔",
+ ],
+ Array [
+ "四川省",
+ "绵阳市",
+ "办公用品",
+ "纸张",
+ ],
+ Array [
+ "浙江省",
+ "杭州市",
+ "办公用品",
+ "笔",
+ ],
+ Array [
+ "浙江省",
+ "杭州市",
+ "办公用品",
+ "纸张",
+ ],
+ Array [
+ "浙江省",
+ "舟山市",
+ "办公用品",
+ "笔",
+ ],
+ Array [
+ "浙江省",
+ "舟山市",
+ "办公用品",
+ "纸张",
+ ],
+ ]
+ `);
- test('for getDimensionsWithParentPath function', () => {
- const field = 'city';
- const defaultDimensions = ['province', 'city'];
- const dimensions = [
- new CellData(
- {
- province: '辽宁省',
- city: '芜湖市',
- category: '家具',
- subCategory: '椅子',
- price: '',
- },
- 'price',
- ),
- ];
- const result = getDimensionsWithParentPath(
- field,
- defaultDimensions,
- dimensions,
- );
-
- expect(result).toEqual(['辽宁省[&]芜湖市']);
+ expect(
+ flattenDimensionValues({
+ fields,
+ pivotMeta,
+ sortedDimensionValues,
+ dimensionValues: ['四川省', MULTI_VALUE, '办公用品', MULTI_VALUE],
+ }),
+ ).toMatchInlineSnapshot(`
+ Array [
+ Array [
+ "四川省",
+ "成[&]都[&]市",
+ "办公用品",
+ "笔",
+ ],
+ Array [
+ "四川省",
+ "成[&]都[&]市",
+ "办公用品",
+ "纸张",
+ ],
+ Array [
+ "四川省",
+ "绵阳市",
+ "办公用品",
+ "笔",
+ ],
+ Array [
+ "四川省",
+ "绵阳市",
+ "办公用品",
+ "纸张",
+ ],
+ ]
+ `);
});
});
diff --git a/packages/s2-core/__tests__/unit/utils/export/__snapshots__/copy-spec.ts.snap b/packages/s2-core/__tests__/unit/utils/export/__snapshots__/copy-spec.ts.snap
new file mode 100644
index 0000000000..c7c3058c62
--- /dev/null
+++ b/packages/s2-core/__tests__/unit/utils/export/__snapshots__/copy-spec.ts.snap
@@ -0,0 +1,162 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`List Table Core Data Process should copy all data 1`] = `
+"1 浙江省 杭州市 家具 ### 问题摘要
+- **会话地址**: 7789
+2 浙江省 绍兴市 家具 桌子 2367
+3 浙江省 宁波市 家具 桌子 3877
+4 浙江省 舟山市 家具 桌子 4342
+5 浙江省 杭州市 家具 沙发 5343
+6 浙江省 绍兴市 家具 沙发 632
+7 浙江省 宁波市 家具 沙发 7234
+8 浙江省 舟山市 家具 沙发 834
+9 浙江省 杭州市 办公用品 笔 945
+10 浙江省 绍兴市 办公用品 笔 1304
+11 浙江省 宁波市 办公用品 笔 1145
+12 浙江省 舟山市 办公用品 笔 1432
+13 浙江省 杭州市 办公用品 纸张 1343
+14 浙江省 绍兴市 办公用品 纸张 1354
+15 浙江省 宁波市 办公用品 纸张 1523
+16 浙江省 舟山市 办公用品 纸张 1634
+17 四川省 成都市 家具 桌子 1723
+18 四川省 绵阳市 家具 桌子 1822
+19 四川省 南充市 家具 桌子 1943
+20 四川省 乐山市 家具 桌子 2330
+21 四川省 成都市 家具 沙发 2451
+22 四川省 绵阳市 家具 沙发 2244
+23 四川省 南充市 家具 沙发 2333
+24 四川省 乐山市 家具 沙发 2445
+25 四川省 成都市 办公用品 笔 2335
+26 四川省 绵阳市 办公用品 笔 245
+27 四川省 南充市 办公用品 笔 2457
+28 四川省 乐山市 办公用品 笔 2458
+29 四川省 成都市 办公用品 纸张 4004
+30 四川省 绵阳市 办公用品 纸张 3077
+31 四川省 南充市 办公用品 纸张 3551
+32 四川省 乐山市 办公用品 纸张 352"
+`;
+
+exports[`List Table Core Data Process should copy correct data when selected diagonal cells 1`] = `
+"浙江省
+
+
+
+
+
+
+
+ 宁波市"
+`;
+
+exports[`Pivot Table getBrushHeaderCopyable should copy all col data in grid mode for custom field meta 1`] = `
+Array [
+ Object {
+ "content": "家具 家具 办公用品 办公用品
+桌子 沙发 笔 纸张
+数量 数量 数量 数量",
+ "type": "text/plain",
+ },
+ Object {
+ "content": "家具 | 家具 | 办公用品 | 办公用品 |
桌子 | 沙发 | 笔 | 纸张 |
数量 | 数量 | 数量 | 数量 |
",
+ "type": "text/html",
+ },
+]
+`;
+
+exports[`Pivot Table getBrushHeaderCopyable should copy all original row data in grid mode if contains text ellipses 1`] = `
+Array [
+ Object {
+ "content": "浙江省 杭州市
+浙江省 绍兴市
+浙江省 宁波市
+浙江省 舟山市
+四川省 成都市
+四川省 绵阳市
+四川省 南充市
+四川省 乐山市",
+ "type": "text/plain",
+ },
+ Object {
+ "content": "浙江省 | 杭州市 |
浙江省 | 绍兴市 |
浙江省 | 宁波市 |
浙江省 | 舟山市 |
四川省 | 成都市 |
四川省 | 绵阳市 |
四川省 | 南充市 |
四川省 | 乐山市 |
",
+ "type": "text/html",
+ },
+]
+`;
+
+exports[`Pivot Table getBrushHeaderCopyable should copy all row data in grid mode with formatter 1`] = `
+"浙江省 杭州市 数值
+浙江省 绍兴市 数值
+浙江省 宁波市 数值
+浙江省 舟山市 数值
+四川省 成都市 数值
+四川省 绵阳市 数值
+四川省 南充市 数值
+四川省 乐山市 数值"
+`;
+
+exports[`Pivot Table getBrushHeaderCopyable should copy col total data in grid mode 1`] = `
+Array [
+ Object {
+ "content": "家具 家具 家具 办公用品 办公用品
+桌子 沙发 小计 笔 纸张
+number number 小计 number number",
+ "type": "text/plain",
+ },
+ Object {
+ "content": "家具 | 家具 | 家具 | 办公用品 | 办公用品 |
桌子 | 沙发 | 小计 | 笔 | 纸张 |
number | number | 小计 | number | number |
",
+ "type": "text/html",
+ },
+]
+`;
+
+exports[`Tree Table Core Data Process should copy normal data with header for custom field formatter if enable copyWithFormat 1`] = `
+Array [
+ Object {
+ "content": " 家具 家具 家具 办公用品 办公用品
+ 桌子 沙发 小计 笔 纸张
+ 数量 数量 数量 数量
+浙江省 18375-@ 14043-@ 32418-@ 4826-@ 5854-@
+浙江省 杭州市 7789-@ 5343-@ 13132-@ 945-@ 1343-@
+浙江省 绍兴市 2367-@ 632-@ 2999-@ 1304-@ 1354-@
+浙江省 宁波市 3877-@ 7234-@ 11111-@ 1145-@ 1523-@
+浙江省 舟山市 4342-@ 834-@ 5176-@ 1432-@ 1634-@
+四川省 7818-@ 9473-@ 17291-@ 7495-@ 10984-@
+四川省 成都市 1723-@ 2451-@ 4174-@ 2335-@ 4004-@
+四川省 绵阳市 1822-@ 2244-@ 4066-@ 245-@ 3077-@
+四川省 南充市 1943-@ 2333-@ 4276-@ 2457-@ 3551-@
+四川省 乐山市 2330-@ 2445-@ 4775-@ 2458-@ 352-@
+总计 26193-@ 23516-@ 49709-@ 12321-@ 16838-@",
+ "type": "text/plain",
+ },
+ Object {
+ "content": " | | 家具 | 家具 | 家具 | 办公用品 | 办公用品 |
| | 桌子 | 沙发 | 小计 | 笔 | 纸张 |
| | 数量 | 数量 | | 数量 | 数量 |
浙江省 | | 18375-@ | 14043-@ | 32418-@ | 4826-@ | 5854-@ |
浙江省 | 杭州市 | 7789-@ | 5343-@ | 13132-@ | 945-@ | 1343-@ |
浙江省 | 绍兴市 | 2367-@ | 632-@ | 2999-@ | 1304-@ | 1354-@ |
浙江省 | 宁波市 | 3877-@ | 7234-@ | 11111-@ | 1145-@ | 1523-@ |
浙江省 | 舟山市 | 4342-@ | 834-@ | 5176-@ | 1432-@ | 1634-@ |
四川省 | | 7818-@ | 9473-@ | 17291-@ | 7495-@ | 10984-@ |
四川省 | 成都市 | 1723-@ | 2451-@ | 4174-@ | 2335-@ | 4004-@ |
四川省 | 绵阳市 | 1822-@ | 2244-@ | 4066-@ | 245-@ | 3077-@ |
四川省 | 南充市 | 1943-@ | 2333-@ | 4276-@ | 2457-@ | 3551-@ |
四川省 | 乐山市 | 2330-@ | 2445-@ | 4775-@ | 2458-@ | 352-@ |
总计 | | 26193-@ | 23516-@ | 49709-@ | 12321-@ | 16838-@ |
",
+ "type": "text/html",
+ },
+]
+`;
+
+exports[`Tree Table Core Data Process should copy normal data with header for custom field name 1`] = `
+Array [
+ Object {
+ "content": " 家具 家具 家具 办公用品 办公用品
+ 桌子 沙发 小计 笔 纸张
+ 数量 数量 数量 数量
+浙江省 18375 14043 32418 4826 5854
+浙江省 杭州市 7789 5343 13132 945 1343
+浙江省 绍兴市 2367 632 2999 1304 1354
+浙江省 宁波市 3877 7234 11111 1145 1523
+浙江省 舟山市 4342 834 5176 1432 1634
+四川省 7818 9473 17291 7495 10984
+四川省 成都市 1723 2451 4174 2335 4004
+四川省 绵阳市 1822 2244 4066 245 3077
+四川省 南充市 1943 2333 4276 2457 3551
+四川省 乐山市 2330 2445 4775 2458 352
+总计 26193 23516 49709 12321 16838",
+ "type": "text/plain",
+ },
+ Object {
+ "content": " | | 家具 | 家具 | 家具 | 办公用品 | 办公用品 |
| | 桌子 | 沙发 | 小计 | 笔 | 纸张 |
| | 数量 | 数量 | | 数量 | 数量 |
浙江省 | | 18375 | 14043 | 32418 | 4826 | 5854 |
浙江省 | 杭州市 | 7789 | 5343 | 13132 | 945 | 1343 |
浙江省 | 绍兴市 | 2367 | 632 | 2999 | 1304 | 1354 |
浙江省 | 宁波市 | 3877 | 7234 | 11111 | 1145 | 1523 |
浙江省 | 舟山市 | 4342 | 834 | 5176 | 1432 | 1634 |
四川省 | | 7818 | 9473 | 17291 | 7495 | 10984 |
四川省 | 成都市 | 1723 | 2451 | 4174 | 2335 | 4004 |
四川省 | 绵阳市 | 1822 | 2244 | 4066 | 245 | 3077 |
四川省 | 南充市 | 1943 | 2333 | 4276 | 2457 | 3551 |
四川省 | 乐山市 | 2330 | 2445 | 4775 | 2458 | 352 |
总计 | | 26193 | 23516 | 49709 | 12321 | 16838 |
",
+ "type": "text/html",
+ },
+]
+`;
diff --git a/packages/s2-core/__tests__/unit/utils/export/__snapshots__/export-pivot-spec.ts.snap b/packages/s2-core/__tests__/unit/utils/export/__snapshots__/export-pivot-spec.ts.snap
new file mode 100644
index 0000000000..7bbda655b9
--- /dev/null
+++ b/packages/s2-core/__tests__/unit/utils/export/__snapshots__/export-pivot-spec.ts.snap
@@ -0,0 +1,13 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PivotSheet Export Test should export correct data when data is incomplete 1`] = `
+" province 浙江省 浙江省 浙江省 浙江省 四川省 四川省 四川省 四川省
+ city 杭州市 绍兴市 宁波市 舟山市 成都市 绵阳市 南充市 乐山市
+type sub_type number number number number number number number number
+家具
+家具 桌子 2367 3877 4342 1723 1822 1943 2330
+家具 沙发 632 7234 834 2451 2244 2333 2445
+办公用品
+办公用品 笔
+办公用品 纸张 1354 1523 1634 4004 3077 3551 352"
+`;
diff --git a/packages/s2-core/__tests__/unit/utils/export/__snapshots__/export-spec.ts.snap b/packages/s2-core/__tests__/unit/utils/export/__snapshots__/export-spec.ts.snap
new file mode 100644
index 0000000000..d4c258e782
--- /dev/null
+++ b/packages/s2-core/__tests__/unit/utils/export/__snapshots__/export-spec.ts.snap
@@ -0,0 +1,360 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PivotSheet Export Test should export correct $$extra$$ field name 1`] = `
+Array [
+ "type",
+ "sub_type",
+ "数值",
+ "数值",
+ "数值",
+ "数值",
+ "数值",
+ "数值",
+ "数值",
+ "数值
+",
+]
+`;
+
+exports[`TableSheet Export Test should export correct data with no series number 1`] = `
+Array [
+ "province city type sub_type number
+",
+ "浙江省 杭州市 家具 桌子 7789
+",
+ "浙江省 绍兴市 家具 桌子 2367
+",
+ "浙江省 宁波市 家具 桌子 3877
+",
+ "浙江省 舟山市 家具 桌子 4342
+",
+ "浙江省 杭州市 家具 沙发 5343
+",
+ "浙江省 绍兴市 家具 沙发 632
+",
+ "浙江省 宁波市 家具 沙发 7234
+",
+ "浙江省 舟山市 家具 沙发 834
+",
+ "浙江省 杭州市 办公用品 笔 945
+",
+ "浙江省 绍兴市 办公用品 笔 1304
+",
+ "浙江省 宁波市 办公用品 笔 1145
+",
+ "浙江省 舟山市 办公用品 笔 1432
+",
+ "浙江省 杭州市 办公用品 纸张 1343
+",
+ "浙江省 绍兴市 办公用品 纸张 1354
+",
+ "浙江省 宁波市 办公用品 纸张 1523
+",
+ "浙江省 舟山市 办公用品 纸张 1634
+",
+ "四川省 成都市 家具 桌子 1723
+",
+ "四川省 绵阳市 家具 桌子 1822
+",
+ "四川省 南充市 家具 桌子 1943
+",
+ "四川省 乐山市 家具 桌子 2330
+",
+ "四川省 成都市 家具 沙发 2451
+",
+ "四川省 绵阳市 家具 沙发 2244
+",
+ "四川省 南充市 家具 沙发 2333
+",
+ "四川省 乐山市 家具 沙发 2445
+",
+ "四川省 成都市 办公用品 笔 2335
+",
+ "四川省 绵阳市 办公用品 笔 245
+",
+ "四川省 南充市 办公用品 笔 2457
+",
+ "四川省 乐山市 办公用品 笔 2458
+",
+ "四川省 成都市 办公用品 纸张 4004
+",
+ "四川省 绵阳市 办公用品 纸张 3077
+",
+ "四川省 南充市 办公用品 纸张 3551
+",
+ "四川省 乐山市 办公用品 纸张 352
+",
+ " 家具 桌子 26193
+",
+ " 家具 49709
+",
+ " 家具 沙发 23516
+",
+ " 办公用品 29159
+",
+ " 办公用品 笔 12321
+",
+ " 办公用品 纸张 16838
+",
+ "浙江省 家具 桌子 18375
+",
+ "浙江省 家具 沙发 14043
+",
+ "浙江省 办公用品 笔 4826
+",
+ "浙江省 办公用品 纸张 5854
+",
+ "四川省 家具 桌子 7818
+",
+ "四川省 家具 沙发 9473
+",
+ "四川省 办公用品 笔 7495
+",
+ "四川省 办公用品 纸张 10984
+",
+ "浙江省 杭州市 家具 13132
+",
+ "浙江省 杭州市 办公用品 2288
+",
+ "浙江省 杭州市 15420
+",
+ "浙江省 绍兴市 家具 2999
+",
+ "浙江省 绍兴市 办公用品 2658
+",
+ "浙江省 绍兴市 5657
+",
+ "浙江省 宁波市 家具 11111
+",
+ "浙江省 宁波市 办公用品 2668
+",
+ "浙江省 宁波市 13779
+",
+ "浙江省 舟山市 家具 5176
+",
+ "浙江省 舟山市 办公用品 3066
+",
+ "浙江省 舟山市 8242
+",
+ "四川省 成都市 家具 4174
+",
+ "四川省 成都市 办公用品 6339
+",
+ "四川省 成都市 10513
+",
+ "四川省 绵阳市 家具 4066
+",
+ "四川省 绵阳市 办公用品 3322
+",
+ "四川省 绵阳市 7388
+",
+ "四川省 南充市 家具 4276
+",
+ "四川省 南充市 办公用品 6008
+",
+ "四川省 南充市 10284
+",
+ "四川省 乐山市 家具 4775
+",
+ "四川省 乐山市 办公用品 2810
+",
+ "四川省 乐山市 7585
+",
+ "浙江省 家具 32418
+",
+ "浙江省 办公用品 10680
+",
+ "浙江省 43098
+",
+ "四川省 家具 17291
+",
+ "四川省 办公用品 18479
+",
+ "四川省 35770
+",
+ " 78868",
+]
+`;
+
+exports[`TableSheet Export Test should export correct data with no series number 2`] = `
+Array [
+ "province",
+ "city",
+ "type",
+ "sub_type",
+ "number
+",
+]
+`;
+
+exports[`TableSheet Export Test should export correct data with series number 1`] = `
+Array [
+ "序号 province city 产品类型 sub_type number
+",
+ "1 浙江省 杭州市 家具 桌子 7789
+",
+ "2 浙江省 绍兴市 家具 桌子 2367
+",
+ "3 浙江省 宁波市 家具 桌子 3877
+",
+ "4 浙江省 舟山市 家具 桌子 4342
+",
+ "5 浙江省 杭州市 家具 沙发 5343
+",
+ "6 浙江省 绍兴市 家具 沙发 632
+",
+ "7 浙江省 宁波市 家具 沙发 7234
+",
+ "8 浙江省 舟山市 家具 沙发 834
+",
+ "9 浙江省 杭州市 办公用品 笔 945
+",
+ "10 浙江省 绍兴市 办公用品 笔 1304
+",
+ "11 浙江省 宁波市 办公用品 笔 1145
+",
+ "12 浙江省 舟山市 办公用品 笔 1432
+",
+ "13 浙江省 杭州市 办公用品 纸张 1343
+",
+ "14 浙江省 绍兴市 办公用品 纸张 1354
+",
+ "15 浙江省 宁波市 办公用品 纸张 1523
+",
+ "16 浙江省 舟山市 办公用品 纸张 1634
+",
+ "17 四川省 成都市 家具 桌子 1723
+",
+ "18 四川省 绵阳市 家具 桌子 1822
+",
+ "19 四川省 南充市 家具 桌子 1943
+",
+ "20 四川省 乐山市 家具 桌子 2330
+",
+ "21 四川省 成都市 家具 沙发 2451
+",
+ "22 四川省 绵阳市 家具 沙发 2244
+",
+ "23 四川省 南充市 家具 沙发 2333
+",
+ "24 四川省 乐山市 家具 沙发 2445
+",
+ "25 四川省 成都市 办公用品 笔 2335
+",
+ "26 四川省 绵阳市 办公用品 笔 245
+",
+ "27 四川省 南充市 办公用品 笔 2457
+",
+ "28 四川省 乐山市 办公用品 笔 2458
+",
+ "29 四川省 成都市 办公用品 纸张 4004
+",
+ "30 四川省 绵阳市 办公用品 纸张 3077
+",
+ "31 四川省 南充市 办公用品 纸张 3551
+",
+ "32 四川省 乐山市 办公用品 纸张 352
+",
+ "33 家具 桌子 26193
+",
+ "34 家具 49709
+",
+ "35 家具 沙发 23516
+",
+ "36 办公用品 29159
+",
+ "37 办公用品 笔 12321
+",
+ "38 办公用品 纸张 16838
+",
+ "39 浙江省 家具 桌子 18375
+",
+ "40 浙江省 家具 沙发 14043
+",
+ "41 浙江省 办公用品 笔 4826
+",
+ "42 浙江省 办公用品 纸张 5854
+",
+ "43 四川省 家具 桌子 7818
+",
+ "44 四川省 家具 沙发 9473
+",
+ "45 四川省 办公用品 笔 7495
+",
+ "46 四川省 办公用品 纸张 10984
+",
+ "47 浙江省 杭州市 家具 13132
+",
+ "48 浙江省 杭州市 办公用品 2288
+",
+ "49 浙江省 杭州市 15420
+",
+ "50 浙江省 绍兴市 家具 2999
+",
+ "51 浙江省 绍兴市 办公用品 2658
+",
+ "52 浙江省 绍兴市 5657
+",
+ "53 浙江省 宁波市 家具 11111
+",
+ "54 浙江省 宁波市 办公用品 2668
+",
+ "55 浙江省 宁波市 13779
+",
+ "56 浙江省 舟山市 家具 5176
+",
+ "57 浙江省 舟山市 办公用品 3066
+",
+ "58 浙江省 舟山市 8242
+",
+ "59 四川省 成都市 家具 4174
+",
+ "60 四川省 成都市 办公用品 6339
+",
+ "61 四川省 成都市 10513
+",
+ "62 四川省 绵阳市 家具 4066
+",
+ "63 四川省 绵阳市 办公用品 3322
+",
+ "64 四川省 绵阳市 7388
+",
+ "65 四川省 南充市 家具 4276
+",
+ "66 四川省 南充市 办公用品 6008
+",
+ "67 四川省 南充市 10284
+",
+ "68 四川省 乐山市 家具 4775
+",
+ "69 四川省 乐山市 办公用品 2810
+",
+ "70 四川省 乐山市 7585
+",
+ "71 浙江省 家具 32418
+",
+ "72 浙江省 办公用品 10680
+",
+ "73 浙江省 43098
+",
+ "74 四川省 家具 17291
+",
+ "75 四川省 办公用品 18479
+",
+ "76 四川省 35770
+",
+ "77 78868",
+]
+`;
+
+exports[`TableSheet Export Test should export correct data with series number 2`] = `
+Array [
+ "序号",
+ "province",
+ "city",
+ "产品类型",
+ "sub_type",
+ "number
+",
+]
+`;
diff --git a/packages/s2-core/__tests__/unit/utils/export/copy-spec.ts b/packages/s2-core/__tests__/unit/utils/export/copy-spec.ts
index 4687639bf2..086fa5ec1f 100644
--- a/packages/s2-core/__tests__/unit/utils/export/copy-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/export/copy-spec.ts
@@ -1,24 +1,24 @@
import { map } from 'lodash';
import { data as originalData, totalData } from 'tests/data/mock-dataset.json';
import {
+ TOTALS_OPTIONS,
assembleDataCfg,
assembleOptions,
- TOTALS_OPTIONS,
waitForRender,
} from 'tests/util';
import { getContainer } from 'tests/util/helpers';
-import type { Meta, S2DataConfig } from '@/common/interface';
-import { Aggregation } from '@/common/interface';
-import { TableDataCell, TableSeriesNumberCell } from '@/cell';
+import type { S2DataConfig } from '../../../../src/common';
+import { TableSeriesNumberCell } from '@/cell';
import { NewLine, NewTab, S2Event } from '@/common/constant';
import {
- CellType,
InteractionStateName,
SortMethodType,
} from '@/common/constant/interaction';
-import { PivotSheet, TableSheet } from '@/sheet-type';
+import type { Meta } from '@/common/interface';
+import { Aggregation } from '@/common/interface';
+import { PivotSheet, SpreadSheet, TableSheet } from '@/sheet-type';
import { getSelectedData } from '@/utils/export/copy';
-import { CopyMIMEType } from '@/utils/export/interface';
+import { CopyMIMEType } from '@/common/interface/export';
import { convertString } from '@/utils/export/method';
import { getCellMeta } from '@/utils/interaction/select-event';
@@ -32,7 +32,7 @@ const testData = originalData.map((item, i) => {
return { ...item };
});
-const getCopyPlainContent = (sheet: TableSheet | PivotSheet): string => {
+const getCopyPlainContent = (sheet: SpreadSheet): string => {
const data = getSelectedData(sheet);
return data[0].content;
@@ -53,8 +53,14 @@ describe('List Table Core Data Process', () => {
}),
assembleOptions({
showSeriesNumber: true,
+ interaction: {
+ selectedCellHighlight: {
+ currentRow: true,
+ },
+ },
}),
);
+
await s2.render();
});
@@ -74,7 +80,7 @@ describe('List Table Core Data Process', () => {
it('should copy normal data', () => {
const cell = s2.facet
.getDataCells()
- .find((cell) => !(cell instanceof TableSeriesNumberCell))!;
+ .find((cell) => cell.getMeta().valueField === 'province')!;
s2.interaction.changeState({
cells: [getCellMeta(cell)],
@@ -94,14 +100,13 @@ describe('List Table Core Data Process', () => {
});
it('should copy row data', () => {
- const cell = s2.facet
- .getCells()
- .filter((cell) => cell instanceof TableSeriesNumberCell)[3];
+ const cell = s2.facet.getSeriesNumberCells()[3];
s2.interaction.changeState({
cells: [getCellMeta(cell)],
stateName: InteractionStateName.SELECTED,
});
+
expect(getCopyPlainContent(s2)).toMatchInlineSnapshot(
`"1 浙江省 舟山市 家具 桌子 4342"`,
);
@@ -113,6 +118,7 @@ describe('List Table Core Data Process', () => {
stateName: InteractionStateName.ALL_SELECTED,
});
+ expect(getCopyPlainContent(s2)).toMatchSnapshot();
expect(getCopyPlainContent(s2).split(NewLine).length).toBe(33);
expect(getCopyPlainContent(s2).split(NewLine)[2]).toMatchInlineSnapshot(
`"2 浙江省 绍兴市 家具 桌子 2367"`,
@@ -130,12 +136,13 @@ describe('List Table Core Data Process', () => {
const cell = s2.facet
.getDataCells()
- .find((cell) => !(cell instanceof TableSeriesNumberCell))!;
+ .find((cell) => cell.getMeta().valueField === 'province')!;
s2.interaction.changeState({
cells: [getCellMeta(cell)],
stateName: InteractionStateName.SELECTED,
});
+
expect(getCopyPlainContent(s2)).toEqual('province\r\n浙江省');
});
@@ -159,53 +166,46 @@ describe('List Table Core Data Process', () => {
await sheet.render();
const cell = s2.facet
- .getCells()
- .filter(
- (cell) =>
- cell.cellType === CellType.DATA_CELL &&
- !(cell instanceof TableSeriesNumberCell),
- )[0];
+ .getDataCells()
+ .find((cell) => cell.getMeta().valueField === 'province')!;
sheet.interaction.changeState({
cells: [getCellMeta(cell)],
stateName: InteractionStateName.SELECTED,
});
+
expect(getCopyPlainContent(sheet)).toEqual('浙江省元');
});
// https://github.com/antvis/S2/issues/1770
it('should copy format data with row header selected', async () => {
- const sheet = new TableSheet(
- getContainer(),
- assembleDataCfg({
- meta: [{ field: 'province', formatter: (v) => `${v}_formatted` }],
- fields: {
- columns: ['province', 'city', 'type', 'sub_type', 'number'],
- },
- }),
- assembleOptions({
- interaction: {
- enableCopy: true,
- copyWithFormat: true,
- },
- showSeriesNumber: false,
- }),
- );
+ s2.setDataCfg({
+ meta: [{ field: 'province', formatter: (v) => `${v}_formatted` }],
+ fields: {
+ columns: ['province', 'city', 'type', 'sub_type', 'number'],
+ },
+ });
- await sheet.render();
+ s2.setOptions({
+ interaction: {
+ enableCopy: true,
+ copyWithFormat: true,
+ },
+ showSeriesNumber: false,
+ });
- const cell = sheet.facet
- .getCells()
- .filter((cell) => cell instanceof TableDataCell)[0];
+ await s2.render();
- sheet.interaction.changeState({
- cells: [getCellMeta(cell)],
+ const dataCell = s2.facet.getDataCells()[0];
+
+ s2.interaction.changeState({
+ cells: [getCellMeta(dataCell)],
stateName: InteractionStateName.SELECTED,
});
- const data = getCopyPlainContent(sheet);
+ const data = getCopyPlainContent(s2);
- expect(data).toBe('浙江省_formatted');
+ expect(data).toEqual('浙江省_formatted');
});
// https://github.com/antvis/S2/issues/1770
@@ -231,7 +231,7 @@ describe('List Table Core Data Process', () => {
const cell = sheet.facet.getColCells()[1];
- await sheet.interaction.changeState({
+ sheet.interaction.changeState({
cells: [getCellMeta(cell)],
stateName: InteractionStateName.SELECTED,
});
@@ -253,17 +253,7 @@ describe('List Table Core Data Process', () => {
const dataContent = getCopyPlainContent(s2);
- expect(dataContent).toMatchInlineSnapshot(`
- "浙江省
-
-
-
-
-
-
-
- 宁波市"
- `);
+ expect(dataContent).toMatchSnapshot();
});
it('should copy correct data with data filtered', async () => {
@@ -281,9 +271,7 @@ describe('List Table Core Data Process', () => {
});
});
- const cell = s2.facet
- .getCells()
- .filter((cell) => cell instanceof TableSeriesNumberCell)[3];
+ const cell = s2.facet.getSeriesNumberCells()[3];
s2.interaction.changeState({
cells: [getCellMeta(cell)],
@@ -296,7 +284,9 @@ describe('List Table Core Data Process', () => {
s2.interaction.changeState({
stateName: InteractionStateName.ALL_SELECTED,
});
+
expect(getCopyPlainContent(s2).split('\n').length).toEqual(16);
+
// clear filter condition
s2.emit(S2Event.RANGE_FILTER, {
filterKey: 'province',
@@ -314,9 +304,7 @@ describe('List Table Core Data Process', () => {
]);
});
- const cell = s2.facet
- .getCells()
- .filter((cell) => cell instanceof TableSeriesNumberCell)[1];
+ const cell = s2.facet.getSeriesNumberCells()[1];
s2.interaction.changeState({
cells: [getCellMeta(cell)],
@@ -325,13 +313,15 @@ describe('List Table Core Data Process', () => {
const data = getCopyPlainContent(s2);
expect(data).toBe('1 浙江省 宁波市 家具 沙发 7234');
+
s2.interaction.changeState({
stateName: InteractionStateName.ALL_SELECTED,
});
+
expect(getCopyPlainContent(s2).split('\n').length).toEqual(33);
});
- it('should copy correct data with \n data', async () => {
+ it('should copy correct data with "\n" data', async () => {
const newLineText = `1
2`;
const sheet = new TableSheet(
@@ -356,12 +346,8 @@ describe('List Table Core Data Process', () => {
await sheet.render();
const cell = sheet.facet
- .getCells()
- .filter(
- (cell) =>
- cell.cellType === CellType.DATA_CELL &&
- !(cell instanceof TableSeriesNumberCell),
- )[20];
+ .getDataCells()
+ .filter((cell) => !(cell instanceof TableSeriesNumberCell))[20];
sheet.interaction.changeState({
cells: [getCellMeta(cell)],
@@ -409,6 +395,7 @@ describe('List Table Core Data Process', () => {
it('should copy row data when select data row cell', async () => {
s2.setOptions({
+ showSeriesNumber: false,
interaction: {
selectedCellHighlight: {
currentRow: true,
@@ -425,15 +412,13 @@ describe('List Table Core Data Process', () => {
stateName: InteractionStateName.SELECTED,
});
- expect(getCopyPlainContent(s2)).toMatchInlineSnapshot(`
- "1 浙江省 杭州市 家具 ### 问题摘要
- - **会话地址**: 7789"
- `);
- expect(getCopyPlainContent(s2).split(NewTab).length).toBe(6);
+ expect(getCopyPlainContent(s2)).toEqual('浙江省');
+ expect(getCopyPlainContent(s2).split(NewTab).length).toBe(1);
});
it('should support custom copy matrix transformer', async () => {
s2.setOptions({
+ showSeriesNumber: false,
interaction: {
customTransformer: () => {
return {
@@ -1348,9 +1333,55 @@ describe('Tree Table Core Data Process', () => {
总计 26193 23516 49709 12321 16838"
`);
});
+
+ it('should copy normal data with header for custom field name', async () => {
+ s2.setOptions({
+ interaction: {
+ copyWithHeader: true,
+ },
+ });
+ s2.setDataCfg({
+ meta: [
+ {
+ field: 'number',
+ name: '数量',
+ },
+ ],
+ });
+ await s2.render();
+
+ setSelectedVisibleCell();
+
+ expect(getSelectedData(s2)).toMatchSnapshot();
+ });
+
+ it('should copy normal data with header for custom field formatter if enable copyWithFormat', async () => {
+ s2.setOptions({
+ interaction: {
+ copyWithHeader: true,
+ copyWithFormat: true,
+ },
+ });
+ s2.setDataCfg({
+ meta: [
+ {
+ field: 'number',
+ name: '数量',
+ formatter: (value) => `${value}-@`,
+ },
+ ],
+ });
+ await s2.render();
+
+ setSelectedVisibleCell();
+
+ expect(getSelectedData(s2)).toMatchSnapshot();
+ });
});
describe('Pivot Table getBrushHeaderCopyable', () => {
+ let s2: SpreadSheet;
+
const dataCfg = assembleDataCfg({
meta: [],
fields: {
@@ -1359,6 +1390,7 @@ describe('Pivot Table getBrushHeaderCopyable', () => {
values: ['number'],
},
});
+
const options = assembleOptions({
hierarchyType: 'grid',
interaction: {
@@ -1367,9 +1399,8 @@ describe('Pivot Table getBrushHeaderCopyable', () => {
},
});
- const s2 = new PivotSheet(getContainer(), dataCfg, options);
-
beforeEach(async () => {
+ s2 = new PivotSheet(getContainer(), dataCfg, options);
await s2.render();
});
@@ -1396,6 +1427,56 @@ describe('Pivot Table getBrushHeaderCopyable', () => {
`);
});
+ test('should copy all row data in grid mode with formatter', async () => {
+ s2.setDataCfg({
+ fields: {
+ valueInCols: false,
+ },
+ meta: [
+ {
+ field: 'number',
+ name: '数值',
+ },
+ ],
+ });
+ await s2.render();
+
+ const cells = s2.facet.getRowCells();
+
+ s2.interaction.changeState({
+ cells: map(cells, getCellMeta),
+ stateName: InteractionStateName.SELECTED,
+ onUpdateCells: (root) => {
+ root.updateCells(cells);
+ },
+ });
+
+ expect(getCopyPlainContent(s2)).toMatchSnapshot();
+ });
+
+ test('should copy all original row data in grid mode if contains text ellipses', () => {
+ s2.setOptions({
+ style: {
+ rowCell: {
+ // 展示省略号
+ width: 10,
+ },
+ },
+ });
+
+ const cells = s2.facet.getRowCells();
+
+ s2.interaction.changeState({
+ cells: map(cells, getCellMeta),
+ stateName: InteractionStateName.SELECTED,
+ onUpdateCells: (root) => {
+ root.updateCells(s2.facet.getRowCells());
+ },
+ });
+
+ expect(getSelectedData(s2)).toMatchSnapshot();
+ });
+
test('should copy all col data in grid mode', () => {
const cells = s2.facet.getColCells();
@@ -1406,8 +1487,8 @@ describe('Pivot Table getBrushHeaderCopyable', () => {
root.updateCells(cells);
},
});
- // 列头高度
+ // 列头高度
expect(getCopyPlainContent(s2)).toMatchInlineSnapshot(`
"家具 家具 办公用品 办公用品
桌子 沙发 笔 纸张
@@ -1415,6 +1496,59 @@ describe('Pivot Table getBrushHeaderCopyable', () => {
`);
});
+ test('should copy all col data in grid mode with formatter', async () => {
+ s2.setDataCfg({
+ meta: [
+ {
+ field: 'number',
+ name: '数值',
+ },
+ ],
+ });
+ await s2.render();
+
+ const cells = s2.facet.getColCells();
+
+ s2.interaction.changeState({
+ cells: map(cells, getCellMeta),
+ stateName: InteractionStateName.SELECTED,
+ onUpdateCells: (root) => {
+ root.updateCells(cells);
+ },
+ });
+
+ expect(getCopyPlainContent(s2)).toMatchInlineSnapshot(`
+ "家具 家具 办公用品 办公用品
+ 桌子 沙发 笔 纸张
+ 数值 数值 数值 数值"
+ `);
+ });
+
+ test('should copy all col data in grid mode for custom field meta', async () => {
+ s2.setDataCfg({
+ meta: [
+ {
+ field: 'number',
+ name: '数量',
+ },
+ ],
+ });
+
+ await s2.render();
+
+ const cells = s2.facet.getColCells();
+
+ s2.interaction.changeState({
+ cells: map(cells, getCellMeta),
+ stateName: InteractionStateName.SELECTED,
+ onUpdateCells: (root) => {
+ root.updateCells(cells);
+ },
+ });
+
+ expect(getSelectedData(s2)).toMatchSnapshot();
+ });
+
test('should copy selection row data in grid mode', async () => {
const sheet = new PivotSheet(
getContainer(),
@@ -1523,6 +1657,7 @@ describe('Pivot Table getBrushHeaderCopyable', () => {
root.updateCells(sheet.facet.getColCells());
},
});
+
expect(getCopyPlainContent(sheet)).toMatchInlineSnapshot(`
"浙江省 浙江省
杭州市 绍兴市"
@@ -1598,14 +1733,6 @@ describe('Pivot Table getBrushHeaderCopyable', () => {
const copyableList = getSelectedData(sheet);
- expect(copyableList[0].content).toMatchInlineSnapshot(`
- "家具 家具 家具 办公用品 办公用品
- 桌子 沙发 小计 笔 纸张
- number number 小计 number number"
- `);
-
- expect(copyableList[1].content).toMatchInlineSnapshot(
- `"家具 | 家具 | 家具 | 办公用品 | 办公用品 |
桌子 | 沙发 | 小计 | 笔 | 纸张 |
number | number | 小计 | number | number |
"`,
- );
+ expect(copyableList).toMatchSnapshot();
});
});
diff --git a/packages/s2-core/__tests__/unit/utils/export/export-pivot-spec.ts b/packages/s2-core/__tests__/unit/utils/export/export-pivot-spec.ts
index 969537bb3c..2a46ca4d72 100644
--- a/packages/s2-core/__tests__/unit/utils/export/export-pivot-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/export/export-pivot-spec.ts
@@ -1,15 +1,9 @@
-import {
- asyncGetAllPlainData,
- copyData,
- NewLine,
- NewTab,
- PivotSheet,
-} from '@antv/s2';
-import { getContainer } from 'tests/util/helpers';
-import { assembleDataCfg, assembleOptions } from 'tests/util';
+import { NewLine, NewTab, PivotSheet, asyncGetAllPlainData } from '@antv/s2';
import { map, omit } from 'lodash';
import { data as originData } from 'tests/data/mock-dataset.json';
-import { CopyMIMEType } from '@/utils/export/interface';
+import { assembleDataCfg, assembleOptions } from 'tests/util';
+import { getContainer } from 'tests/util/helpers';
+import { CopyMIMEType } from '@/common/interface/export';
describe('PivotSheet Export Test', () => {
let pivotSheet: PivotSheet;
@@ -50,7 +44,7 @@ describe('PivotSheet Export Test', () => {
}
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
});
@@ -93,7 +87,7 @@ describe('PivotSheet Export Test', () => {
}
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
});
@@ -131,7 +125,7 @@ describe('PivotSheet Export Test', () => {
);
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
formatOptions: true,
@@ -171,7 +165,7 @@ describe('PivotSheet Export Test', () => {
);
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
formatOptions: true,
@@ -218,7 +212,7 @@ describe('PivotSheet Export Test', () => {
);
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
});
@@ -258,7 +252,7 @@ describe('PivotSheet Export Test', () => {
);
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
});
@@ -298,7 +292,7 @@ describe('PivotSheet Export Test', () => {
);
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
});
@@ -341,7 +335,7 @@ describe('PivotSheet Export Test', () => {
);
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
formatOptions: { isFormatHeader: true },
@@ -377,7 +371,7 @@ describe('PivotSheet Export Test', () => {
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
formatOptions: { isFormatData: true },
@@ -427,7 +421,35 @@ describe('PivotSheet Export Test', () => {
);
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: NewTab,
+ });
+
+ expect(data).toMatchSnapshot();
+ });
+
+ it('should export correct data when series number', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ assembleDataCfg({
+ meta: [],
+ fields: {
+ valueInCols: true,
+ columns: ['province', 'city'],
+ rows: ['type', 'sub_type'],
+ values: ['number'],
+ },
+ }),
+ assembleOptions({
+ hierarchyType: 'grid',
+ showSeriesNumber: true,
+ interaction: { enableCopy: true, copyWithHeader: true },
+ }),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
});
@@ -436,20 +458,23 @@ describe('PivotSheet Export Test', () => {
" province 浙江省 浙江省 浙江省 浙江省 四川省 四川省 四川省 四川省
city 杭州市 绍兴市 宁波市 舟山市 成都市 绵阳市 南充市 乐山市
type sub_type number number number number number number number number
- 家具
- 家具 桌子 2367 3877 4342 1723 1822 1943 2330
- 家具 沙发 632 7234 834 2451 2244 2333 2445
- 办公用品
- 办公用品 笔
- 办公用品 纸张 1354 1523 1634 4004 3077 3551 352"
+ 家具 桌子 7789 2367 3877 4342 1723 1822 1943 2330
+ 家具 沙发 5343 632 7234 834 2451 2244 2333 2445
+ 办公用品 笔 945 1304 1145 1432 2335 245 2457 2458
+ 办公用品 纸张 1343 1354 1523 1634 4004 3077 3551 352"
`);
+
+ const rows = data.split(NewLine);
+
+ expect(rows[0].split(NewTab)[1]).toEqual('province');
+ expect(rows[1].split(NewTab)[1]).toEqual('city');
});
- it('should export correct data when series number', async () => {
+ it('should export correct data with formatter', async () => {
const s2 = new PivotSheet(
getContainer(),
assembleDataCfg({
- meta: [],
+ meta: [{ field: 'number', name: '数值' }],
fields: {
valueInCols: true,
columns: ['province', 'city'],
@@ -459,13 +484,12 @@ describe('PivotSheet Export Test', () => {
}),
assembleOptions({
hierarchyType: 'grid',
- showSeriesNumber: true,
interaction: { enableCopy: true, copyWithHeader: true },
}),
);
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
});
@@ -473,7 +497,7 @@ describe('PivotSheet Export Test', () => {
expect(data).toMatchInlineSnapshot(`
" province 浙江省 浙江省 浙江省 浙江省 四川省 四川省 四川省 四川省
city 杭州市 绍兴市 宁波市 舟山市 成都市 绵阳市 南充市 乐山市
- type sub_type number number number number number number number number
+ type sub_type 数值 数值 数值 数值 数值 数值 数值 数值
家具 桌子 7789 2367 3877 4342 1723 1822 1943 2330
家具 沙发 5343 632 7234 834 2451 2244 2333 2445
办公用品 笔 945 1304 1145 1432 2335 245 2457 2458
@@ -497,7 +521,7 @@ describe('PivotSheet Export Test', () => {
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
customTransformer: () => {
@@ -513,11 +537,13 @@ describe('PivotSheet Export Test', () => {
});
// https://github.com/antvis/S2/issues/2236
- it('should export correct data When the split separator is configured', () => {
- const data = copyData({
+ it('should export correct data When the split separator is configured', async () => {
+ const data = await asyncGetAllPlainData({
sheetInstance: pivotSheet,
split: ',',
- formatOptions: { isFormatHeader: true },
+ formatOptions: {
+ isFormatHeader: true,
+ },
});
expect(data).toMatchInlineSnapshot(`
diff --git a/packages/s2-core/__tests__/unit/utils/export/export-spec.ts b/packages/s2-core/__tests__/unit/utils/export/export-spec.ts
new file mode 100644
index 0000000000..00f03a3b42
--- /dev/null
+++ b/packages/s2-core/__tests__/unit/utils/export/export-spec.ts
@@ -0,0 +1,473 @@
+import { asyncGetAllPlainData } from '../../../../src/utils';
+import { assembleDataCfg, assembleOptions } from '../../../util';
+import { getContainer } from '../../../util/helpers';
+import { PivotSheet, TableSheet } from '@/sheet-type';
+
+describe('TableSheet Export Test', () => {
+ it('should export correct data with series number', async () => {
+ const s2 = new TableSheet(
+ getContainer(),
+ assembleDataCfg({
+ meta: [
+ {
+ field: 'type',
+ name: '产品类型',
+ formatter: (type) => (type ? `${type}产品` : ''),
+ },
+ ],
+ fields: {
+ columns: ['province', 'city', 'type', 'sub_type', 'number'],
+ },
+ }),
+ assembleOptions({
+ showSeriesNumber: true,
+ }),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ formatOptions: {
+ isFormatHeader: true,
+ },
+ });
+
+ const rows = data.split('\n');
+ const headers = rows[0].split('\t');
+
+ expect(rows).toHaveLength(78);
+ expect(rows).toMatchSnapshot();
+
+ // 6列数据 包括序列号
+ rows.forEach((row) => {
+ expect(row.split('\t')).toHaveLength(6);
+ });
+
+ expect(headers).toMatchSnapshot();
+ });
+
+ it('should export correct data with no series number', async () => {
+ const s2 = new TableSheet(
+ getContainer(),
+ assembleDataCfg({
+ meta: [],
+ fields: {
+ columns: ['province', 'city', 'type', 'sub_type', 'number'],
+ },
+ }),
+ assembleOptions({
+ showSeriesNumber: false,
+ }),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ });
+ const rows = data.split('\n');
+ const headers = rows[0].split('\t');
+
+ expect(rows).toHaveLength(78);
+ expect(rows).toMatchSnapshot();
+
+ // 5列数据 不包括序列号
+ rows.forEach((e) => {
+ expect(e.split('\t')).toHaveLength(5);
+ });
+ expect(headers).toMatchSnapshot();
+ });
+});
+
+describe('PivotSheet Export Test', () => {
+ it('should export correct data in grid mode', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ assembleDataCfg({
+ meta: [],
+ fields: {
+ valueInCols: true,
+ columns: ['province', 'city', 'type', 'sub_type', 'number'],
+ },
+ }),
+ assembleOptions({ hierarchyType: 'grid' }),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ });
+ const rows = data.split('\n');
+
+ expect(rows).toHaveLength(14);
+ expect(rows[0].split('\t')[1]).toEqual('province');
+ expect(rows[1].split('\t')[1]).toEqual('city');
+
+ rows.forEach((e) => {
+ expect(e.split('\t')).toHaveLength(34);
+ });
+ });
+
+ it('should export correct data in tree mode', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ assembleDataCfg({
+ meta: [],
+ fields: {
+ valueInCols: true,
+ columns: ['province', 'city', 'type', 'sub_type', 'number'],
+ },
+ }),
+ assembleOptions({
+ hierarchyType: 'tree',
+ }),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ });
+ const rows = data.split('\n');
+
+ expect(rows).toHaveLength(16);
+ expect(rows[0].split('\t')[1]).toEqual('province');
+ expect(rows[1].split('\t')[1]).toEqual('city');
+
+ rows.forEach((e) => {
+ expect(e.split('\t')).toHaveLength(34);
+ });
+ });
+
+ // 因为导出的数据单测,很难看出问题,所以提供图片 + 代码的模式查看:
+ // https://gw.alipayobjects.com/zos/antfincdn/AU83KF1Sq/6fb3f3e6-0064-4ef8-a5c3-b1333fb59adf.png
+ it('should export correct data in tree mode and row collapseAll is true', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ assembleDataCfg(),
+ assembleOptions({
+ hierarchyType: 'tree',
+ style: {
+ rowCell: {
+ collapseAll: true,
+ },
+ },
+ }),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ });
+ const rows = data.split('\n');
+
+ expect(rows).toHaveLength(5);
+ expect(rows[0].split('\t').length).toEqual(5);
+ expect(rows[0].split('\t')[0]).toEqual('类别');
+ expect(rows[0].split('\t')[1]).toEqual('家具');
+ expect(rows[1].split('\t')[0]).toEqual('子类别');
+ expect(rows[1].split('\t')[1]).toEqual('桌子');
+ expect(rows[2].split('\t')[0]).toEqual('省份');
+ expect(rows[2].split('\t')[1]).toEqual('数量');
+ });
+
+ // https://gw.alipayobjects.com/zos/antfincdn/PyrWwocNf/56d0914b-159a-4293-8615-6c1308bf4b3a.png
+ it('should export correct data in tree mode and hierarchyCollapse is false', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ assembleDataCfg(),
+ assembleOptions({
+ hierarchyType: 'tree',
+ style: {
+ rowCell: {
+ collapseAll: false,
+ },
+ },
+ }),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ });
+ const rows = data.split('\n');
+
+ expect(rows).toHaveLength(13);
+ expect(rows[0].split('\t').length).toEqual(6);
+ expect(rows[0].split('\t')[1]).toEqual('类别');
+ expect(rows[0].split('\t')[2]).toEqual('家具');
+ expect(rows[1].split('\t')[1]).toEqual('子类别');
+ expect(rows[1].split('\t')[2]).toEqual('桌子');
+ expect(rows[2].split('\t')[0]).toEqual('省份');
+ expect(rows[2].split('\t')[1]).toEqual('城市');
+ expect(rows[2].split('\t')[2]).toEqual('数量');
+ });
+
+ it('should export correct data in grid mode with valueInCols is false', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ assembleDataCfg({
+ meta: [],
+ fields: {
+ valueInCols: false,
+ columns: ['province', 'city', 'type', 'sub_type', 'number'],
+ },
+ }),
+ assembleOptions({
+ hierarchyType: 'grid',
+ }),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ });
+ const rows = data.split('\n');
+
+ expect(rows).toHaveLength(13);
+ rows.forEach((e) => {
+ expect(e.split('\t')).toHaveLength(35);
+ });
+ });
+
+ it('should export correct data in grid mode with totals in col', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ assembleDataCfg({
+ fields: {
+ valueInCols: true,
+ columns: ['province', 'city', 'type', 'sub_type', 'number'],
+ },
+ }),
+ assembleOptions({
+ hierarchyType: 'grid',
+ totals: {
+ row: {
+ showGrandTotals: true,
+ showSubTotals: true,
+ subTotalsDimensions: ['province'],
+ },
+ col: {
+ showGrandTotals: true,
+ showSubTotals: true,
+ subTotalsDimensions: ['type'],
+ },
+ },
+ }),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ });
+ const rows = data.split('\n');
+
+ expect(rows).toHaveLength(17);
+ rows.forEach((e) => {
+ expect(e.split('\t')).toHaveLength(53);
+ });
+ });
+
+ it('should export correct data in grid mode with grouped totals in col', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ assembleDataCfg({
+ fields: {
+ valueInCols: true,
+ columns: ['province', 'city', 'type', 'sub_type', 'number'],
+ },
+ }),
+ assembleOptions({
+ hierarchyType: 'grid',
+ totals: {
+ row: {
+ showGrandTotals: true,
+ showSubTotals: true,
+ subTotalsDimensions: ['province'],
+ },
+ col: {
+ grandTotalsGroupDimensions: ['city', 'type'],
+ subTotalsGroupDimensions: ['sub_type'],
+ showGrandTotals: true,
+ showSubTotals: true,
+ subTotalsDimensions: ['type'],
+ },
+ },
+ }),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ });
+ const rows = data.split('\n');
+
+ expect(rows).toHaveLength(17);
+ rows.forEach((e) => {
+ expect(e.split('\t')).toHaveLength(60);
+ });
+ });
+
+ it('should export correct data in grid mode with grouped totals in row', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ assembleDataCfg({
+ fields: {
+ valueInCols: false,
+ columns: ['province', 'city', 'type', 'sub_type', 'number'],
+ },
+ }),
+ assembleOptions({
+ hierarchyType: 'grid',
+ totals: {
+ row: {
+ showGrandTotals: true,
+ showSubTotals: true,
+ subTotalsDimensions: ['province'],
+ },
+ col: {
+ grandTotalsGroupDimensions: ['city', 'sub_type', 'province'],
+ subTotalsGroupDimensions: ['sub_type'],
+ showGrandTotals: true,
+ showSubTotals: true,
+ subTotalsDimensions: ['type'],
+ },
+ },
+ }),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ });
+ const rows = data.split('\n');
+
+ expect(rows).toHaveLength(16);
+ rows.forEach((e) => {
+ expect(e.split('\t')).toHaveLength(63);
+ });
+ });
+ it('should export correct data in grid mode with totals in row', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ assembleDataCfg({
+ fields: {
+ valueInCols: false,
+ columns: ['province', 'city', 'type', 'sub_type', 'number'],
+ },
+ }),
+ assembleOptions({
+ hierarchyType: 'grid',
+ totals: {
+ row: {
+ showGrandTotals: true,
+ showSubTotals: true,
+ subTotalsDimensions: ['province'],
+ },
+ col: {
+ showGrandTotals: true,
+ showSubTotals: true,
+ subTotalsDimensions: ['type'],
+ },
+ },
+ }),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ });
+ const rows = data.split('\n');
+
+ expect(rows).toHaveLength(16);
+ rows.forEach((e) => {
+ expect(e.split('\t')).toHaveLength(54);
+ });
+ });
+
+ it('should export correct data when isFormat: {isFormatHeader: true}', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ assembleDataCfg({
+ meta: [
+ {
+ field: 'province',
+ formatter: (value) => {
+ return `${value}-province`;
+ },
+ },
+ {
+ field: 'type',
+ formatter: (value) => {
+ return `${value}-type`;
+ },
+ },
+ ],
+ fields: {
+ valueInCols: true,
+ columns: ['province', 'city'],
+ rows: ['type', 'sub_type'],
+ values: ['number'],
+ },
+ }),
+ assembleOptions({}),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ formatOptions: {
+ isFormatHeader: true,
+ },
+ });
+ const rows = data.split('\n');
+
+ expect(rows).toHaveLength(7);
+ expect(rows[0].split('\t')[1]).toEqual('province');
+ expect(rows[0].split('\t')[2]).toEqual('浙江省-province');
+ expect(rows[1].split('\t')[1]).toEqual('city');
+ expect(rows[3].split('\t')[0]).toEqual('家具-type');
+ });
+
+ it('should export correct $$extra$$ field name', async () => {
+ const s2 = new PivotSheet(
+ getContainer(),
+ assembleDataCfg({
+ meta: [
+ {
+ field: 'number',
+ name: '数值',
+ },
+ ],
+ fields: {
+ valueInCols: true,
+ columns: ['province', 'city'],
+ rows: ['type', 'sub_type'],
+ values: ['number'],
+ },
+ }),
+ assembleOptions({}),
+ );
+
+ await s2.render();
+ const data = await asyncGetAllPlainData({
+ sheetInstance: s2,
+ split: '\t',
+ formatOptions: false,
+ });
+ const rows = data.split('\n');
+ const headers = rows[2].split('\t');
+
+ expect(headers).toMatchSnapshot();
+ });
+});
diff --git a/packages/s2-core/__tests__/unit/utils/export/export-table-spec.ts b/packages/s2-core/__tests__/unit/utils/export/export-table-spec.ts
index fca32be09c..726ebc946d 100644
--- a/packages/s2-core/__tests__/unit/utils/export/export-table-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/export/export-table-spec.ts
@@ -3,9 +3,9 @@ import { data as originData } from 'tests/data/mock-dataset.json';
import { assembleDataCfg, assembleOptions } from '../../../util';
import { getContainer } from '../../../util/helpers';
import { TableSheet } from '@/sheet-type';
-import { asyncGetAllPlainData, copyData } from '@/utils';
+import { asyncGetAllPlainData } from '@/utils';
import { NewTab, NewLine } from '@/common';
-import { CopyMIMEType } from '@/utils/export/interface';
+import { CopyMIMEType } from '@/common/interface/export';
describe('TableSheet Export Test', () => {
it('should export correct data with series number', async () => {
@@ -61,7 +61,7 @@ describe('TableSheet Export Test', () => {
]);
}
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
formatOptions: {
@@ -99,7 +99,7 @@ describe('TableSheet Export Test', () => {
);
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
});
@@ -140,7 +140,7 @@ describe('TableSheet Export Test', () => {
);
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
formatOptions: true,
@@ -155,6 +155,7 @@ describe('TableSheet Export Test', () => {
浙江省-province 家具-type 沙发 5343"
`);
});
+
it('should support custom export matrix transformer', async () => {
const s2 = new TableSheet(
getContainer(),
@@ -170,7 +171,7 @@ describe('TableSheet Export Test', () => {
);
await s2.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: s2,
split: NewTab,
formatOptions: true,
@@ -200,7 +201,7 @@ describe('TableSheet Export Test', () => {
);
await tableSheet.render();
- const data = copyData({
+ const data = await asyncGetAllPlainData({
sheetInstance: tableSheet,
split: ',',
});
diff --git a/packages/s2-core/__tests__/unit/utils/export/index-spec.ts b/packages/s2-core/__tests__/unit/utils/export/utils-spec.ts
similarity index 94%
rename from packages/s2-core/__tests__/unit/utils/export/index-spec.ts
rename to packages/s2-core/__tests__/unit/utils/export/utils-spec.ts
index acf738bb79..547081bb92 100644
--- a/packages/s2-core/__tests__/unit/utils/export/index-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/export/utils-spec.ts
@@ -1,6 +1,6 @@
-import { copyToClipboard } from '@/utils/export';
+import { copyToClipboard } from '@/utils/export/utils';
-describe('Copy Tests', () => {
+describe('Export & Copy Utils Tests', () => {
test('should async copy text to clipboard', async () => {
const text = '222';
diff --git a/packages/s2-core/__tests__/unit/utils/facet-spec.ts b/packages/s2-core/__tests__/unit/utils/facet-spec.ts
index 8267cdcb2b..b44bff8a28 100644
--- a/packages/s2-core/__tests__/unit/utils/facet-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/facet-spec.ts
@@ -1,30 +1,10 @@
import {
- getSubTotalNodeWidthOrHeightByLevel,
getIndexRangeWithOffsets,
getAdjustedRowScrollX,
getAdjustedScrollOffset,
} from '@/utils/facet';
describe('Facet util test', () => {
- test('should get correct width of subTotal node', () => {
- const sampleNodesForAllLevels = [
- {
- id: 'root[&]测试',
- value: '测试',
- isSubTotals: true,
- width: 20,
- level: 0,
- },
- ];
-
- expect(
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- getSubTotalNodeWidthOrHeightByLevel(sampleNodesForAllLevels, -1, 'width'),
- ).toEqual(20);
- expect(getSubTotalNodeWidthOrHeightByLevel([], -1, 'width')).toEqual(0);
- });
-
test('should get correct index range for given offsets', () => {
const offsets = [0, 30, 60, 90, 120, 150, 160, 170, 190];
diff --git a/packages/s2-core/__tests__/unit/utils/g-mini-charts-spec.ts b/packages/s2-core/__tests__/unit/utils/g-mini-charts-spec.ts
index c560ca9177..5e88113ef6 100644
--- a/packages/s2-core/__tests__/unit/utils/g-mini-charts-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/g-mini-charts-spec.ts
@@ -3,7 +3,7 @@ import { getContainer } from 'tests/util/helpers';
import { forEach, map } from 'lodash';
import { data } from 'tests/data/mock-dataset.json';
import type { RangeColors } from '../../../src/common/interface/theme';
-import { PivotSheet } from '@/sheet-type';
+import { PivotSheet, SpreadSheet } from '@/sheet-type';
import { CellType, MiniChartTypes, type S2CellType } from '@/common';
import {
getBulletRangeColor,
@@ -312,6 +312,7 @@ describe('MiniCharts Utils Tests', () => {
});
describe('drawInterval Test', () => {
+ let s2: SpreadSheet;
const dataCfg = assembleDataCfg({
meta: [],
fields: {
@@ -324,6 +325,7 @@ describe('drawInterval Test', () => {
const horizontalBorderWidth =
getTheme({})?.dataCell?.cell?.horizontalBorderWidth ?? 1;
+
const options = assembleOptions({
style: {
dataCell: {
@@ -334,9 +336,8 @@ describe('drawInterval Test', () => {
conditions: {},
});
- const s2 = new PivotSheet(getContainer(), dataCfg, options);
-
beforeEach(async () => {
+ s2 = new PivotSheet(getContainer(), dataCfg, options);
await s2.render();
});
diff --git a/packages/s2-core/__tests__/unit/utils/hide-columns-spec.ts b/packages/s2-core/__tests__/unit/utils/hide-columns-spec.ts
index fd08727dc0..03c02f07c8 100644
--- a/packages/s2-core/__tests__/unit/utils/hide-columns-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/hide-columns-spec.ts
@@ -56,6 +56,10 @@ describe('Hide Columns Tests', () => {
mockSpreadSheetInstance.render = jest.fn();
mockSpreadSheetInstance.interaction = {
reset: jest.fn(),
+ isSelectedState: jest.fn(),
+ intercepts: new Set(),
+ getActiveCells: jest.fn(() => []),
+ clearHoverTimer: jest.fn(),
} as unknown as RootInteraction;
mockSpreadSheetInstance.isTableMode = () => true;
mockSpreadSheetInstance.isPivotMode = () => false;
@@ -344,6 +348,427 @@ describe('Hide Columns Tests', () => {
]);
});
+ // https://github.com/antvis/S2/issues/2194
+ test('should hidden group columns for fields (5 => 2)', async () => {
+ for (const field of ['5', '4', '3', '2']) {
+ // eslint-disable-next-line no-await-in-loop
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, [field]);
+ }
+
+ expect(mockSpreadSheetInstance.store.get('hiddenColumnsDetail'))
+ .toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "displaySiblingNode": Object {
+ "next": null,
+ "prev": Object {
+ "colIndex": 4,
+ "field": "4",
+ "id": "id-4",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 5,
+ "field": "5",
+ "id": "id-5",
+ },
+ ],
+ },
+ Object {
+ "displaySiblingNode": Object {
+ "next": null,
+ "prev": Object {
+ "colIndex": 3,
+ "field": "3",
+ "id": "id-3",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 4,
+ "field": "4",
+ "id": "id-4",
+ },
+ ],
+ },
+ Object {
+ "displaySiblingNode": Object {
+ "next": null,
+ "prev": Object {
+ "colIndex": 2,
+ "field": "2",
+ "id": "id-2",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 3,
+ "field": "3",
+ "id": "id-3",
+ },
+ ],
+ },
+ Object {
+ "displaySiblingNode": Object {
+ "next": null,
+ "prev": Object {
+ "colIndex": 1,
+ "field": "1",
+ "id": "id-1",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 2,
+ "field": "2",
+ "id": "id-2",
+ },
+ ],
+ },
+ ]
+ `);
+ });
+
+ test('should hidden group columns for fields (3 => 5)', async () => {
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['3']);
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['5']);
+
+ expect(mockSpreadSheetInstance.store.get('hiddenColumnsDetail'))
+ .toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "displaySiblingNode": Object {
+ "next": Object {
+ "colIndex": 4,
+ "field": "4",
+ "id": "id-4",
+ },
+ "prev": Object {
+ "colIndex": 2,
+ "field": "2",
+ "id": "id-2",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 3,
+ "field": "3",
+ "id": "id-3",
+ },
+ ],
+ },
+ Object {
+ "displaySiblingNode": Object {
+ "next": null,
+ "prev": Object {
+ "colIndex": 4,
+ "field": "4",
+ "id": "id-4",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 5,
+ "field": "5",
+ "id": "id-5",
+ },
+ ],
+ },
+ ]
+ `);
+ });
+
+ test('should get empty next sibling nodes when always hidden last column for fields (1 => 2)', async () => {
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['1']);
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['2']);
+
+ expect(mockSpreadSheetInstance.store.get('hiddenColumnsDetail'))
+ .toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "displaySiblingNode": Object {
+ "next": Object {
+ "colIndex": 2,
+ "field": "2",
+ "id": "id-2",
+ },
+ "prev": null,
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 1,
+ "field": "1",
+ "id": "id-1",
+ },
+ ],
+ },
+ Object {
+ "displaySiblingNode": Object {
+ "next": Object {
+ "colIndex": 3,
+ "field": "3",
+ "id": "id-3",
+ },
+ "prev": null,
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 2,
+ "field": "2",
+ "id": "id-2",
+ },
+ ],
+ },
+ ]
+ `);
+ });
+
+ test('should get empty next sibling nodes when always hidden last column for fields (1 => 3)', async () => {
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['1']);
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['3']);
+
+ expect(mockSpreadSheetInstance.store.get('hiddenColumnsDetail'))
+ .toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "displaySiblingNode": Object {
+ "next": Object {
+ "colIndex": 2,
+ "field": "2",
+ "id": "id-2",
+ },
+ "prev": null,
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 1,
+ "field": "1",
+ "id": "id-1",
+ },
+ ],
+ },
+ Object {
+ "displaySiblingNode": Object {
+ "next": Object {
+ "colIndex": 4,
+ "field": "4",
+ "id": "id-4",
+ },
+ "prev": Object {
+ "colIndex": 2,
+ "field": "2",
+ "id": "id-2",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 3,
+ "field": "3",
+ "id": "id-3",
+ },
+ ],
+ },
+ ]
+ `);
+ });
+
+ test('should get empty next sibling nodes when always hidden last column for fields (5 => 4)', async () => {
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['5']);
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['4']);
+
+ expect(mockSpreadSheetInstance.store.get('hiddenColumnsDetail'))
+ .toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "displaySiblingNode": Object {
+ "next": null,
+ "prev": Object {
+ "colIndex": 4,
+ "field": "4",
+ "id": "id-4",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 5,
+ "field": "5",
+ "id": "id-5",
+ },
+ ],
+ },
+ Object {
+ "displaySiblingNode": Object {
+ "next": null,
+ "prev": Object {
+ "colIndex": 3,
+ "field": "3",
+ "id": "id-3",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 4,
+ "field": "4",
+ "id": "id-4",
+ },
+ ],
+ },
+ ]
+ `);
+ });
+
+ test('should get correctly sibling nodes when hidden first and last column for fields (1 => 5)', async () => {
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['1']);
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['5']);
+
+ expect(mockSpreadSheetInstance.store.get('hiddenColumnsDetail'))
+ .toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "displaySiblingNode": Object {
+ "next": Object {
+ "colIndex": 2,
+ "field": "2",
+ "id": "id-2",
+ },
+ "prev": null,
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 1,
+ "field": "1",
+ "id": "id-1",
+ },
+ ],
+ },
+ Object {
+ "displaySiblingNode": Object {
+ "next": null,
+ "prev": Object {
+ "colIndex": 4,
+ "field": "4",
+ "id": "id-4",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 5,
+ "field": "5",
+ "id": "id-5",
+ },
+ ],
+ },
+ ]
+ `);
+ });
+
+ test('should get correctly sibling nodes when hidden odd columns for fields (2 => 4)', async () => {
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['2']);
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['4']);
+
+ expect(mockSpreadSheetInstance.store.get('hiddenColumnsDetail'))
+ .toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "displaySiblingNode": Object {
+ "next": Object {
+ "colIndex": 3,
+ "field": "3",
+ "id": "id-3",
+ },
+ "prev": Object {
+ "colIndex": 1,
+ "field": "1",
+ "id": "id-1",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 2,
+ "field": "2",
+ "id": "id-2",
+ },
+ ],
+ },
+ Object {
+ "displaySiblingNode": Object {
+ "next": Object {
+ "colIndex": 5,
+ "field": "5",
+ "id": "id-5",
+ },
+ "prev": Object {
+ "colIndex": 3,
+ "field": "3",
+ "id": "id-3",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 4,
+ "field": "4",
+ "id": "id-4",
+ },
+ ],
+ },
+ ]
+ `);
+ });
+
+ test('should get correctly sibling nodes when hidden near columns for fields (2 => 3)', async () => {
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['2']);
+ await hideColumnsByThunkGroup(mockSpreadSheetInstance, ['3']);
+
+ expect(mockSpreadSheetInstance.store.get('hiddenColumnsDetail'))
+ .toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "displaySiblingNode": Object {
+ "next": Object {
+ "colIndex": 3,
+ "field": "3",
+ "id": "id-3",
+ },
+ "prev": Object {
+ "colIndex": 1,
+ "field": "1",
+ "id": "id-1",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 2,
+ "field": "2",
+ "id": "id-2",
+ },
+ ],
+ },
+ Object {
+ "displaySiblingNode": Object {
+ "next": Object {
+ "colIndex": 4,
+ "field": "4",
+ "id": "id-4",
+ },
+ "prev": Object {
+ "colIndex": 1,
+ "field": "1",
+ "id": "id-1",
+ },
+ },
+ "hideColumnNodes": Array [
+ Object {
+ "colIndex": 3,
+ "field": "3",
+ "id": "id-3",
+ },
+ ],
+ },
+ ]
+ `);
+ });
+
test('should skip hidden group columns if hidden column fields not change', async () => {
await hideColumnsByThunkGroup(mockSpreadSheetInstance, []);
diff --git a/packages/s2-core/__tests__/unit/utils/interaction/hover-event-spec.ts b/packages/s2-core/__tests__/unit/utils/interaction/hover-event-spec.ts
index 391d77684a..589b1c90d4 100644
--- a/packages/s2-core/__tests__/unit/utils/interaction/hover-event-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/interaction/hover-event-spec.ts
@@ -27,7 +27,7 @@ jest.mock('@/cell', () => {
});
describe('Hover Event Utils Tests', () => {
- describe('getActiveHoverRowColCells test', () => {
+ describe('#getActiveHoverRowColCells', () => {
test('should return correct result for getActiveHoverRowColCells', () => {
const cells = [
new ColCell({} as unknown as Node, {} as unknown as SpreadSheet),
@@ -45,7 +45,7 @@ describe('Hover Event Utils Tests', () => {
});
});
- describe('updateAllColHeaderCellState test', () => {
+ describe('#updateAllColHeaderCellState', () => {
test('should return correct result for updateAllColHeaderCellState', () => {
const cells = [
new ColCell({} as unknown as Node, {} as unknown as SpreadSheet),
diff --git a/packages/s2-core/__tests__/unit/utils/interaction/resize-spec.ts b/packages/s2-core/__tests__/unit/utils/interaction/resize-spec.ts
index 24059c0f90..8da6764df0 100644
--- a/packages/s2-core/__tests__/unit/utils/interaction/resize-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/interaction/resize-spec.ts
@@ -33,7 +33,7 @@ describe('Resize Utils Tests', () => {
let s2: SpreadSheet;
- beforeAll(() => {
+ beforeEach(() => {
MockSpreadSheet.mockClear();
s2 = new MockSpreadSheet();
diff --git a/packages/s2-core/__tests__/unit/utils/interaction/state-controller-spec.ts b/packages/s2-core/__tests__/unit/utils/interaction/state-controller-spec.ts
index b7f16f6d51..93faee639f 100644
--- a/packages/s2-core/__tests__/unit/utils/interaction/state-controller-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/interaction/state-controller-spec.ts
@@ -1,10 +1,10 @@
-import { getCellMeta } from '@/utils/interaction/select-event';
-import type { RowCell } from '@/cell/row-cell';
+import type { RowCell } from '../../../../src/cell';
import { CellType, InteractionStateName } from '@/common/constant/interaction';
import type { S2Options } from '@/common/interface';
import { Store } from '@/common/store';
import { RootInteraction } from '@/interaction/root';
import { SpreadSheet } from '@/sheet-type';
+import { getCellMeta } from '@/utils/interaction/select-event';
import { clearState, setState } from '@/utils/interaction/state-controller';
jest.mock('@/sheet-type');
diff --git a/packages/s2-core/__tests__/unit/utils/merge-cell-spec.ts b/packages/s2-core/__tests__/unit/utils/merge-cell-spec.ts
index e33ef59157..c5c70a4069 100644
--- a/packages/s2-core/__tests__/unit/utils/merge-cell-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/merge-cell-spec.ts
@@ -20,12 +20,11 @@ import {
import type { RootInteraction } from '@/interaction/root';
import type {
MergedCellInfo,
- S2CellType,
TempMergedCell,
ViewMeta,
} from '@/common/interface';
import type { BaseFacet } from '@/facet';
-import type { MergedCell } from '@/cell';
+import type { DataCell, MergedCell } from '@/cell';
jest.mock('@/sheet-type');
@@ -35,7 +34,7 @@ describe('Merge Cells Test', () => {
let mockOneCellEdges: [number, number][][] = [];
let mockTwoCellEdges: [number, number][][] = [];
let mockMergeCellInfo: MergedCellInfo[] = [];
- let mockAllVisibleCells: S2CellType[] = [];
+ let mockAllVisibleCells: DataCell[] = [];
beforeEach(() => {
mockInstance = new MockSpreadSheet();
@@ -112,7 +111,7 @@ describe('Merge Cells Test', () => {
mockAllVisibleCells = [
{ getMeta: jest.fn().mockReturnValue(mockMergeCellInfo[2]) },
{ getMeta: jest.fn().mockReturnValue(mockMergeCellInfo[3]) },
- ] as unknown as S2CellType[];
+ ] as unknown as DataCell[];
});
test('should get none active cells info', () => {
@@ -204,7 +203,7 @@ describe('Merge Cells Test', () => {
},
];
- expect(getPolygonPoints(mockCells as unknown as S2CellType[])).toEqual(
+ expect(getPolygonPoints(mockCells as unknown as DataCell[])).toEqual(
mockResult,
);
});
diff --git a/packages/s2-core/__tests__/unit/utils/sort-action-spec.tsx b/packages/s2-core/__tests__/unit/utils/sort-action-spec.tsx
index 3f0c6bc0e5..1031a7f419 100644
--- a/packages/s2-core/__tests__/unit/utils/sort-action-spec.tsx
+++ b/packages/s2-core/__tests__/unit/utils/sort-action-spec.tsx
@@ -14,7 +14,7 @@ import {
type S2DataConfig,
VALUE_FIELD,
} from '@/common';
-import { PivotSheet } from '@/sheet-type';
+import { PivotSheet, SpreadSheet } from '@/sheet-type';
import { PivotDataSet, type SortActionParams } from '@/data-set';
import { CellData } from '@/data-set/cell-data';
@@ -509,6 +509,10 @@ describe('GetSortByMeasureValues Total Fallback Tests', () => {
sheet.dataSet = dataSet;
});
+ afterEach(() => {
+ sheet.destroy();
+ });
+
test('should sort by col total', () => {
// 根据列(类别)的总和排序
const sortParam: SortParam = {
@@ -531,7 +535,6 @@ describe('GetSortByMeasureValues Total Fallback Tests', () => {
{
price: 41.5,
type: '纸张',
- [EXTRA_FIELD]: 'price',
},
'price',
),
@@ -539,7 +542,6 @@ describe('GetSortByMeasureValues Total Fallback Tests', () => {
{
price: 37,
type: '笔',
- [EXTRA_FIELD]: 'price',
},
'price',
),
@@ -567,7 +569,6 @@ describe('GetSortByMeasureValues Total Fallback Tests', () => {
{
price: 33,
province: '吉林',
- [EXTRA_FIELD]: 'price',
},
'price',
),
@@ -575,7 +576,6 @@ describe('GetSortByMeasureValues Total Fallback Tests', () => {
{
price: 45.5,
province: '浙江',
- [EXTRA_FIELD]: 'price',
},
'price',
),
@@ -675,7 +675,6 @@ describe('GetSortByMeasureValues Total Fallback Tests', () => {
province: '浙江',
city: '杭州',
price: 3,
- [EXTRA_FIELD]: 'price',
},
'price',
),
@@ -684,7 +683,6 @@ describe('GetSortByMeasureValues Total Fallback Tests', () => {
province: '浙江',
city: '舟山',
price: 42.5,
- [EXTRA_FIELD]: 'price',
},
'price',
),
@@ -693,7 +691,6 @@ describe('GetSortByMeasureValues Total Fallback Tests', () => {
province: '吉林',
city: '长春',
price: 13,
- [EXTRA_FIELD]: 'price',
},
'price',
),
@@ -702,7 +699,6 @@ describe('GetSortByMeasureValues Total Fallback Tests', () => {
province: '吉林',
city: '白山',
price: 20,
- [EXTRA_FIELD]: 'price',
},
'price',
),
@@ -772,3 +768,67 @@ describe('GetSortByMeasureValues Total Fallback Tests', () => {
]);
});
});
+
+describe('total group dimension sort test', () => {
+ let sheet: SpreadSheet;
+
+ beforeEach(() => {
+ const currentOptions = {
+ totals: {
+ col: {
+ grandTotalsGroupDimensions: ['city'],
+ showGrandTotals: true,
+ },
+ },
+ } as S2Options;
+
+ const dataConfig = {
+ ...sortData,
+ data: [
+ ...sortData.data,
+ {
+ city: '杭州',
+ type: '纸张',
+ price: '999',
+ },
+ {
+ city: '杭州',
+ type: '笔',
+ price: '666',
+ },
+ ],
+ fields: {
+ rows: ['type'],
+ columns: ['province', 'city'],
+ values: ['price'],
+ },
+ };
+
+ sheet = new PivotSheet(getContainer(), dataConfig, currentOptions);
+ sheet.render();
+ });
+
+ afterEach(() => {
+ sheet.destroy();
+ });
+ test('should sort by col total with group', () => {
+ // 根据列(类别)的总和排序
+ const sortParam: SortParam = {
+ sortFieldId: 'type',
+ sortByMeasure: TOTAL_VALUE,
+ sortMethod: 'desc',
+ query: {
+ [EXTRA_FIELD]: 'price',
+ city: '杭州',
+ },
+ };
+
+ const params: SortActionParams = {
+ dataSet: sheet.dataSet as PivotDataSet,
+ sortParam,
+ };
+ const measureValues = getSortByMeasureValues(params);
+
+ expect(measureValues).toMatchSnapshot();
+ });
+});
diff --git a/packages/s2-core/__tests__/unit/utils/text-spec.ts b/packages/s2-core/__tests__/unit/utils/text-spec.ts
index 10cf637e1a..4829de77ab 100644
--- a/packages/s2-core/__tests__/unit/utils/text-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/text-spec.ts
@@ -8,6 +8,8 @@ import {
getCellWidth,
getEmptyPlaceholder,
getContentAreaForMultiData,
+ isZeroOrEmptyValue,
+ isUnchangedValue,
} from '@/utils/text';
const isHD = window.devicePixelRatio >= 2;
@@ -274,3 +276,70 @@ describe('Text Utils Tests', () => {
]);
});
});
+
+describe('isZeroOrEmptyValue', () => {
+ test('should return true for zero values', () => {
+ expect(isZeroOrEmptyValue('0.00%')).toBe(true);
+ expect(isZeroOrEmptyValue('-0.00%')).toBe(true);
+ expect(isZeroOrEmptyValue('0.0万亿')).toBe(true);
+ expect(isZeroOrEmptyValue('-0.0万亿')).toBe(true);
+ expect(isZeroOrEmptyValue('0.00万')).toBe(true);
+ expect(isZeroOrEmptyValue('-0.00万')).toBe(true);
+ expect(isZeroOrEmptyValue('0')).toBe(true);
+ expect(isZeroOrEmptyValue('-0')).toBe(true);
+ expect(isZeroOrEmptyValue(0)).toBe(true);
+ expect(isZeroOrEmptyValue(-0)).toBe(true);
+ });
+
+ test('should return false for non-zero values', () => {
+ expect(isZeroOrEmptyValue('0.5%')).toBe(false);
+ expect(isZeroOrEmptyValue('-0.5%')).toBe(false);
+ expect(isZeroOrEmptyValue('0.01万亿')).toBe(false);
+ expect(isZeroOrEmptyValue('-0.01万亿')).toBe(false);
+ expect(isZeroOrEmptyValue('1')).toBe(false);
+ expect(isZeroOrEmptyValue('-1')).toBe(false);
+ expect(isZeroOrEmptyValue(0.1)).toBe(false);
+ expect(isZeroOrEmptyValue(-0.1)).toBe(false);
+ });
+
+ test('should return true for non-numeric values', () => {
+ expect(isZeroOrEmptyValue('abc')).toBe(true);
+ expect(isZeroOrEmptyValue('')).toBe(true);
+ expect(isZeroOrEmptyValue(null as any)).toBe(true);
+ expect(isZeroOrEmptyValue(undefined as any)).toBe(true);
+ });
+});
+
+describe('isUnchangedValue', () => {
+ test('should return true for zero values', () => {
+ expect(isUnchangedValue(0, 123)).toBeTruthy();
+ expect(isUnchangedValue('0', 'abc')).toBeTruthy();
+ });
+
+ test('should return true for empty values', () => {
+ expect(isUnchangedValue('', 'abc')).toBeTruthy();
+ expect(isUnchangedValue(null as any, 123)).toBeTruthy();
+ expect(isUnchangedValue(undefined as any, 123)).toBeTruthy();
+ });
+
+ test('should return true for unchanged values', () => {
+ expect(isUnchangedValue('test', 'test')).toBeTruthy();
+ expect(isUnchangedValue(123, 123)).toBeTruthy();
+ });
+
+ test('should return true for numberless changed values', () => {
+ expect(isUnchangedValue('test', 'abc')).toBeTruthy();
+ });
+
+ test('should return false for numeric changed values', () => {
+ expect(isUnchangedValue(123, 456)).toBeFalsy();
+ });
+
+ test('should return true for negative zero', () => {
+ expect(isUnchangedValue(-0, 123)).toBeTruthy();
+ });
+
+ test('should return false for negative values', () => {
+ expect(isUnchangedValue(-123, 123)).toBeFalsy();
+ });
+});
diff --git a/packages/s2-core/__tests__/unit/utils/tooltip-spec.ts b/packages/s2-core/__tests__/unit/utils/tooltip-spec.ts
index d0a348b6a5..00cbc509af 100644
--- a/packages/s2-core/__tests__/unit/utils/tooltip-spec.ts
+++ b/packages/s2-core/__tests__/unit/utils/tooltip-spec.ts
@@ -2,9 +2,9 @@ import {
createFakeSpreadSheet,
createMockCellInfo,
createPivotSheet,
+ createTableSheet,
getContainer,
} from 'tests/util/helpers';
-
import { omit } from 'lodash';
import * as dataConfig from 'tests/data/mock-dataset.json';
import { CellData } from '@/data-set/cell-data';
@@ -62,7 +62,7 @@ describe('Tooltip Utils Tests', () => {
height: 1000,
};
- beforeAll(() => {
+ beforeEach(() => {
s2 = createFakeSpreadSheet();
tooltipContainer = {
getBoundingClientRect: () =>
@@ -873,6 +873,159 @@ describe('Tooltip Utils Tests', () => {
},
);
});
+
+ describe('Tooltip Get Data Tests For TableSheet', () => {
+ beforeEach(() => {
+ s2 = createTableSheet(
+ { showSeriesNumber: true },
+ { useSimpleData: false },
+ );
+ s2.render();
+ });
+
+ afterEach(() => {
+ s2.destroy();
+ });
+
+ test('should get correctly summaries of selected col cell', () => {
+ const typeColCell = s2.facet.getColLeafNodes()[1].belongsCell!;
+ const subTypeColCell = s2.facet.getColLeafNodes()[2].belongsCell!;
+
+ expect(getMockTooltipData(typeColCell)).toMatchInlineSnapshot(`
+ Object {
+ "description": "类别说明。。",
+ "details": null,
+ "headInfo": null,
+ "infos": undefined,
+ "interpretation": undefined,
+ "name": null,
+ "summaries": Array [
+ Object {
+ "name": "",
+ "selectedData": Array [
+ "家具",
+ "家具",
+ "家具",
+ "家具",
+ "家具",
+ "家具",
+ "家具",
+ "家具",
+ "办公用品",
+ "办公用品",
+ "办公用品",
+ "办公用品",
+ "办公用品",
+ "办公用品",
+ "办公用品",
+ "办公用品",
+ "家具",
+ "家具",
+ "家具",
+ "家具",
+ "家具",
+ "家具",
+ "家具",
+ "家具",
+ "办公用品",
+ "办公用品",
+ "办公用品",
+ "办公用品",
+ "办公用品",
+ "办公用品",
+ "办公用品",
+ "办公用品",
+ ],
+ "value": "",
+ },
+ ],
+ "tips": undefined,
+ }
+ `);
+ expect(getMockTooltipData(subTypeColCell)).toMatchInlineSnapshot(`
+ Object {
+ "description": "子类别说明。。",
+ "details": null,
+ "headInfo": null,
+ "infos": undefined,
+ "interpretation": undefined,
+ "name": null,
+ "summaries": Array [
+ Object {
+ "name": "",
+ "selectedData": Array [
+ "桌子",
+ "桌子",
+ "桌子",
+ "桌子",
+ "沙发",
+ "沙发",
+ "沙发",
+ "沙发",
+ "笔",
+ "笔",
+ "笔",
+ "笔",
+ "纸张",
+ "纸张",
+ "纸张",
+ "纸张",
+ "桌子",
+ "桌子",
+ "桌子",
+ "桌子",
+ "沙发",
+ "沙发",
+ "沙发",
+ "沙发",
+ "笔",
+ "笔",
+ "笔",
+ "笔",
+ "纸张",
+ "纸张",
+ "纸张",
+ "纸张",
+ ],
+ "value": "",
+ },
+ ],
+ "tips": undefined,
+ }
+ `);
+ });
+
+ test('should get correctly summaries of selected series number cell', () => {
+ const seriesCell = s2.facet.getDataCells()[0];
+
+ expect(getMockTooltipData(seriesCell)).toMatchInlineSnapshot(`
+ Object {
+ "description": undefined,
+ "details": null,
+ "headInfo": null,
+ "infos": undefined,
+ "interpretation": undefined,
+ "name": null,
+ "summaries": Array [
+ Object {
+ "name": "",
+ "selectedData": Array [
+ Object {
+ "city": "杭州市",
+ "number": 7789,
+ "province": "浙江省",
+ "sub_type": "桌子",
+ "type": "家具",
+ },
+ ],
+ "value": "",
+ },
+ ],
+ "tips": undefined,
+ }
+ `);
+ });
+ });
});
test('should set container style', () => {
diff --git a/packages/s2-core/__tests__/util/helpers.ts b/packages/s2-core/__tests__/util/helpers.ts
index 35e9226cda..596827ab0f 100644
--- a/packages/s2-core/__tests__/util/helpers.ts
+++ b/packages/s2-core/__tests__/util/helpers.ts
@@ -7,21 +7,31 @@ import {
FederatedMouseEvent,
FederatedPointerEvent,
type CanvasConfig,
+ Group,
} from '@antv/g';
import { omit } from 'lodash';
import * as simpleDataConfig from 'tests/data/simple-data.json';
import * as dataConfig from 'tests/data/mock-dataset.json';
import { Renderer } from '@antv/g-canvas';
-import type { BaseDataSet, Node } from '../../src';
+import { getTheme, type BaseDataSet, type Node, Hierarchy } from '../../src';
+
+import { assembleOptions, assembleDataCfg } from '.';
import { RootInteraction } from '@/interaction/root';
import { Store } from '@/common/store';
-import type { S2CellType, S2Options, ViewMeta } from '@/common/interface';
+import type {
+ InternalFullyTheme,
+ LayoutResult,
+ S2CellType,
+ S2DataConfig,
+ S2Options,
+ ViewMeta,
+} from '@/common/interface';
import { PivotSheet, SpreadSheet, TableSheet } from '@/sheet-type';
import type { BaseTooltip } from '@/ui/tooltip';
import { customMerge } from '@/utils/merge';
-import { DEFAULT_OPTIONS } from '@/common/constant';
+import { DEFAULT_OPTIONS, FrozenGroupType } from '@/common/constant';
import type { BaseFacet } from '@/facet';
-import type { PanelBBox } from '@/facet/bbox/panelBBox';
+import type { PanelBBox } from '@/facet/bbox/panel-bbox';
export const parseCSV = (csv: string, header?: string[]) => {
const DELIMITER = ',';
@@ -53,7 +63,11 @@ export const sleep = async (timeout = 0) => {
});
};
-export const createFakeSpreadSheet = () => {
+export const createFakeSpreadSheet = (config?: {
+ s2Options?: Partial;
+ s2DataConfig?: Partial;
+}) => {
+ const { s2Options = {}, s2DataConfig = {} } = config || {};
const container = getContainer();
class FakeSpreadSheet extends EE {
@@ -66,20 +80,15 @@ export const createFakeSpreadSheet = () => {
const s2 = new FakeSpreadSheet() as unknown as SpreadSheet;
- s2.options = {
- ...DEFAULT_OPTIONS,
- hdAdapter: false,
- };
- s2.dataCfg = {
- meta: [],
- data: [],
- fields: {
- rows: [],
- columns: [],
- values: [],
+ s2.options = assembleOptions(
+ {
+ ...DEFAULT_OPTIONS,
+ hdAdapter: false,
},
- sortParams: [],
- };
+ s2Options,
+ );
+
+ s2.dataCfg = assembleDataCfg({ sortParams: [] }, s2DataConfig);
s2.container = new Canvas({
width: DEFAULT_OPTIONS.width!,
height: DEFAULT_OPTIONS.height!,
@@ -91,41 +100,52 @@ export const createFakeSpreadSheet = () => {
getCellMultiData() {
return [];
},
+ getField: jest.fn(),
} as unknown as any;
+
+ const layoutResult: LayoutResult = {
+ rowLeafNodes: [],
+ colLeafNodes: [],
+ rowNodes: [],
+ colNodes: [],
+ colsHierarchy: new Hierarchy(),
+ rowsHierarchy: new Hierarchy(),
+ };
+
s2.facet = {
panelBBox: {
maxX: s2.options.width,
maxY: s2.options.height,
} as PanelBBox,
- panelGroup: {
- getChildren() {
- return [];
- },
- },
- foregroundGroup: {
- getChildren() {
- return [];
- },
- },
- layoutResult: {
- getCellMeta: jest.fn(),
- rowLeafNodes: [],
- colLeafNodes: [],
- rowNodes: [],
- colNodes: [],
- },
+ panelGroup: s2.container.appendChild(new Group()),
+ foregroundGroup: s2.container.appendChild(new Group()),
+ backgroundGroup: s2.container.appendChild(new Group()),
+ layoutResult,
+ getLayoutResult: () => layoutResult,
getCellMeta: jest.fn(),
getCellById: jest.fn(),
- getCellChildrenNodes: jest.fn(),
- getCells: jest.fn(),
- getColCells: jest.fn(),
- getRowCells: jest.fn(),
- getDataCells: jest.fn(),
- getRowNodes: jest.fn(),
- getRowLeafNodes: jest.fn(),
- getColNodes: jest.fn(),
- getColLeafNodes: jest.fn(),
- getInitColLeafNodes: jest.fn(),
+ getCellChildrenNodes: () => [],
+ getCells: () => [],
+ getColCells: () => [],
+ getRowCells: () => [],
+ getDataCells: () => [],
+ getRowNodes: () => [],
+ getRowLeafNodes: () => [],
+ getColNodes: () => [],
+ getColLeafNodes: () => [],
+ getInitColLeafNodes: () => [],
+ getHeaderCells: () => [],
+ getHiddenColumnsInfo: jest.fn(),
+ getCellAdaptiveHeight: jest.fn(),
+ getRowLeafNodeByIndex: jest.fn(),
+ getColLeafNodeByIndex: jest.fn(),
+ frozenGroupInfo: {
+ [FrozenGroupType.FROZEN_ROW]: {},
+ [FrozenGroupType.FROZEN_COL]: {},
+ [FrozenGroupType.FROZEN_TRAILING_ROW]: {},
+ [FrozenGroupType.FROZEN_TRAILING_COL]: {},
+ },
+ cornerBBox: {},
} as unknown as BaseFacet;
s2.container.render = jest.fn();
s2.store = new Store();
@@ -148,11 +168,25 @@ export const createFakeSpreadSheet = () => {
s2.getCell = jest.fn();
s2.isHierarchyTreeType = jest.fn();
s2.facet.getRowNodes = jest.fn().mockReturnValue([]);
+ s2.facet.getCells = jest.fn().mockReturnValue([]);
s2.getCanvasElement = () =>
s2.container.getContextService().getDomElement() as HTMLCanvasElement;
s2.isCustomHeaderFields = jest.fn(() => false);
s2.isCustomRowFields = jest.fn(() => false);
s2.isCustomColumnFields = jest.fn(() => false);
+ s2.isValueInCols = jest.fn();
+ s2.isCustomHeaderFields = jest.fn();
+ s2.isCustomColumnFields = jest.fn();
+ s2.isCustomRowFields = jest.fn();
+ s2.getTotalsConfig = jest.fn();
+ s2.getLayoutWidthType = jest.fn();
+ s2.enableFrozenHeaders = jest.fn();
+ s2.measureTextWidth = jest.fn();
+ s2.isFrozenRowHeader = jest.fn();
+ s2.theme = getTheme({
+ name: 'default',
+ spreadsheet: s2,
+ }) as InternalFullyTheme;
const interaction = new RootInteraction(s2 as unknown as SpreadSheet);
@@ -275,7 +309,7 @@ export const createFederatedMouseEvent = (
};
export const createTableSheet = (
- s2Options: S2Options,
+ s2Options: S2Options | null,
{ useSimpleData } = { useSimpleData: true },
) =>
new TableSheet(
diff --git a/packages/s2-core/__tests__/util/index.ts b/packages/s2-core/__tests__/util/index.ts
index ef6dfcd39d..195f07e5d6 100644
--- a/packages/s2-core/__tests__/util/index.ts
+++ b/packages/s2-core/__tests__/util/index.ts
@@ -1,36 +1,38 @@
-import { data, totalData, meta } from 'tests/data/mock-dataset.json';
+import { data, meta, totalData } from 'tests/data/mock-dataset.json';
import {
+ DEFAULT_DATA_CONFIG,
DEFAULT_OPTIONS,
+ S2Event,
+ SpreadSheet,
type S2DataConfig,
type S2Options,
- DEFAULT_DATA_CONFIG,
- SpreadSheet,
- S2Event,
} from '@/index';
import { customMerge } from '@/utils';
-export const assembleOptions = (...options: Partial[]) =>
- customMerge(
- DEFAULT_OPTIONS,
- { debug: false, width: 600, height: 600 },
- ...options,
- );
+export const assembleOptions = (...options: Partial[]) => {
+ const s2Options: S2Options = {
+ debug: false,
+ width: 600,
+ height: 600,
+ };
+
+ return customMerge(DEFAULT_OPTIONS, s2Options, ...options);
+};
-export const assembleDataCfg = (...dataCfg: Partial[]) =>
- customMerge(
- DEFAULT_DATA_CONFIG,
- {
- fields: {
- rows: ['province', 'city'],
- columns: ['type', 'sub_type'],
- values: ['number'],
- valueInCols: true,
- },
- meta,
- data: data.concat(totalData as any),
+export const assembleDataCfg = (...dataCfg: Partial[]) => {
+ const s2DataCfg: S2DataConfig = {
+ fields: {
+ rows: ['province', 'city'],
+ columns: ['type', 'sub_type'],
+ values: ['number'],
+ valueInCols: true,
},
- ...dataCfg,
- );
+ meta,
+ data: data.concat(totalData as any),
+ };
+
+ return customMerge(DEFAULT_DATA_CONFIG, s2DataCfg, ...dataCfg);
+};
export const TOTALS_OPTIONS: S2Options['totals'] = {
row: {
diff --git a/packages/s2-core/package.json b/packages/s2-core/package.json
index 44d1402cb0..2c47ca6b39 100644
--- a/packages/s2-core/package.json
+++ b/packages/s2-core/package.json
@@ -46,9 +46,10 @@
"build:umd": "cross-env FORMAT=umd rollup -c rollup.config.mjs",
"build:analysis": "cross-env FORMAT=esm ANALYSIS=true rollup -c rollup.config.mjs",
"build:dts": "run-s dts:*",
+ "build:size-limit": "size-limit",
+ "build:size-limit-json": "yarn build:size-limit --json",
"dts:build": "tsc -p tsconfig.declaration.json",
"dts:extract": "cross-env LIB=s2-core node ../../scripts/dts.js",
- "bundle:size": "bundlesize",
"watch": "rimraf esm && pnpm build:esm -w",
"test:live": "node ./scripts/test-live.mjs",
"sync-event": "node ./scripts/sync-event.mjs",
@@ -85,14 +86,15 @@
"*.css",
"dist/*"
],
- "bundlesize": [
+ "size-limit": [
{
"path": "./dist/index.min.js",
- "maxSize": "300 kB"
+ "import": "{ createComponent }",
+ "limit": "200 kB"
},
{
"path": "./dist/style.min.css",
- "maxSize": "5 kB"
+ "limit": "5 kB"
}
],
"publishConfig": {
diff --git a/packages/s2-core/src/cell/base-cell.ts b/packages/s2-core/src/cell/base-cell.ts
index e94f7f4b23..435531a4cc 100644
--- a/packages/s2-core/src/cell/base-cell.ts
+++ b/packages/s2-core/src/cell/base-cell.ts
@@ -156,6 +156,12 @@ export abstract class BaseCell extends Group {
condition: Condition,
): ConditionMappingResult | undefined | null;
+ protected abstract getBackgroundColor(): {
+ backgroundColor: string | undefined;
+ backgroundColorOpacity: number | undefined;
+ intelligentReverseTextColor: boolean;
+ };
+
public constructor(
meta: T,
spreadsheet: SpreadSheet,
@@ -300,6 +306,14 @@ export abstract class BaseCell extends Group {
return this.linkFieldShape;
}
+ public getBackgroundShape() {
+ return this.backgroundShape;
+ }
+
+ public getStateShapes() {
+ return this.stateShapes;
+ }
+
protected getResizeAreaStyle(): ResizeArea {
return this.getStyle('resizeArea') as ResizeArea;
}
@@ -353,7 +367,7 @@ export abstract class BaseCell extends Group {
}
/**
- * 绘制hover悬停,刷选的外框
+ * 绘制 hover 悬停,刷选的外框
*/
protected drawInteractiveBorderShape() {
this.stateShapes.set(
@@ -361,27 +375,11 @@ export abstract class BaseCell extends Group {
renderRect(this, {
...this.getBBoxByType(CellClipBox.PADDING_BOX),
visibility: 'hidden',
+ pointerEvents: 'none',
}),
);
}
- protected abstract getBackgroundColor(): {
- backgroundColor: string | undefined;
- backgroundColorOpacity: number | undefined;
- intelligentReverseTextColor: boolean;
- };
-
- protected drawBackgroundShape() {
- const { backgroundColor, backgroundColorOpacity } =
- this.getBackgroundColor();
-
- this.backgroundShape = renderRect(this, {
- ...this.getBBoxByType(),
- fill: backgroundColor,
- fillOpacity: backgroundColorOpacity,
- });
- }
-
/**
* 交互使用的背景色
*/
@@ -391,10 +389,22 @@ export abstract class BaseCell extends Group {
renderRect(this, {
...this.getBBoxByType(),
visibility: 'hidden',
+ pointerEvents: 'none',
}),
);
}
+ protected drawBackgroundShape() {
+ const { backgroundColor, backgroundColorOpacity } =
+ this.getBackgroundColor();
+
+ this.backgroundShape = renderRect(this, {
+ ...this.getBBoxByType(),
+ fill: backgroundColor,
+ fillOpacity: backgroundColorOpacity,
+ });
+ }
+
public renderTextShape(
style: TextStyleProps,
options?: RenderTextShapeOptions,
@@ -750,4 +760,20 @@ export abstract class BaseCell extends Group {
return getIconTotalWidth(this.groupedIcons[position], iconStyle);
}
+
+ protected getCrossBackgroundColor(rowIndex: number) {
+ const { crossBackgroundColor, backgroundColorOpacity } =
+ this.getStyle().cell;
+
+ if (crossBackgroundColor && rowIndex % 2 === 0) {
+ // 隔行颜色的配置
+ // 偶数行展示灰色背景,因为index是从0开始的
+ return { backgroundColorOpacity, backgroundColor: crossBackgroundColor };
+ }
+
+ return {
+ backgroundColorOpacity,
+ backgroundColor: this.getStyle().cell.backgroundColor,
+ };
+ }
}
diff --git a/packages/s2-core/src/cell/col-cell.ts b/packages/s2-core/src/cell/col-cell.ts
index 60236dc167..ae843dac63 100644
--- a/packages/s2-core/src/cell/col-cell.ts
+++ b/packages/s2-core/src/cell/col-cell.ts
@@ -99,11 +99,41 @@ export class ColCell extends HeaderCell {
return false;
}
- protected getTextPosition(): PointLike {
- const { isLeaf } = this.meta;
+ /**
+ * 计算文本位置时候需要,留给后代根据情况(固定列)覆盖
+ * @param viewport
+ * @returns viewport
+ */
+ protected handleViewport(): AreaRange {
+ /**
+ * p(x, y)
+ * +----------------------+ x
+ * | +--------------->
+ * | viewport | |ColCell |
+ * | |-|---------+
+ * +--------------------|-+
+ * |
+ * y |
+ * v
+ *
+ * 将 viewport 坐标(p)映射到 col header 的坐标体系中,简化计算逻辑
+ *
+ */
const { width, cornerWidth = 0, scrollX = 0 } = this.getHeaderConfig();
const scrollContainsRowHeader = !this.spreadsheet.isFrozenRowHeader();
+
+ const viewport: AreaRange = {
+ start: scrollX - (scrollContainsRowHeader ? cornerWidth : 0),
+ size: width + (scrollContainsRowHeader ? cornerWidth : 0),
+ };
+
+ return viewport;
+ }
+
+ protected getTextPosition(): PointLike {
+ const { isLeaf } = this.meta;
+
const textStyle = this.getTextStyle();
const contentBox = this.getBBoxByType(CellClipBox.CONTENT_BOX);
const iconStyle = this.getIconStyle()!;
@@ -137,26 +167,7 @@ export class ColCell extends HeaderCell {
return { x: textX, y: textY };
}
- /**
- * p(x, y)
- * +----------------------+ x
- * | +--------------->
- * | viewport | |ColCell |
- * | |-|---------+
- * +--------------------|-+
- * |
- * y |
- * v
- *
- * 将 viewport 坐标(p)映射到 col header 的坐标体系中,简化计算逻辑
- *
- */
- const viewport: AreaRange = {
- start: scrollX - (scrollContainsRowHeader ? cornerWidth : 0),
- size: width + (scrollContainsRowHeader ? cornerWidth : 0),
- };
-
- this.handleViewport(viewport);
+ const viewport = this.handleViewport();
const { cell, icon } = this.getStyle()!;
const { textAlign, textBaseline } = this.getTextStyle();
@@ -270,7 +281,7 @@ export class ColCell extends HeaderCell {
style: {
...attrs.style,
x: 0,
- y: y + height - resizeStyle.size! / 2,
+ y: y + height - resizeStyle.size!,
width: resizeAreaWidth,
},
},
@@ -369,7 +380,7 @@ export class ColCell extends HeaderCell {
{
style: {
...attrs.style,
- x: offsetX + width - resizeStyle.size! / 2,
+ x: offsetX + width - resizeStyle.size!,
y: offsetY,
height,
},
@@ -435,11 +446,22 @@ export class ColCell extends HeaderCell {
}
this.addExpandColumnSplitLine();
- this.addExpandColumnIcon();
+ this.addExpandColumnIcons();
}
- protected addExpandColumnIcon() {
- const iconConfig = this.getExpandColumnIconConfig();
+ protected addExpandColumnIcons() {
+ const isLastColumn = this.isLastColumn();
+
+ this.addExpandColumnIcon(isLastColumn);
+
+ // 如果当前节点的兄弟节点 (前/后) 都被隐藏了, 隐藏后当前节点变为最后一个节点, 需要渲染两个展开按钮, 一个展开[前], 一个展开[后]
+ if (this.isAllDisplaySiblingNodeHidden() && isLastColumn) {
+ this.addExpandColumnIcon(false);
+ }
+ }
+
+ private addExpandColumnIcon(isLastColumn: boolean) {
+ const iconConfig = this.getExpandColumnIconConfig(isLastColumn);
const icon = renderIcon(this, {
...iconConfig,
name: 'ExpandColIcon',
@@ -452,12 +474,12 @@ export class ColCell extends HeaderCell {
}
// 在隐藏的下一个兄弟节点的起始坐标显示隐藏提示线和展开按钮, 如果是尾元素, 则显示在前一个兄弟节点的结束坐标
- protected getExpandColumnIconConfig() {
+ protected getExpandColumnIconConfig(isLastColumn: boolean) {
const { size = 0 } = this.getExpandIconTheme();
const { x, y, width, height } = this.getBBoxByType();
const baseIconX = x - size;
- const iconX = this.isLastColumn() ? baseIconX + width : baseIconX;
+ const iconX = isLastColumn ? baseIconX + width : baseIconX;
const iconY = y + height / 2 - size / 2;
return {
@@ -472,12 +494,20 @@ export class ColCell extends HeaderCell {
return isLastColumnAfterHidden(this.spreadsheet, this.meta.id);
}
- /**
- * 计算文本位置时候需要,留给后代根据情况(固定列)覆盖
- * @param viewport
- * @returns viewport
- */
- protected handleViewport(viewport: AreaRange): AreaRange {
- return viewport;
+ protected isAllDisplaySiblingNodeHidden() {
+ const { id } = this.meta;
+ const lastHiddenColumnDetail = this.spreadsheet.store.get(
+ 'hiddenColumnsDetail',
+ [],
+ );
+
+ const isPrevSiblingNodeHidden = lastHiddenColumnDetail.find(
+ ({ displaySiblingNode }) => displaySiblingNode?.next?.id === id,
+ );
+ const isNextSiblingNodeHidden = lastHiddenColumnDetail.find(
+ ({ displaySiblingNode }) => displaySiblingNode?.prev?.id === id,
+ );
+
+ return isNextSiblingNodeHidden && isPrevSiblingNodeHidden;
}
}
diff --git a/packages/s2-core/src/cell/corner-cell.ts b/packages/s2-core/src/cell/corner-cell.ts
index dd61264bab..2d484d095b 100644
--- a/packages/s2-core/src/cell/corner-cell.ts
+++ b/packages/s2-core/src/cell/corner-cell.ts
@@ -7,7 +7,7 @@ import {
ResizeDirectionType,
S2Event,
} from '../common/constant';
-import type { FormatResult, TextTheme } from '../common/interface';
+import type { FormatResult } from '../common/interface';
import { CellBorderPosition, CellClipBox } from '../common/interface';
import { CornerNodeType } from '../common/interface/node';
import { CustomRect } from '../engine';
@@ -15,6 +15,7 @@ import type { CornerHeaderConfig } from '../facet/header/interface';
import {
getHorizontalTextIconPosition,
getVerticalIconPosition,
+ getVerticalTextPosition,
} from '../utils/cell/cell';
import { formattedFieldValue } from '../utils/cell/header-cell';
import { renderTreeIcon } from '../utils/g-renders';
@@ -40,8 +41,6 @@ export class CornerCell extends HeaderCell {
return [CellBorderPosition.TOP, CellBorderPosition.LEFT];
}
- public update() {}
-
protected initCell() {
super.initCell();
this.resetTextAndConditionIconShapes();
@@ -51,53 +50,7 @@ export class CornerCell extends HeaderCell {
this.drawActionAndConditionIcons();
this.drawBorders();
this.drawResizeArea();
- }
-
- public drawTextShape() {
- const { x, y, height, width } = this.getBBoxByType(CellClipBox.CONTENT_BOX);
- const textStyle = this.getTextStyle();
- const cornerText = this.getFieldValue();
- const maxWidth = this.getMaxTextWidth();
-
- const { textX, leftIconX, rightIconX } = getHorizontalTextIconPosition({
- bbox: {
- x: x + this.getTreeIconWidth(),
- y,
- width: width - this.getTreeIconWidth(),
- height,
- },
- textAlign: textStyle.textAlign!,
- textWidth: this.getActualTextWidth(),
- groupedIcons: this.groupedIcons,
- iconStyle: this.getIconStyle()!,
- });
-
- const textY = y + height / 2;
-
- this.renderTextShape({
- ...textStyle,
- x: textX,
- y: textY,
- text: cornerText,
- wordWrapWidth: maxWidth,
- });
-
- const { size = 0 } = this.getStyle()!.icon!;
- const iconY = getVerticalIconPosition(
- size,
- y + height / 2,
- size,
- textStyle.textBaseline!,
- );
-
- this.leftIconPosition = {
- x: leftIconX,
- y: iconY,
- };
- this.rightIconPosition = {
- x: rightIconX,
- y: iconY,
- };
+ this.update();
}
/**
@@ -228,7 +181,7 @@ export class CornerCell extends HeaderCell {
{
style: {
...attrs.style,
- x: offsetX + width - resizeStyle.size! / 2,
+ x: offsetX + width - resizeStyle.size!,
y: offsetY,
height: this.isLastRowCornerCell() ? headerHeight : height,
},
@@ -249,20 +202,6 @@ export class CornerCell extends HeaderCell {
return this.showTreeIcon() ? size! + margin!.right! : 0;
}
- protected getTextStyle(): TextTheme {
- const { text, bolderText } = this.getStyle()!;
- const cornerTextStyle = this.isBolderText() ? text : bolderText;
-
- const textStyle =
- this.getContainConditionMappingResultTextStyle(cornerTextStyle);
-
- return {
- ...textStyle,
- // 角头因为要折行,所以在都是按照 middle 来计算,这里写死,不然用户配置了 baseline,会导致计算错误
- textBaseline: 'middle',
- };
- }
-
protected getMaxTextWidth(): number {
const { width } = this.getBBoxByType(CellClipBox.CONTENT_BOX);
@@ -272,9 +211,46 @@ export class CornerCell extends HeaderCell {
}
protected getTextPosition(): PointLike {
+ const contentBox = this.getBBoxByType(CellClipBox.CONTENT_BOX);
+ const { x, y, height, width } = contentBox;
+
+ const textStyle = this.getTextStyle();
+
+ const { textX, leftIconX, rightIconX } = getHorizontalTextIconPosition({
+ bbox: {
+ x: x + this.getTreeIconWidth(),
+ y,
+ width: width - this.getTreeIconWidth(),
+ height,
+ },
+ textAlign: textStyle.textAlign!,
+ textWidth: this.getActualTextWidth(),
+ groupedIcons: this.groupedIcons,
+ iconStyle: this.getIconStyle()!,
+ });
+
+ const textY = getVerticalTextPosition(contentBox, textStyle.textBaseline!);
+
+ const { size = 0 } = this.getStyle()!.icon!;
+ const iconY = getVerticalIconPosition(
+ size,
+ textY,
+ textStyle.fontSize!,
+ textStyle.textBaseline!,
+ );
+
+ this.leftIconPosition = {
+ x: leftIconX,
+ y: iconY,
+ };
+ this.rightIconPosition = {
+ x: rightIconX,
+ y: iconY,
+ };
+
return {
- x: 0,
- y: 0,
+ x: textX,
+ y: textY,
};
}
diff --git a/packages/s2-core/src/cell/data-cell.ts b/packages/s2-core/src/cell/data-cell.ts
index 76a086c80c..a81850c762 100644
--- a/packages/s2-core/src/cell/data-cell.ts
+++ b/packages/s2-core/src/cell/data-cell.ts
@@ -28,6 +28,7 @@ import type {
MultiData,
TextTheme,
ViewMeta,
+ ViewMetaData,
ViewMetaIndexType,
} from '../common/interface';
import {
@@ -37,7 +38,7 @@ import {
type IconCondition,
type InteractionStateTheme,
} from '../common/interface';
-import { getFieldValueOfViewMetaData } from '../data-set/cell-data';
+import { CellData } from '../data-set/cell-data';
import {
getHorizontalTextIconPosition,
getVerticalIconPosition,
@@ -67,6 +68,12 @@ import type { RawData } from './../common/interface/s2DataConfig';
* 3、left rect area is interval(in left) and text(in right)
*/
export class DataCell extends BaseCell {
+ /**
+ * 用于 merge cell 中用于绘制 border 的位置信息
+ * @see packages/s2-core/src/facet/base-facet.ts L1319
+ */
+ position: [rowIndex: number, colIndex: number];
+
// condition icon 坐标
iconPosition: PointLike;
@@ -180,15 +187,18 @@ export class DataCell extends BaseCell {
return;
}
- if (this.spreadsheet.options.interaction?.hoverHighlight) {
+ const { currentRow, currentCol } =
+ this.spreadsheet.interaction.getHoverHighlight();
+
+ if (currentRow || currentCol) {
// 如果当前是hover,要绘制出十字交叉的行列样式
const currentColIndex = this.meta.colIndex;
const currentRowIndex = this.meta.rowIndex;
// 当视图内的 cell 行列 index 与 hover 的 cell 一致,绘制hover的十字样式
if (
- currentColIndex === currentHoverCell?.colIndex ||
- currentRowIndex === currentHoverCell?.rowIndex
+ (currentCol && currentColIndex === currentHoverCell?.colIndex) ||
+ (currentRow && currentRowIndex === currentHoverCell?.rowIndex)
) {
this.updateByState(InteractionStateName.HOVER);
} else {
@@ -259,18 +269,18 @@ export class DataCell extends BaseCell {
this.generateIconConfig();
this.drawBackgroundShape();
this.drawInteractiveBgShape();
+
if (!this.shouldHideRowSubtotalData()) {
this.drawConditionIntervalShape();
}
- this.drawInteractiveBorderShape();
-
if (!this.shouldHideRowSubtotalData()) {
this.drawTextShape();
this.drawConditionIconShapes();
}
this.drawBorders();
+ this.drawInteractiveBorderShape();
this.update();
}
@@ -308,17 +318,24 @@ export class DataCell extends BaseCell {
}
protected shouldHideRowSubtotalData() {
+ const { rowId, rowIndex } = this.meta;
+ // 如果该格子是被下钻的格子,下钻格子本身来说是明细格子,因为下钻变成了小计格子,是应该展示的
+ const drillDownIdPathMap = this.spreadsheet.store.get('drillDownIdPathMap');
+
+ if (drillDownIdPathMap?.has(rowId!)) {
+ return false;
+ }
+
const { row = {} } = this.spreadsheet.options.totals ?? {};
- const { rowIndex } = this.meta;
- const node = this.spreadsheet.facet.getRowLeafNodes()[rowIndex];
+ const node = this.spreadsheet.facet?.getRowLeafNodeByIndex(rowIndex);
const isRowSubTotal = !node?.isGrandTotals && node?.isTotals;
- /*
+ /**
* 在树状结构时,如果单元格本身是行小计,但是行小计配置又未开启时
- * 不过能否查到实际的数据,都不应该展示
+ * 不管能否查到实际的数据,都不应该展示
*/
return (
- this.spreadsheet.options.hierarchyType === 'tree' &&
+ this.spreadsheet.isHierarchyTreeType() &&
!row.showSubTotals &&
isRowSubTotal
);
@@ -329,7 +346,7 @@ export class DataCell extends BaseCell {
return {
value: null,
- /*
+ /**
* 这里使用默认的placeholder,而不是空字符串,是为了防止后续使用用户自定义的placeholder
* 比如用户自定义 placeholder 为 0, 那行小计也会显示0,也很有迷惑性,显示 - 更为合理
*/
@@ -392,18 +409,12 @@ export class DataCell extends BaseCell {
}
public getBackgroundColor() {
- const cellStyle = this.getStyle()?.cell;
- const { crossBackgroundColor, backgroundColorOpacity } = cellStyle!;
-
- let backgroundColor = cellStyle!.backgroundColor;
-
- if (crossBackgroundColor && this.meta.rowIndex % 2 === 0) {
- /*
- * 隔行颜色的配置
- * 偶数行展示灰色背景,因为index是从0开始的
- */
- backgroundColor = crossBackgroundColor;
- }
+ const backgroundColorByCross = this.getCrossBackgroundColor(
+ this.meta.rowIndex,
+ );
+ const backgroundColor = backgroundColorByCross.backgroundColor;
+ const backgroundColorOpacity =
+ backgroundColorByCross.backgroundColorOpacity;
if (this.shouldHideRowSubtotalData()) {
return {
@@ -419,7 +430,7 @@ export class DataCell extends BaseCell {
);
}
- // dataCell根据state 改变当前样式,
+ // dataCell 根据 state 改变当前样式,
protected changeRowColSelectState(indexType: ViewMetaIndexType) {
const { interaction } = this.spreadsheet;
const currentIndex = get(this.meta, indexType);
@@ -481,7 +492,7 @@ export class DataCell extends BaseCell {
? this.spreadsheet.dataSet.getCellData({
query: { rowIndex: this.meta.rowIndex },
})
- : getFieldValueOfViewMetaData(this.meta.data);
+ : CellData.getFieldValue(this.meta.data as ViewMetaData);
return condition?.mapping(value, rowDataInfo as RawData, this);
}
diff --git a/packages/s2-core/src/cell/header-cell.ts b/packages/s2-core/src/cell/header-cell.ts
index f2039de51b..69a5dee2a5 100644
--- a/packages/s2-core/src/cell/header-cell.ts
+++ b/packages/s2-core/src/cell/header-cell.ts
@@ -82,7 +82,7 @@ export abstract class HeaderCell<
return super.shouldInit() && !this.isShallowRender();
}
- protected handleRestOptions(...[headerConfig]: [T]) {
+ protected handleRestOptions(...[headerConfig]: [T, unknown]) {
this.headerConfig = { ...headerConfig };
const { value, query } = this.meta;
@@ -139,13 +139,32 @@ export abstract class HeaderCell<
}
protected getFormattedFieldValue(): FormatResult {
- const { value, field } = this.meta;
+ const { isTotalRoot, isGrandTotals, value } = this.meta;
- const formatter = this.spreadsheet.dataSet.getFieldFormatter(field);
- // TODO: formatter 简化成两个参数 formatter(value, this,meta)
- const formattedValue = formatter!
- ? formatter(value, undefined, this.meta)
- : value;
+ const formatter = this.spreadsheet.dataSet.getFieldFormatter(
+ this.meta.field,
+ );
+
+ /**
+ * 如果是 table mode,列头不需要被格式化
+ * 树状模式下,小计是父维度本身,需要被格式化,此时只有总计才不需要被格式化
+ * 平铺模式下,总计/小计 文字单元格,不需要被格式化
+ * 自定义树模式下,没有总计小计概念,isTotals 均为 false, 所以不受影响
+ */
+ let shouldFormat = true;
+
+ if (this.spreadsheet.isTableMode()) {
+ shouldFormat = false;
+ } else if (this.spreadsheet.isHierarchyTreeType()) {
+ shouldFormat = !(isGrandTotals && isTotalRoot);
+ } else {
+ shouldFormat = !isTotalRoot;
+ }
+
+ const formattedValue =
+ shouldFormat && formatter
+ ? formatter(value, undefined, this.meta)
+ : value;
return {
formattedValue,
@@ -415,7 +434,11 @@ export abstract class HeaderCell<
public update() {
const { interaction } = this.spreadsheet;
const stateInfo = interaction?.getState();
- const cells = interaction?.getCells([CellType.COL_CELL, CellType.ROW_CELL]);
+ const cells = interaction?.getCells([
+ CellType.CORNER_CELL,
+ CellType.COL_CELL,
+ CellType.ROW_CELL,
+ ]);
if (!first(cells)) {
return;
@@ -423,6 +446,7 @@ export abstract class HeaderCell<
switch (stateInfo?.stateName) {
case InteractionStateName.SELECTED:
+ case InteractionStateName.BRUSH_SELECTED:
this.handleSelect(cells, stateInfo?.nodes);
break;
case InteractionStateName.HOVER_FOCUS:
diff --git a/packages/s2-core/src/cell/index.ts b/packages/s2-core/src/cell/index.ts
index c6ca335870..80545190fd 100644
--- a/packages/s2-core/src/cell/index.ts
+++ b/packages/s2-core/src/cell/index.ts
@@ -4,11 +4,11 @@ import { CornerCell } from './corner-cell';
import { DataCell } from './data-cell';
import { HeaderCell } from './header-cell';
import { MergedCell } from './merged-cell';
-import { RowCell } from './row-cell';
import { TableColCell } from './table-col-cell';
import { TableCornerCell } from './table-corner-cell';
import { TableDataCell } from './table-data-cell';
import { TableSeriesNumberCell } from './table-series-number-cell';
+import { RowCell } from './row-cell';
import { SeriesNumberCell } from './series-number-cell';
export {
@@ -16,7 +16,6 @@ export {
TableColCell,
TableSeriesNumberCell,
TableDataCell,
- SeriesNumberCell,
RowCell,
ColCell,
DataCell,
@@ -24,4 +23,5 @@ export {
CornerCell,
BaseCell,
HeaderCell,
+ SeriesNumberCell,
};
diff --git a/packages/s2-core/src/cell/merged-cell.ts b/packages/s2-core/src/cell/merged-cell.ts
index 064fef3a09..b3d84810b2 100644
--- a/packages/s2-core/src/cell/merged-cell.ts
+++ b/packages/s2-core/src/cell/merged-cell.ts
@@ -1,18 +1,21 @@
import { isEmpty, isObject } from 'lodash';
import { CellType } from '../common/constant';
-import type { ViewMeta } from '../common/interface';
-import type { S2CellType } from '../common/interface/interaction';
+import { CellBorderPosition, type ViewMeta } from '../common/interface';
import type { SpreadSheet } from '../sheet-type';
-import { renderPolygon } from '../utils/g-renders';
-import { getPolygonPoints } from '../utils/interaction/merge-cell';
+import { renderLine, renderPolygon } from '../utils/g-renders';
+import {
+ getPolygonPoints,
+ getRightAndBottomCells,
+} from '../utils/interaction/merge-cell';
import { drawObjectText } from '../utils/text';
+import { getBorderPositionAndStyle } from '../utils';
import { DataCell } from './data-cell';
/**
* Cell for panelGroup area
*/
export class MergedCell extends DataCell {
- public cells: S2CellType[];
+ public cells: DataCell[];
public get cellType() {
return CellType.MERGED_CELL;
@@ -20,13 +23,13 @@ export class MergedCell extends DataCell {
public constructor(
spreadsheet: SpreadSheet,
- cells: S2CellType[],
+ cells: DataCell[],
meta?: ViewMeta,
) {
super(meta!, spreadsheet, cells);
}
- handleRestOptions(...[cells]: [S2CellType[]]) {
+ handleRestOptions(...[cells]: [DataCell[]]) {
this.cells = cells;
}
@@ -35,9 +38,9 @@ export class MergedCell extends DataCell {
protected initCell() {
this.resetTextAndConditionIconShapes();
// TODO:1、交互态扩展; 2、合并后的单元格文字布局及文字内容(目前参考Excel合并后只保留第一个单元格子的数据)
- this.conditions = this.spreadsheet.options.conditions!;
this.drawBackgroundShape();
this.drawTextShape();
+ this.drawBorders();
}
/**
@@ -49,7 +52,6 @@ export class MergedCell extends DataCell {
this.backgroundShape = renderPolygon(this, {
points: allPoints,
- stroke: cellTheme!.horizontalBorderColor,
fill: cellTheme!.backgroundColor,
});
}
@@ -65,4 +67,54 @@ export class MergedCell extends DataCell {
super.drawTextShape();
}
}
+
+ override drawBorders(): void {
+ const { right, bottom, bottomRightCornerCell } = getRightAndBottomCells(
+ this.cells,
+ );
+
+ right.forEach((cell) => {
+ const { position, style } = getBorderPositionAndStyle(
+ CellBorderPosition.RIGHT,
+ cell.getBBoxByType(),
+ cell.getStyle()?.cell!,
+ );
+
+ renderLine(this, { ...position, ...style });
+ });
+
+ bottom.forEach((cell) => {
+ const { position, style } = getBorderPositionAndStyle(
+ CellBorderPosition.BOTTOM,
+ cell.getBBoxByType(),
+ cell.getStyle()?.cell!,
+ );
+
+ renderLine(this, { ...position, ...style });
+ });
+
+ bottomRightCornerCell.forEach((cell) => {
+ const { x, y, width, height } = cell.getBBoxByType();
+ const {
+ horizontalBorderWidth = 0,
+ verticalBorderWidth = 0,
+ verticalBorderColor,
+ } = cell.getStyle()?.cell!;
+
+ const x1 = x + width - verticalBorderWidth / 2;
+ const x2 = x1;
+ const y1 = y + height - horizontalBorderWidth;
+ const y2 = y + height;
+
+ renderLine(this, {
+ x1,
+ x2,
+ y1,
+ y2,
+ lineWidth: verticalBorderWidth,
+ stroke: verticalBorderColor,
+ strokeOpacity: verticalBorderWidth,
+ });
+ });
+ }
}
diff --git a/packages/s2-core/src/cell/row-cell.ts b/packages/s2-core/src/cell/row-cell.ts
index bb8d1bb688..2fcf24e1a4 100644
--- a/packages/s2-core/src/cell/row-cell.ts
+++ b/packages/s2-core/src/cell/row-cell.ts
@@ -1,7 +1,8 @@
import type { PointLike } from '@antv/g';
-import { find, get } from 'lodash';
+import { find, get, merge } from 'lodash';
import {
CellType,
+ FrozenGroupType,
KEY_GROUP_ROW_RESIZE_AREA,
ResizeAreaEffect,
ResizeDirectionType,
@@ -26,6 +27,7 @@ import {
getResizeAreaAttrs,
} from '../utils/interaction/resize';
import { isMobile } from '../utils/is-mobile';
+import type { FrozenFacet } from '../facet/frozen-facet';
import type { SimpleBBox } from './../engine/interface';
import { adjustTextIconPositionWhileScrolling } from './../utils/cell/text-scrolling';
import { shouldAddResizeArea } from './../utils/interaction/resize';
@@ -64,6 +66,16 @@ export class RowCell extends HeaderCell {
this.update();
}
+ public getBackgroundColor() {
+ const { backgroundColor, backgroundColorOpacity } =
+ this.getCrossBackgroundColor(this.meta.rowIndex);
+
+ return merge(
+ { backgroundColor, backgroundColorOpacity },
+ this.getBackgroundConditionFill(),
+ );
+ }
+
protected showTreeIcon() {
return this.spreadsheet.isHierarchyTreeType() && !this.meta.isLeaf;
}
@@ -232,6 +244,7 @@ export class RowCell extends HeaderCell {
viewportHeight: headerHeight,
scrollX = 0,
scrollY = 0,
+ spreadsheet,
} = this.getHeaderConfig();
const resizeAreaBBox: SimpleBBox = {
@@ -241,25 +254,30 @@ export class RowCell extends HeaderCell {
height: resizeStyle.size!,
};
+ const isFrozen = this.getMeta().isFrozen;
+
+ const frozenRowGroupHeight = (spreadsheet.facet as FrozenFacet)
+ .frozenGroupInfo[FrozenGroupType.FROZEN_ROW]?.height;
+
const resizeClipAreaBBox: SimpleBBox = {
x: 0,
- y: 0,
+ y: frozenRowGroupHeight,
width: headerWidth,
height: headerHeight,
};
if (
+ !isFrozen &&
!shouldAddResizeArea(resizeAreaBBox, resizeClipAreaBBox, {
scrollX,
scrollY,
- }) ||
- !position
+ })
) {
return;
}
const offsetX = position.x + x - scrollX;
- const offsetY = position.y + y - scrollY;
+ const offsetY = position.y + y - (isFrozen ? 0 : scrollY);
const resizeAreaWidth = this.spreadsheet.isFrozenRowHeader()
? headerWidth - position.x - (x - scrollX)
@@ -282,7 +300,7 @@ export class RowCell extends HeaderCell {
style: {
...attrs.style,
x: offsetX,
- y: offsetY + height - resizeStyle.size! / 2,
+ y: offsetY + height - resizeStyle.size!,
width: resizeAreaWidth,
},
},
@@ -355,16 +373,26 @@ export class RowCell extends HeaderCell {
};
}
+ protected handleViewport() {
+ const { scrollY, viewportHeight, spreadsheet } = this.getHeaderConfig();
+
+ const frozenRowGroupHeight = (spreadsheet.facet as FrozenFacet)
+ .frozenGroupInfo[FrozenGroupType.FROZEN_ROW].height;
+
+ const viewport: AreaRange = {
+ start: this.getMeta().isFrozen ? 0 : scrollY! + frozenRowGroupHeight,
+ size: viewportHeight - frozenRowGroupHeight,
+ };
+
+ return viewport;
+ }
+
protected getTextPosition(): PointLike {
- const { scrollY, viewportHeight } = this.getHeaderConfig();
const textArea = this.getTextArea();
const textStyle = this.getTextStyle();
const { cell, icon: iconStyle } = this.getStyle();
- const viewport: AreaRange = {
- start: scrollY!,
- size: viewportHeight,
- };
+ const viewport = this.handleViewport();
const { textStart } = adjustTextIconPositionWhileScrolling(
viewport,
diff --git a/packages/s2-core/src/cell/table-col-cell.ts b/packages/s2-core/src/cell/table-col-cell.ts
index 8f8875f506..11cc2c1d99 100644
--- a/packages/s2-core/src/cell/table-col-cell.ts
+++ b/packages/s2-core/src/cell/table-col-cell.ts
@@ -1,6 +1,7 @@
import { find } from 'lodash';
import { ColCell } from '../cell/col-cell';
import {
+ FrozenGroupType,
HORIZONTAL_RESIZE_AREA_KEY_PRE,
KEY_GROUP_FROZEN_COL_RESIZE_AREA,
} from '../common/constant';
@@ -8,15 +9,14 @@ import type { FormatResult } from '../common/interface';
import type { AreaRange } from '../common/interface/scroll';
import type { SimpleBBox } from '../engine';
import type { BaseHeaderConfig } from '../facet/header';
-import { getNodeRoot, isFrozenCol, isFrozenTrailingCol } from '../facet/utils';
import { formattedFieldValue } from '../utils/cell/header-cell';
import { renderRect } from '../utils/g-renders';
import {
getOrCreateResizeAreaGroupById,
shouldAddResizeArea,
} from '../utils/interaction/resize';
-import { getFrozenColWidth } from '../utils/layout/frozen';
import { getSortTypeIcon } from '../utils/sort-action';
+import type { FrozenFacet } from '../facet/frozen-facet';
export class TableColCell extends ColCell {
protected handleRestOptions(...[headerConfig]: [BaseHeaderConfig]) {
@@ -33,18 +33,6 @@ export class TableColCell extends ColCell {
};
}
- protected isFrozenCell() {
- const { colCount = 0, trailingColCount = 0 } =
- this.spreadsheet.options.frozen!;
- const colNodes = this.spreadsheet.facet?.getColNodes(0);
- const { colIndex } = getNodeRoot(this.meta);
-
- return (
- isFrozenCol(colIndex, colCount) ||
- isFrozenTrailingCol(colIndex, trailingColCount, colNodes?.length)
- );
- }
-
protected getFormattedFieldValue(): FormatResult {
return formattedFieldValue(
this.meta,
@@ -53,7 +41,7 @@ export class TableColCell extends ColCell {
}
protected shouldAddVerticalResizeArea() {
- if (this.isFrozenCell()) {
+ if (this.getMeta().isFrozen) {
return true;
}
@@ -62,6 +50,7 @@ export class TableColCell extends ColCell {
scrollY,
width: headerWidth,
height: headerHeight,
+ spreadsheet,
} = this.getHeaderConfig();
const { x, y, width, height } = this.getBBoxByType();
const resizeStyle = this.getResizeAreaStyle();
@@ -73,17 +62,15 @@ export class TableColCell extends ColCell {
height,
};
- const frozenWidth = getFrozenColWidth(
- this.spreadsheet.facet.getColLeafNodes(),
- this.spreadsheet.options.frozen!,
- );
+ const frozenGroupInfo = (spreadsheet.facet as FrozenFacet).frozenGroupInfo;
+ const colWidth = frozenGroupInfo[FrozenGroupType.FROZEN_COL].width;
+ const trailingColWidth =
+ frozenGroupInfo[FrozenGroupType.FROZEN_TRAILING_COL].width;
+
const resizeClipAreaBBox: SimpleBBox = {
- x: frozenWidth.frozenColWidth,
+ x: colWidth,
y: 0,
- width:
- headerWidth -
- frozenWidth.frozenColWidth -
- frozenWidth.frozenTrailingColWidth,
+ width: headerWidth - colWidth - trailingColWidth,
height: headerHeight,
};
@@ -97,7 +84,7 @@ export class TableColCell extends ColCell {
const { x, y } = this.meta;
const { scrollX = 0, position } = this.getHeaderConfig();
- if (this.isFrozenCell()) {
+ if (this.getMeta().isFrozen) {
return {
x: position?.x + x,
y: position?.y + y,
@@ -111,9 +98,7 @@ export class TableColCell extends ColCell {
}
protected getColResizeArea() {
- const isFrozenCell = this.isFrozenCell();
-
- if (!isFrozenCell) {
+ if (!this.getMeta().isFrozen) {
return super.getColResizeArea();
}
@@ -142,16 +127,20 @@ export class TableColCell extends ColCell {
}
protected drawBackgroundShape() {
- const { backgroundColor } = this.getStyle()!.cell!;
+ const { backgroundColor, backgroundColorOpacity } =
+ this.getStyle()!.cell! || {};
this.backgroundShape = renderRect(this, {
...this.getBBoxByType(),
fill: backgroundColor,
+ fillOpacity: backgroundColorOpacity,
});
}
- protected handleViewport(viewport: AreaRange): AreaRange {
- if (this.isFrozenCell()) {
+ protected handleViewport(): AreaRange {
+ const viewport = super.handleViewport();
+
+ if (this.getMeta().isFrozen) {
viewport.start = 0;
}
diff --git a/packages/s2-core/src/cell/table-data-cell.ts b/packages/s2-core/src/cell/table-data-cell.ts
index 2f73f83cc9..13fa924d50 100644
--- a/packages/s2-core/src/cell/table-data-cell.ts
+++ b/packages/s2-core/src/cell/table-data-cell.ts
@@ -1,6 +1,7 @@
import { Frame } from '../facet/header/frame';
import { DataCell } from '../cell/data-cell';
import {
+ FrozenGroupType,
KEY_GROUP_FROZEN_ROW_RESIZE_AREA,
KEY_GROUP_ROW_RESIZE_AREA,
ResizeAreaEffect,
@@ -13,8 +14,10 @@ import {
import {
getOrCreateResizeAreaGroupById,
getResizeAreaAttrs,
+ shouldAddResizeArea,
} from '../utils/interaction/resize';
-import { CustomRect } from '../engine';
+import { CustomRect, type SimpleBBox } from '../engine';
+import type { FrozenFacet } from '../facet/frozen-facet';
import { BaseCell } from './base-cell';
export class TableDataCell extends DataCell {
@@ -32,7 +35,7 @@ export class TableDataCell extends DataCell {
protected shouldDrawResizeArea() {
// 每一行直绘制一条贯穿式 resize 热区
- const id = String(this.meta.rowIndex);
+ const id = `${this.meta.rowIndex}`;
const resizeArea = getOrCreateResizeAreaGroupById(
this.spreadsheet,
@@ -95,6 +98,36 @@ export class TableDataCell extends DataCell {
let offsetY =
y + headerHeight + Frame.getHorizontalBorderWidth(this.spreadsheet);
+ const frozenGroupInfo = (this.spreadsheet.facet as FrozenFacet)
+ .frozenGroupInfo;
+ const rowHeight = frozenGroupInfo[FrozenGroupType.FROZEN_ROW].height;
+ const rowTrailingHeight =
+ frozenGroupInfo[FrozenGroupType.FROZEN_TRAILING_ROW].height;
+
+ const resizeAreaBBox: SimpleBBox = {
+ x: 0,
+ y: y + height - resizeStyle.size!,
+ width: headerWidth,
+ height: resizeStyle.size!,
+ };
+ const resizeClipAreaBBox: SimpleBBox = {
+ x: 0,
+ y: rowHeight,
+ width: headerWidth,
+ height:
+ this.spreadsheet.facet.panelBBox.height - rowHeight - rowTrailingHeight,
+ };
+
+ if (
+ !isFrozen &&
+ !shouldAddResizeArea(resizeAreaBBox, resizeClipAreaBBox, {
+ scrollX: 0,
+ scrollY,
+ })
+ ) {
+ return;
+ }
+
if (!isFrozen) {
offsetY -= scrollY + paginationSy;
}
diff --git a/packages/s2-core/src/cell/table-series-number-cell.ts b/packages/s2-core/src/cell/table-series-number-cell.ts
index 8464f6500c..d5a0faef26 100644
--- a/packages/s2-core/src/cell/table-series-number-cell.ts
+++ b/packages/s2-core/src/cell/table-series-number-cell.ts
@@ -6,7 +6,7 @@ export class TableSeriesNumberCell extends TableDataCell {
public get cellType() {
/*
* 在行列冻结并且开启序号时
- * 那么在如果行头冻结2列,并且CellTypes设置成以前的RowCell时,【FrozenRowGroup的分割线】和【左上角和左下角的边框样式】样式会混乱
+ * 如果行头冻结 2 列,并且 CellTypes 设置成以前的 RowCell 时,【 FrozenRowGroup 的分割线】和【左上角和左下角的边框样式】样式会混乱
* 因此下层在选择到序号时,需要将 cellType 修改为 RowCell, 保证交互逻辑统一:
* packages/s2-core/src/utils/interaction/select-event.ts -> getCellMeta
*/
diff --git a/packages/s2-core/src/common/constant/basic.ts b/packages/s2-core/src/common/constant/basic.ts
index afdf8dd69b..680fb04a8b 100644
--- a/packages/s2-core/src/common/constant/basic.ts
+++ b/packages/s2-core/src/common/constant/basic.ts
@@ -1,33 +1,21 @@
import { i18n } from '../i18n';
-export const VALUE_FIELD = '$$value$$';
-export const EXTRA_FIELD = '$$extra$$';
-export const EXTRA_COLUMN_FIELD = '$$extra_column$$';
-
-export const SERIES_NUMBER_FIELD = '$$series_number$$';
-
-export const TOTAL_VALUE = '$$total$$';
-export const MULTI_VALUE = '$$multi$$';
-
-export const NULL_SYMBOL_ID = '$$null$$';
-export const UNDEFINED_SYMBOL_ID = '$$undefined$$';
-
+// 约定这个 z-index 为 0 的 container 作为基准
export const BACK_GROUND_GROUP_CONTAINER_Z_INDEX = 0;
-/*
- * foregroundGroup 上的 children 层叠顺序
- * 约定这个 z-index 为 0 的 container 作为基准
- */
+// foregroundGroup 上的 children 层叠顺序
export const FRONT_GROUND_GROUP_CONTAINER_Z_INDEX = 3;
-export const FRONT_GROUND_GROUP_COL_SCROLL_Z_INDEX = 3;
-export const FRONT_GROUND_GROUP_COL_FROZEN_Z_INDEX = 4;
+export const FRONT_GROUND_GROUP_SCROLL_Z_INDEX = 3;
+export const FRONT_GROUND_GROUP_FROZEN_Z_INDEX = 4;
export const FRONT_GROUND_GROUP_RESIZE_AREA_Z_INDEX = 5;
export const FRONT_GROUND_GROUP_BRUSH_SELECTION_Z_INDEX = 5;
// panelGroup 上的 children 层叠顺序
export const PANEL_GROUP_GROUP_CONTAINER_Z_INDEX = 1;
export const PANEL_GROUP_SCROLL_GROUP_Z_INDEX = 1;
-export const PANEL_GROUP_FROZEN_GROUP_Z_INDEX = 2;
+export const PANEL_GRID_GROUP_Z_INDEX = 2;
+export const PANEL_MERGE_GROUP_Z_INDEX = 3;
+export const PANEL_GROUP_FROZEN_GROUP_Z_INDEX = 4;
// group's key
export const KEY_GROUP_BACK_GROUND = 'backGroundGroup';
@@ -52,6 +40,8 @@ export const KEY_GROUP_COL_SCROLL = 'colScrollGroup';
export const KEY_GROUP_COL_FROZEN = 'colFrozenGroup';
export const KEY_GROUP_COL_FROZEN_TRAILING = 'colFrozenTrailingGroup';
export const KEY_GROUP_GRID_GROUP = 'gridGroup';
+export const KEY_GROUP_ROW_SCROLL = 'rowScrollGroup';
+export const KEY_GROUP_ROW_HEADER_FROZEN = 'rowHeaderFrozenGroup';
export const HORIZONTAL_RESIZE_AREA_KEY_PRE = 'horizontal-resize-area-';
@@ -73,9 +63,6 @@ export enum MiniChartTypes {
Bullet = 'bullet',
}
-// 线条 linecap 样式
-export const SQUARE_LINE_CAP = 'square';
-
export const getDefaultSeriesNumberText = (defaultText?: string) =>
defaultText ?? i18n('序号');
diff --git a/packages/s2-core/src/common/constant/copy.ts b/packages/s2-core/src/common/constant/copy.ts
index 8ba009648e..d3818f24a8 100644
--- a/packages/s2-core/src/common/constant/copy.ts
+++ b/packages/s2-core/src/common/constant/copy.ts
@@ -5,6 +5,7 @@ export enum CopyType {
}
export const NewLine = '\r\n';
+
export const NewTab = '\t';
// 每次异步渲染数据的阈值
diff --git a/packages/s2-core/src/common/constant/field.ts b/packages/s2-core/src/common/constant/field.ts
new file mode 100644
index 0000000000..6a677e5b88
--- /dev/null
+++ b/packages/s2-core/src/common/constant/field.ts
@@ -0,0 +1,12 @@
+// 值字段的 id 是固定的!
+export const VALUE_FIELD = '$$value$$';
+export const EXTRA_FIELD = '$$extra$$';
+export const ORIGIN_FIELD = '$$origin$$';
+export const EXTRA_COLUMN_FIELD = '$$extra_column$$';
+export const TOTAL_VALUE = '$$total$$';
+export const MULTI_VALUE = '$$multi$$';
+export const SERIES_NUMBER_FIELD = '$$series_number$$';
+export const EMPTY_FIELD_VALUE = '$$empty_field_value$$';
+export const EMPTY_EXTRA_FIELD_PLACEHOLDER = '$$empty_extra_placeholder$$';
+export const NULL_SYMBOL_ID = '$$null$$';
+export const UNDEFINED_SYMBOL_ID = '$$undefined$$';
diff --git a/packages/s2-core/src/common/constant/index.ts b/packages/s2-core/src/common/constant/index.ts
index 8bb7b84fac..c9e8259d6d 100644
--- a/packages/s2-core/src/common/constant/index.ts
+++ b/packages/s2-core/src/common/constant/index.ts
@@ -1,3 +1,4 @@
+export * from './field';
export * from './events';
export * from './basic';
export * from './classnames';
@@ -12,3 +13,4 @@ export * from './resize';
export * from './copy';
export * from './pagination';
export * from './node';
+export * from './query';
diff --git a/packages/s2-core/src/common/constant/interaction.ts b/packages/s2-core/src/common/constant/interaction.ts
index 0d775a572c..c8f7f8a641 100644
--- a/packages/s2-core/src/common/constant/interaction.ts
+++ b/packages/s2-core/src/common/constant/interaction.ts
@@ -17,6 +17,7 @@ export enum InteractionName {
export enum InteractionStateName {
ALL_SELECTED = 'allSelected',
SELECTED = 'selected',
+ BRUSH_SELECTED = 'brushSelected',
UNSELECTED = 'unselected',
HOVER = 'hover',
HOVER_FOCUS = 'hoverFocus',
diff --git a/packages/s2-core/src/common/constant/node.ts b/packages/s2-core/src/common/constant/node.ts
index 9f0023a63f..d24907d1ca 100644
--- a/packages/s2-core/src/common/constant/node.ts
+++ b/packages/s2-core/src/common/constant/node.ts
@@ -1,4 +1,3 @@
export const ROOT_NODE_ID = 'root';
-
export const NODE_ID_SEPARATOR = '[&]';
export const ROOT_BEGINNING_REGEX = /^root\[&\]*/;
diff --git a/packages/s2-core/src/common/constant/options.ts b/packages/s2-core/src/common/constant/options.ts
index 7481fe55c4..2dc5fa57b3 100644
--- a/packages/s2-core/src/common/constant/options.ts
+++ b/packages/s2-core/src/common/constant/options.ts
@@ -10,7 +10,13 @@ import { EMPTY_PLACEHOLDER } from './basic';
export const MIN_DEVICE_PIXEL_RATIO = 1;
-export enum LayoutWidthTypes {
+/**
+ * 布局类型:
+ * adaptive: 行列等宽,均分整个 canvas 画布宽度
+ * colAdaptive:列等宽,行头紧凑布局,列等分画布宽度减去行头宽度的剩余宽度
+ * compact:行列紧凑布局,指标维度少的时候无法布满整个画布
+ */
+export enum LayoutWidthType {
Adaptive = 'adaptive',
ColAdaptive = 'colAdaptive',
Compact = 'compact',
@@ -21,7 +27,7 @@ export const SPLIT_LINE_WIDTH = 1;
export const DEFAULT_TREE_ROW_CELL_WIDTH = 120;
export const DEFAULT_STYLE: S2Style = {
- layoutWidthType: LayoutWidthTypes.Adaptive,
+ layoutWidthType: LayoutWidthType.Adaptive,
rowCell: {
showTreeLeafNodeAlignDot: false,
widthByField: null,
@@ -112,7 +118,7 @@ export const DEFAULT_MOBILE_OPTIONS: S2Options = {
width: mobileWidth - 40,
height: 380,
style: {
- layoutWidthType: LayoutWidthTypes.ColAdaptive,
+ layoutWidthType: LayoutWidthType.ColAdaptive,
},
interaction: {
hoverHighlight: false,
diff --git a/packages/s2-core/src/common/constant/query.ts b/packages/s2-core/src/common/constant/query.ts
new file mode 100644
index 0000000000..7f642628c3
--- /dev/null
+++ b/packages/s2-core/src/common/constant/query.ts
@@ -0,0 +1,6 @@
+export enum QueryDataType {
+ /* 获取所有的数据 */
+ All = 'all',
+ /* 只需要明细数据 */
+ DetailOnly = 'detailOnly',
+}
diff --git a/packages/s2-core/src/common/constant/total.ts b/packages/s2-core/src/common/constant/total.ts
deleted file mode 100644
index 128ebdb566..0000000000
--- a/packages/s2-core/src/common/constant/total.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import type { TotalSelectionsOfMultiData } from '../../data-set/interface';
-
-export const DEFAULT_TOTAL_SELECTIONS: TotalSelectionsOfMultiData = {
- row: {
- grandTotalOnly: false,
- subTotalOnly: false,
- totalDimensions: true,
- },
- column: {
- grandTotalOnly: false,
- subTotalOnly: false,
- totalDimensions: true,
- },
-};
-
-export enum DataSelectType {
- // 获取所有的数据
- All = 'all',
- // 只需要明细数据
- DetailOnly = 'detailOny',
- // 只需要总计/小计数据
- TotalOnly = 'totalOnly',
-}
diff --git a/packages/s2-core/src/common/i18n/en_US.ts b/packages/s2-core/src/common/i18n/en_US.ts
index 88e8e2429a..fb88221d5c 100644
--- a/packages/s2-core/src/common/i18n/en_US.ts
+++ b/packages/s2-core/src/common/i18n/en_US.ts
@@ -1,7 +1,7 @@
export const EN_US = {
小计: 'Total',
总计: 'Total',
- 总和: 'SUM',
+ 总和: '(SUM)',
项: 'items',
已选择: 'selected',
序号: 'Index',
@@ -15,4 +15,5 @@ export const EN_US = {
升序: 'ASC',
降序: 'DESC',
不排序: 'No order',
+ ',': ', ',
};
diff --git a/packages/s2-core/src/common/i18n/zh_CN.ts b/packages/s2-core/src/common/i18n/zh_CN.ts
index 6e677d4684..45913deb78 100644
--- a/packages/s2-core/src/common/i18n/zh_CN.ts
+++ b/packages/s2-core/src/common/i18n/zh_CN.ts
@@ -1,7 +1,7 @@
export const ZH_CN = {
小计: '小计',
总计: '总计',
- 总和: '总和',
+ 总和: '(总和)',
项: '项',
已选择: '已选择',
序号: '序号',
@@ -16,4 +16,5 @@ export const ZH_CN = {
降序: '降序',
组内降序: '组内降序',
不排序: '不排序',
+ ',': ',',
};
diff --git a/packages/s2-core/src/common/icons/gui-icon.ts b/packages/s2-core/src/common/icons/gui-icon.ts
index 5c12f6f101..6812659e49 100644
--- a/packages/s2-core/src/common/icons/gui-icon.ts
+++ b/packages/s2-core/src/common/icons/gui-icon.ts
@@ -1,9 +1,10 @@
/**
- * @Description: 请严格要求 svg 的 viewBox,若设计产出的 svg 不是此规格,请叫其修改为 '0 0 1024 1024'
+ * @description: 请严格要求 svg 的 viewBox,若设计产出的 svg 不是此规格,请叫其修改为 '0 0 1024 1024'
*/
import { Group, type ImageStyleProps } from '@antv/g';
-import { omit, clone } from 'lodash';
+import { clone, omit } from 'lodash';
import { CustomImage } from '../../engine';
+import { DebuggerUtil } from '../debug';
import { getIcon } from './factory';
const STYLE_PLACEHOLDER = '