fix: test

This commit is contained in:
aaaaaajie 2025-04-24 15:42:05 +08:00
parent 8f7da2e5cb
commit d0a7b49cad
4 changed files with 274 additions and 321 deletions

View File

@ -1,8 +1,14 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { createMockServer, MockServer } from '@nocobase/test'; import { createMockServer, MockServer } from '@nocobase/test';
import fs from 'fs'; import { Workbook } from 'exceljs';
import os from 'os';
import path from 'path';
import XLSX from 'xlsx';
describe('export action', () => { describe('export action', () => {
let app: MockServer; let app: MockServer;
@ -79,11 +85,14 @@ describe('export action', () => {
expect(res.status).toBe(200); expect(res.status).toBe(200);
const buffer = res.body; const buffer = res.body;
const workbook = new Workbook();
const workbook = XLSX.read(buffer, { type: 'buffer' }); await workbook.xlsx.load(buffer);
const sheetName = workbook.SheetNames[0]; const worksheet = workbook.getWorksheet(1);
const sheet = workbook.Sheets[sheetName]; const sheetData = worksheet
const rows = XLSX.utils.sheet_to_json(sheet); .getSheetValues()
.slice(1)
.map((row: any[]) => row?.slice(1));
const rows = sheetData[0];
expect(rows.length).toBe(1); expect(rows.length).toBe(1);
}); });
}); });

View File

@ -13,10 +13,13 @@ import { uid } from '@nocobase/utils';
import fs from 'fs'; import fs from 'fs';
import moment from 'moment'; import moment from 'moment';
import path from 'path'; import path from 'path';
import XLSX from 'xlsx';
import { XlsxExporter } from '../services/xlsx-exporter'; import { XlsxExporter } from '../services/xlsx-exporter';
import { Workbook } from 'exceljs';
XLSX.set_fs(fs); function getXlsxData(worksheet) {
const data = worksheet.getSheetValues()[2];
return data.slice(1);
}
describe('export to xlsx with preset', () => { describe('export to xlsx with preset', () => {
let app: MockServer; let app: MockServer;
@ -98,7 +101,7 @@ describe('export to xlsx with preset', () => {
unixTimestamp: '2024-05-10T01:42:35.000Z', unixTimestamp: '2024-05-10T01:42:35.000Z',
}, },
}); });
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: Post, collection: Post,
@ -122,27 +125,23 @@ describe('export to xlsx with preset', () => {
defaultTitle: 'unixTimestamp', defaultTitle: 'unixTimestamp',
}, },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
try { try {
XLSX.writeFile(wb, xlsxFilePath); const workbook = new Workbook();
await workbook.xlsx.readFile(xlsxFilePath);
const worksheet = workbook.getWorksheet(1);
const firstUser = getXlsxData(worksheet);
// read xlsx file
const workbook = XLSX.readFile(xlsxFilePath);
const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
const firstUser = sheetData[1];
expect(firstUser[1]).toEqual('2024-05-10'); expect(firstUser[1]).toEqual('2024-05-10');
expect(firstUser[2]).toEqual('2024-05-10'); expect(firstUser[2]).toEqual('2024-05-10');
expect(firstUser[3]).toEqual('2024-01-01'); expect(firstUser[3]).toEqual('2024-01-01');
expect(firstUser[4]).toEqual('2024-05-10 01:42:35'); expect(firstUser[4]).toEqual('2024-05-10 01:42:35');
} finally { } finally {
fs.unlinkSync(xlsxFilePath); exporter.cleanOutputFile();
} }
}); });
}); });
@ -173,6 +172,7 @@ describe('export to xlsx with preset', () => {
}, },
}); });
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: Post, collection: Post,
@ -184,27 +184,20 @@ describe('export to xlsx with preset', () => {
defaultTitle: 'test_field', defaultTitle: 'test_field',
}, },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
try { try {
XLSX.writeFile(wb, xlsxFilePath); const workbook = new Workbook();
await workbook.xlsx.readFile(xlsxFilePath);
const worksheet = workbook.getWorksheet(1);
const data = getXlsxData(worksheet);
// read xlsx file
const workbook = XLSX.readFile(xlsxFilePath);
const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
const header = sheetData[0];
expect(header).toEqual(['Title', 'test_field']);
const data = sheetData[1];
expect(data[1]).toBe('True'); expect(data[1]).toBe('True');
} finally { } finally {
fs.unlinkSync(xlsxFilePath); exporter.cleanOutputFile();
} }
}); });
@ -238,6 +231,7 @@ describe('export to xlsx with preset', () => {
], ],
}); });
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: Post, collection: Post,
@ -257,36 +251,27 @@ describe('export to xlsx with preset', () => {
defaultTitle: 'decimal', defaultTitle: 'decimal',
}, },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
try { try {
XLSX.writeFile(wb, xlsxFilePath); const workbook = new Workbook();
await workbook.xlsx.readFile(xlsxFilePath);
const worksheet = workbook.getWorksheet(1);
const sheetData = worksheet
.getSheetValues()
.slice(2)
.map((row: any[]) => row?.slice(1));
// read xlsx file // cell type should be number and values as expected
const workbook = XLSX.readFile(xlsxFilePath); expect(sheetData[0][0]).toBe('p1');
const firstSheet = workbook.Sheets[workbook.SheetNames[0]]; expect(sheetData[0][1]).toBe(123);
expect(sheetData[0][2]).toBeCloseTo(123.456);
// cell type should be number expect(sheetData[0][3]).toBeCloseTo(234.567);
const cellA2 = firstSheet['A2'];
expect(cellA2.t).toBe('s');
expect(cellA2.v).toBe('p1');
const cellB2 = firstSheet['B2'];
expect(cellB2.t).toBe('n');
expect(cellB2.v).toBe(123);
const cellC2 = firstSheet['C2'];
expect(cellC2.t).toBe('n');
expect(cellC2.v).toBe(123.456);
const cellD2 = firstSheet['D2'];
expect(cellD2.t).toBe('n');
expect(cellD2.v).toBe(234.567);
} finally { } finally {
fs.unlinkSync(xlsxFilePath); exporter.cleanOutputFile();
} }
}); });
@ -319,6 +304,7 @@ describe('export to xlsx with preset', () => {
}, },
}); });
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: Post, collection: Post,
@ -330,27 +316,25 @@ describe('export to xlsx with preset', () => {
defaultTitle: 'circle', defaultTitle: 'circle',
}, },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
try { try {
XLSX.writeFile(wb, xlsxFilePath); const workbook = new Workbook();
await workbook.xlsx.readFile(xlsxFilePath);
// read xlsx file const worksheet = workbook.getWorksheet(1);
const workbook = XLSX.readFile(xlsxFilePath); const sheetData = worksheet
const firstSheet = workbook.Sheets[workbook.SheetNames[0]]; .getSheetValues()
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 }); .slice(1)
.map((row: any[]) => row?.slice(1));
const header = sheetData[0]; const header = sheetData[0];
expect(header).toEqual(['Title', 'circle']); expect(header).toEqual(['Title', 'circle']);
const firstUser = sheetData[1]; const firstUser = sheetData[1];
expect(firstUser[1]).toEqual('116.397428,39.90923,3241'); expect(firstUser[1]).toEqual('116.397428,39.90923,3241');
} finally { } finally {
fs.unlinkSync(xlsxFilePath); exporter.cleanOutputFile();
} }
}); });
@ -404,6 +388,7 @@ describe('export to xlsx with preset', () => {
}, },
}); });
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: Post, collection: Post,
@ -415,29 +400,25 @@ describe('export to xlsx with preset', () => {
defaultTitle: 'attachment', defaultTitle: 'attachment',
}, },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`); const workbook = new Workbook();
try { await workbook.xlsx.readFile(xlsxFilePath);
XLSX.writeFile(wb, xlsxFilePath); const worksheet = workbook.getWorksheet(1);
const sheetData = worksheet
// read xlsx file .getSheetValues()
const workbook = XLSX.readFile(xlsxFilePath); .slice(1)
const firstSheet = workbook.Sheets[workbook.SheetNames[0]]; .map((row: any[]) => row?.slice(1));
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 }); const header = sheetData[0];
expect(header).toEqual(['Title', 'attachment']);
const header = sheetData[0]; const firstUser = sheetData[1];
expect(header).toEqual(['Title', 'attachment']); expect(firstUser[1]).toEqual(
'https://nocobase.oss-cn-beijing.aliyuncs.com/test1.png,/storage/uploads/682e5ad037dd02a0fe4800a3e91c283b.png',
const firstUser = sheetData[1]; );
expect(firstUser[1]).toEqual( exporter.cleanOutputFile();
'https://nocobase.oss-cn-beijing.aliyuncs.com/test1.png,/storage/uploads/682e5ad037dd02a0fe4800a3e91c283b.png',
);
} finally {
fs.unlinkSync(xlsxFilePath);
}
}); });
it('should export with china region field', async () => { it('should export with china region field', async () => {
@ -465,6 +446,7 @@ describe('export to xlsx with preset', () => {
}, },
}); });
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: Post, collection: Post,
@ -476,27 +458,23 @@ describe('export to xlsx with preset', () => {
defaultTitle: 'region', defaultTitle: 'region',
}, },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`); const workbook = new Workbook();
try { await workbook.xlsx.readFile(xlsxFilePath);
XLSX.writeFile(wb, xlsxFilePath); const worksheet = workbook.getWorksheet(1);
const sheetData = worksheet
// read xlsx file .getSheetValues()
const workbook = XLSX.readFile(xlsxFilePath); .slice(1)
const firstSheet = workbook.Sheets[workbook.SheetNames[0]]; .map((row: any[]) => row?.slice(1));
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 }); const header = sheetData[0];
expect(header).toEqual(['Title', 'region']);
const header = sheetData[0]; const firstUser = sheetData[1];
expect(header).toEqual(['Title', 'region']); expect(firstUser).toEqual(['post0', '山西省/长治市/潞城区']);
exporter.cleanOutputFile();
const firstUser = sheetData[1];
expect(firstUser).toEqual(['post0', '山西省/长治市/潞城区']);
} finally {
fs.unlinkSync(xlsxFilePath);
}
}); });
}); });
@ -584,6 +562,7 @@ describe('export to xlsx', () => {
}, },
}); });
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: Post, collection: Post,
@ -595,19 +574,19 @@ describe('export to xlsx', () => {
defaultTitle: '', defaultTitle: '',
}, },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run({}); await exporter.run({});
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
try { try {
XLSX.writeFile(wb, xlsxFilePath); const workbook = new Workbook();
await workbook.xlsx.readFile(xlsxFilePath);
// read xlsx file const worksheet = workbook.getWorksheet(1);
const workbook = XLSX.readFile(xlsxFilePath); const sheetData = worksheet
const firstSheet = workbook.Sheets[workbook.SheetNames[0]]; .getSheetValues()
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 }); .slice(1)
.map((row: any[]) => row?.slice(1));
const firstUser = sheetData[1]; const firstUser = sheetData[1];
expect(firstUser).toEqual([ expect(firstUser).toEqual([
'some_title', 'some_title',
@ -618,7 +597,7 @@ describe('export to xlsx', () => {
}), }),
]); ]);
} finally { } finally {
fs.unlinkSync(xlsxFilePath); exporter.cleanOutputFile();
} }
}); });
@ -653,6 +632,7 @@ describe('export to xlsx', () => {
}, },
}); });
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: Post, collection: Post,
@ -664,24 +644,21 @@ describe('export to xlsx', () => {
defaultTitle: '', defaultTitle: '',
}, },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`); const workbook = new Workbook();
try { await workbook.xlsx.readFile(xlsxFilePath);
XLSX.writeFile(wb, xlsxFilePath); const worksheet = workbook.getWorksheet(1);
const sheetData = worksheet
// read xlsx file .getSheetValues()
const workbook = XLSX.readFile(xlsxFilePath); .slice(1)
const firstSheet = workbook.Sheets[workbook.SheetNames[0]]; .map((row: any[]) => row?.slice(1));
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 }); const firstUser = sheetData[1];
expect(firstUser).toEqual(['some_title', '2024-05-10 01:42:35']);
const firstUser = sheetData[1]; exporter.cleanOutputFile();
expect(firstUser).toEqual(['some_title', '2024-05-10 01:42:35']);
} finally {
fs.unlinkSync(xlsxFilePath);
}
}); });
it('should export with multi select', async () => { it('should export with multi select', async () => {
@ -727,6 +704,7 @@ describe('export to xlsx', () => {
}, },
}); });
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: User, collection: User,
@ -738,24 +716,21 @@ describe('export to xlsx', () => {
defaultTitle: '', defaultTitle: '',
}, },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`); const workbook = new Workbook();
try { await workbook.xlsx.readFile(xlsxFilePath);
XLSX.writeFile(wb, xlsxFilePath); const worksheet = workbook.getWorksheet(1);
const sheetData = worksheet
// read xlsx file .getSheetValues()
const workbook = XLSX.readFile(xlsxFilePath); .slice(1)
const firstSheet = workbook.Sheets[workbook.SheetNames[0]]; .map((row: any[]) => row?.slice(1));
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 }); const firstUser = sheetData[1];
expect(firstUser).toEqual(['u1', 'Label123,Label223']);
const firstUser = sheetData[1]; exporter.cleanOutputFile();
expect(firstUser).toEqual(['u1', 'Label123,Label223']);
} finally {
fs.unlinkSync(xlsxFilePath);
}
}); });
it('should export with different ui schema', async () => { it('should export with different ui schema', async () => {
@ -793,6 +768,7 @@ describe('export to xlsx', () => {
await User.model.bulkCreate(values); await User.model.bulkCreate(values);
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: User, collection: User,
@ -804,37 +780,26 @@ describe('export to xlsx', () => {
defaultTitle: '', defaultTitle: '',
}, },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
try { try {
await new Promise((resolve, reject) => { const workbook = new Workbook();
XLSX.writeFileAsync( await workbook.xlsx.readFile(xlsxFilePath);
xlsxFilePath, const worksheet = workbook.getWorksheet(1);
wb, const sheetData = worksheet
{ .getSheetValues()
type: 'array', .slice(1)
}, .map((row: any[]) => row?.slice(1));
() => {
resolve(123);
},
);
});
// read xlsx file
const workbook = XLSX.readFile(xlsxFilePath);
const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
const header = sheetData[0]; const header = sheetData[0];
expect(header).toEqual(['姓名', 'Interface 测试']); expect(header).toEqual(['姓名', 'Interface 测试']);
const firstUser = sheetData[1]; const firstUser = sheetData[1];
expect(firstUser).toEqual(['user0', 'testValue.0']); expect(firstUser).toEqual(['user0', 'testValue.0']);
} finally { } finally {
fs.unlinkSync(xlsxFilePath); exporter.cleanOutputFile();
} }
}); });
@ -857,6 +822,7 @@ describe('export to xlsx', () => {
await User.model.bulkCreate(values); await User.model.bulkCreate(values);
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: User, collection: User,
@ -872,34 +838,23 @@ describe('export to xlsx', () => {
}, },
}, },
}, },
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
try { try {
await new Promise((resolve, reject) => { const workbook = new Workbook();
XLSX.writeFileAsync( await workbook.xlsx.readFile(xlsxFilePath);
xlsxFilePath, const worksheet = workbook.getWorksheet(1);
wb, const sheetData = worksheet
{ .getSheetValues()
type: 'array', .slice(1)
}, .map((row: any[]) => row?.slice(1));
() => {
resolve(123);
},
);
});
// read xlsx file
const workbook = XLSX.readFile(xlsxFilePath);
const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
const header = sheetData[0]; const header = sheetData[0];
expect(header).toEqual(['123', '345']); expect(header).toEqual(['123', '345']);
} finally { } finally {
fs.unlinkSync(xlsxFilePath); exporter.cleanOutputFile();
} }
}); });
@ -922,6 +877,7 @@ describe('export to xlsx', () => {
await User.model.bulkCreate(values); await User.model.bulkCreate(values);
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: User, collection: User,
@ -937,34 +893,23 @@ describe('export to xlsx', () => {
}, },
}, },
}, },
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
try { try {
await new Promise((resolve, reject) => { const workbook = new Workbook();
XLSX.writeFileAsync( await workbook.xlsx.readFile(xlsxFilePath);
xlsxFilePath, const worksheet = workbook.getWorksheet(1);
wb, const sheetData = worksheet
{ .getSheetValues()
type: 'array', .slice(1)
}, .map((row: any[]) => row?.slice(1));
() => {
resolve(123);
},
);
});
// read xlsx file
const workbook = XLSX.readFile(xlsxFilePath);
const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
const header = sheetData[0]; const header = sheetData[0];
expect(header).toEqual(['姓名', '年龄']); expect(header).toEqual(['姓名', '年龄']);
} finally { } finally {
fs.unlinkSync(xlsxFilePath); exporter.cleanOutputFile();
} }
}); });
@ -988,6 +933,7 @@ describe('export to xlsx', () => {
await User.model.bulkCreate(values); await User.model.bulkCreate(values);
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: User, collection: User,
@ -1003,29 +949,19 @@ describe('export to xlsx', () => {
}, },
}, },
}, },
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
try { try {
await new Promise((resolve, reject) => { const workbook = new Workbook();
XLSX.writeFileAsync( await workbook.xlsx.readFile(xlsxFilePath);
xlsxFilePath, const worksheet = workbook.getWorksheet(1);
wb, const sheetData = worksheet
{ .getSheetValues()
type: 'array', .slice(1)
}, .map((row: any[]) => row?.slice(1));
() => {
resolve(123);
},
);
});
// read xlsx file
const workbook = XLSX.readFile(xlsxFilePath);
const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
expect(sheetData.length).toBe(11); // 10 users + 1 header expect(sheetData.length).toBe(11); // 10 users + 1 header
const header = sheetData[0]; const header = sheetData[0];
@ -1034,7 +970,7 @@ describe('export to xlsx', () => {
const firstUser = sheetData[1]; const firstUser = sheetData[1];
expect(firstUser).toEqual(['user10', 10]); expect(firstUser).toEqual(['user10', 10]);
} finally { } finally {
fs.unlinkSync(xlsxFilePath); exporter.cleanOutputFile();
} }
}); });
@ -1117,6 +1053,7 @@ describe('export to xlsx', () => {
values, values,
}); });
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: User, collection: User,
@ -1128,29 +1065,19 @@ describe('export to xlsx', () => {
{ dataIndex: ['groups', 'name'], defaultTitle: 'Group Names' }, { dataIndex: ['groups', 'name'], defaultTitle: 'Group Names' },
{ dataIndex: ['createdAt'], defaultTitle: 'Created at' }, { dataIndex: ['createdAt'], defaultTitle: 'Created at' },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
try { try {
await new Promise((resolve, reject) => { const workbook = new Workbook();
XLSX.writeFileAsync( await workbook.xlsx.readFile(xlsxFilePath);
xlsxFilePath, const worksheet = workbook.getWorksheet(1);
wb, const sheetData = worksheet
{ .getSheetValues()
type: 'array', .slice(1)
}, .map((row: any[]) => row?.slice(1));
() => {
resolve(123);
},
);
});
// read xlsx file
const workbook = XLSX.readFile(xlsxFilePath);
const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
expect(sheetData.length).toBe(23); // 22 users * 3 posts + 1 header expect(sheetData.length).toBe(23); // 22 users * 3 posts + 1 header
const header = sheetData[0]; const header = sheetData[0];
@ -1165,7 +1092,7 @@ describe('export to xlsx', () => {
moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD'),
]); ]);
} finally { } finally {
fs.unlinkSync(xlsxFilePath); exporter.cleanOutputFile();
} }
}); });
@ -1189,6 +1116,7 @@ describe('export to xlsx', () => {
await User.model.bulkCreate(values); await User.model.bulkCreate(values);
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: User, collection: User,
@ -1197,29 +1125,19 @@ describe('export to xlsx', () => {
{ dataIndex: ['name'], defaultTitle: 'Name' }, { dataIndex: ['name'], defaultTitle: 'Name' },
{ dataIndex: ['age'], defaultTitle: 'Age' }, { dataIndex: ['age'], defaultTitle: 'Age' },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
try { try {
await new Promise((resolve, reject) => { const workbook = new Workbook();
XLSX.writeFileAsync( await workbook.xlsx.readFile(xlsxFilePath);
xlsxFilePath, const worksheet = workbook.getWorksheet(1);
wb, const sheetData = worksheet
{ .getSheetValues()
type: 'array', .slice(1)
}, .map((row: any[]) => row?.slice(1));
() => {
resolve(123);
},
);
});
// read xlsx file
const workbook = XLSX.readFile(xlsxFilePath);
const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
expect(sheetData.length).toBe(23); // 22 users + 1 header expect(sheetData.length).toBe(23); // 22 users + 1 header
const header = sheetData[0]; const header = sheetData[0];
@ -1228,7 +1146,7 @@ describe('export to xlsx', () => {
const firstUser = sheetData[1]; const firstUser = sheetData[1];
expect(firstUser).toEqual(['user0', 0]); expect(firstUser).toEqual(['user0', 0]);
} finally { } finally {
fs.unlinkSync(xlsxFilePath); exporter.cleanOutputFile();
} }
}); });
@ -1332,6 +1250,7 @@ describe('export to xlsx', () => {
values, values,
}); });
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: User, collection: User,
@ -1343,37 +1262,26 @@ describe('export to xlsx', () => {
defaultTitle: 'Test Field', defaultTitle: 'Test Field',
}, },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
try { try {
await new Promise((resolve, reject) => { const workbook = new Workbook();
XLSX.writeFileAsync( await workbook.xlsx.readFile(xlsxFilePath);
xlsxFilePath, const worksheet = workbook.getWorksheet(1);
wb, const sheetData = worksheet
{ .getSheetValues()
type: 'array', .slice(1)
}, .map((row: any[]) => row?.slice(1));
() => {
resolve(123);
},
);
});
// read xlsx file
const workbook = XLSX.readFile(xlsxFilePath);
const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
const header = sheetData[0]; const header = sheetData[0];
expect(header).toEqual(['Name', 'Associations interface 测试']); expect(header).toEqual(['Name', 'Associations interface 测试']);
const firstUser = sheetData[1]; const firstUser = sheetData[1];
expect(firstUser).toEqual(['user0', 'testValue.1,testValue.2,testValue.3']); expect(firstUser).toEqual(['user0', 'testValue.1,testValue.2,testValue.3']);
} finally { } finally {
fs.unlinkSync(xlsxFilePath); exporter.cleanOutputFile();
} }
}); });
@ -1399,6 +1307,7 @@ describe('export to xlsx', () => {
await User.model.bulkCreate(values); await User.model.bulkCreate(values);
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: User, collection: User,
@ -1407,16 +1316,25 @@ describe('export to xlsx', () => {
{ dataIndex: ['name'], defaultTitle: 'Name' }, { dataIndex: ['name'], defaultTitle: 'Name' },
{ dataIndex: ['age'], defaultTitle: 'Age' }, { dataIndex: ['age'], defaultTitle: 'Age' },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const firstSheet = wb.Sheets[wb.SheetNames[0]]; try {
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 }); const workbook = new Workbook();
await workbook.xlsx.readFile(xlsxFilePath);
expect(sheetData.length).toBe(31); // 30 users + 1 header const worksheet = workbook.getWorksheet(1);
expect(sheetData[0]).toEqual(['Name', 'Age']); // header const sheetData = worksheet
expect(sheetData[1]).toEqual(['user0', 0]); // first user .getSheetValues()
expect(sheetData[30]).toEqual(['user29', 29]); // last user .slice(1)
.map((row: any[]) => row?.slice(1));
expect(sheetData.length).toBe(31); // 30 users + 1 header
expect(sheetData[0]).toEqual(['Name', 'Age']); // header
expect(sheetData[1]).toEqual(['user0', 0]); // first user
expect(sheetData[30]).toEqual(['user29', 29]); // last user
} finally {
exporter.cleanOutputFile();
}
}); });
it('should use default EXPORT_LIMIT (2000) when env not set', async () => { it('should use default EXPORT_LIMIT (2000) when env not set', async () => {
@ -1439,6 +1357,7 @@ describe('export to xlsx', () => {
await User.model.bulkCreate(values); await User.model.bulkCreate(values);
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: User, collection: User,
@ -1447,16 +1366,25 @@ describe('export to xlsx', () => {
{ dataIndex: ['name'], defaultTitle: 'Name' }, { dataIndex: ['name'], defaultTitle: 'Name' },
{ dataIndex: ['age'], defaultTitle: 'Age' }, { dataIndex: ['age'], defaultTitle: 'Age' },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const firstSheet = wb.Sheets[wb.SheetNames[0]]; try {
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 }); const workbook = new Workbook();
await workbook.xlsx.readFile(xlsxFilePath);
expect(sheetData.length).toBe(2001); // 2000 users + 1 header const worksheet = workbook.getWorksheet(1);
expect(sheetData[0]).toEqual(['Name', 'Age']); // header const sheetData = worksheet
expect(sheetData[1]).toEqual(['user0', 0]); // first user .getSheetValues()
expect(sheetData[2000]).toEqual(['user1999', 99]); // last user .slice(1)
.map((row: any[]) => row?.slice(1));
expect(sheetData.length).toBe(2001); // 2000 users + 1 header
expect(sheetData[0]).toEqual(['Name', 'Age']); // header
expect(sheetData[1]).toEqual(['user0', 0]); // first user
expect(sheetData[2000]).toEqual(['user1999', 99]); // last user
} finally {
exporter.cleanOutputFile();
}
}); });
it('should respect the limit option when exporting data', async () => { it('should respect the limit option when exporting data', async () => {
@ -1479,6 +1407,7 @@ describe('export to xlsx', () => {
await User.model.bulkCreate(values); await User.model.bulkCreate(values);
const xlsxFilePath = path.resolve(__dirname, `t_${uid()}.xlsx`);
const exporter = new XlsxExporter({ const exporter = new XlsxExporter({
collectionManager: app.mainDataSource.collectionManager, collectionManager: app.mainDataSource.collectionManager,
collection: User, collection: User,
@ -1488,15 +1417,24 @@ describe('export to xlsx', () => {
{ dataIndex: ['name'], defaultTitle: 'Name' }, { dataIndex: ['name'], defaultTitle: 'Name' },
{ dataIndex: ['age'], defaultTitle: 'Age' }, { dataIndex: ['age'], defaultTitle: 'Age' },
], ],
outputPath: xlsxFilePath,
}); });
const wb = await exporter.run(); await exporter.run();
const firstSheet = wb.Sheets[wb.SheetNames[0]]; try {
const sheetData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 }); const workbook = new Workbook();
await workbook.xlsx.readFile(xlsxFilePath);
expect(sheetData.length).toBe(11); // 10 users + 1 header const worksheet = workbook.getWorksheet(1);
expect(sheetData[0]).toEqual(['Name', 'Age']); // header const sheetData = worksheet
expect(sheetData[1]).toEqual(['user0', 0]); // first user .getSheetValues()
expect(sheetData[10]).toEqual(['user9', 9]); // last user .slice(1)
.map((row: any[]) => row?.slice(1));
expect(sheetData.length).toBe(11); // 10 users + 1 header
expect(sheetData[0]).toEqual(['Name', 'Age']); // header
expect(sheetData[1]).toEqual(['user0', 0]); // first user
expect(sheetData[10]).toEqual(['user9', 9]); // last user
} finally {
exporter.cleanOutputFile();
}
}); });
}); });

View File

@ -32,6 +32,7 @@ export type ExportOptions = {
chunkSize?: number; chunkSize?: number;
limit?: number; limit?: number;
logger?: Logger; logger?: Logger;
outputPath?: string;
}; };
abstract class BaseExporter<T extends ExportOptions = ExportOptions> extends EventEmitter { abstract class BaseExporter<T extends ExportOptions = ExportOptions> extends EventEmitter {

View File

@ -42,10 +42,10 @@ export class XlsxExporter extends BaseExporter<XlsxExportOptions & { fields: Arr
constructor(options: XlsxExportOptions) { constructor(options: XlsxExportOptions) {
const fields = options.columns.map((col) => col.dataIndex); const fields = options.columns.map((col) => col.dataIndex);
super({ ...options, fields }); super({ ...options, fields });
this.outputPath = options.outputPath || this.generateOutputPath('xlsx', '.xlsx');
} }
async init(ctx?): Promise<void> { async init(ctx?): Promise<void> {
this.outputPath = this.generateOutputPath('xlsx', '.xlsx');
this.workbook = new Excel.stream.xlsx.WorkbookWriter({ this.workbook = new Excel.stream.xlsx.WorkbookWriter({
filename: this.outputPath, filename: this.outputPath,
useStyles: true, useStyles: true,
@ -56,7 +56,7 @@ export class XlsxExporter extends BaseExporter<XlsxExportOptions & { fields: Arr
}); });
this.worksheet.columns = this.options.columns.map((x) => ({ this.worksheet.columns = this.options.columns.map((x) => ({
key: x.dataIndex[0], key: x.dataIndex[0],
header: x.title || x.defaultTitle, header: this.renderHeader(x),
})); }));
this.worksheet.getRow(1).font = { bold: true }; this.worksheet.getRow(1).font = { bold: true };
this.worksheet.getRow(1).commit(); this.worksheet.getRow(1).commit();
@ -84,4 +84,9 @@ export class XlsxExporter extends BaseExporter<XlsxExportOptions & { fields: Arr
const buffer = fs.readFileSync(this.outputPath); const buffer = fs.readFileSync(this.outputPath);
return buffer; return buffer;
} }
private renderHeader(col: ExportColumn) {
const fieldInstance = this.findFieldByDataIndex(col.dataIndex);
return col.title || fieldInstance?.options.title || col.defaultTitle;
}
} }