allinssl/frontend/packages/gulp-build-tools/test/compress.test.ts

314 lines
10 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { createCompressTask, compressHelpers, batchCompress } from '../src/modules/compress.js';
import { CompressConfig } from '../src/types.js';
import fs from 'fs';
import path from 'path';
import { rimraf } from 'rimraf';
import { createReadStream } from 'fs';
import { createGunzip } from 'zlib';
import { extract } from 'tar-fs';
describe('compress module', () => {
const testDir = './test-temp/compress';
const srcDir = path.join(testDir, 'src');
const destDir = path.join(testDir, 'dest');
beforeEach(async () => {
await fs.promises.mkdir(srcDir, { recursive: true });
await fs.promises.mkdir(destDir, { recursive: true });
// 创建测试文件
await fs.promises.writeFile(path.join(srcDir, 'file1.txt'), 'This is test file 1');
await fs.promises.writeFile(path.join(srcDir, 'file2.txt'), 'This is test file 2');
// 创建子目录和文件
const subDir = path.join(srcDir, 'subdir');
await fs.promises.mkdir(subDir, { recursive: true });
await fs.promises.writeFile(path.join(subDir, 'file3.txt'), 'This is test file 3 in subdirectory');
});
afterEach(async () => {
await rimraf(testDir);
});
describe('createCompressTask', () => {
it('should create ZIP archive', async () => {
const config: CompressConfig = {
src: path.join(srcDir, '**/*'),
filename: 'test.zip',
dest: destDir,
type: 'zip'
};
const task = createCompressTask(config);
await new Promise<void>((resolve, reject) => {
task((error?: Error) => {
if (error) reject(error);
else resolve();
});
});
const zipPath = path.join(destDir, 'test.zip');
expect(fs.existsSync(zipPath)).toBe(true);
const stats = await fs.promises.stat(zipPath);
expect(stats.size).toBeGreaterThan(0);
});
it('should create TAR archive', async () => {
const config: CompressConfig = {
src: path.join(srcDir, '**/*'),
filename: 'test.tar',
dest: destDir,
type: 'tar'
};
const task = createCompressTask(config);
await new Promise<void>((resolve, reject) => {
task((error?: Error) => {
if (error) reject(error);
else resolve();
});
});
const tarPath = path.join(destDir, 'test.tar');
expect(fs.existsSync(tarPath)).toBe(true);
const stats = await fs.promises.stat(tarPath);
expect(stats.size).toBeGreaterThan(0);
});
it('should create GZIP archive', async () => {
const config: CompressConfig = {
src: path.join(srcDir, '**/*'),
filename: 'test.tar.gz',
dest: destDir,
type: 'gzip'
};
const task = createCompressTask(config);
await new Promise<void>((resolve, reject) => {
task((error?: Error) => {
if (error) reject(error);
else resolve();
});
});
const gzipPath = path.join(destDir, 'test.tar.gz');
expect(fs.existsSync(gzipPath)).toBe(true);
const stats = await fs.promises.stat(gzipPath);
expect(stats.size).toBeGreaterThan(0);
});
it('should handle different compression levels', async () => {
const configs: CompressConfig[] = [
{
src: path.join(srcDir, '**/*'),
filename: 'fast.zip',
dest: destDir,
type: 'zip',
level: 1
},
{
src: path.join(srcDir, '**/*'),
filename: 'best.zip',
dest: destDir,
type: 'zip',
level: 9
}
];
for (const config of configs) {
const task = createCompressTask(config);
await new Promise<void>((resolve, reject) => {
task((error?: Error) => {
if (error) reject(error);
else resolve();
});
});
}
const fastStats = await fs.promises.stat(path.join(destDir, 'fast.zip'));
const bestStats = await fs.promises.stat(path.join(destDir, 'best.zip'));
expect(fastStats.size).toBeGreaterThan(0);
expect(bestStats.size).toBeGreaterThan(0);
// 通常最高压缩级别的文件应该更小,但对于小文件可能差异不大
});
});
describe('compressHelpers', () => {
it('should create config correctly', () => {
const config = compressHelpers.createConfig(
'src/**/*',
'test.zip',
'dest',
{ level: 8, type: 'zip' }
);
expect(config.src).toBe('src/**/*');
expect(config.filename).toBe('test.zip');
expect(config.dest).toBe('dest');
expect(config.level).toBe(8);
expect(config.type).toBe('zip');
});
it('should infer type from filename', () => {
expect(compressHelpers.inferType('test.zip')).toBe('zip');
expect(compressHelpers.inferType('test.tar')).toBe('tar');
expect(compressHelpers.inferType('test.tar.gz')).toBe('gzip');
expect(compressHelpers.inferType('test.tgz')).toBe('gzip');
expect(compressHelpers.inferType('unknown.ext')).toBe('zip');
});
it('should generate timestamped filename', () => {
const filename = compressHelpers.timestampedFilename('backup');
expect(filename).toMatch(/^backup-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}\.zip$/);
const customExt = compressHelpers.timestampedFilename('backup', 'tar.gz');
expect(customExt).toMatch(/^backup-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}\.tar\.gz$/);
});
it('should get compression levels', () => {
expect(compressHelpers.getCompressionLevel('speed')).toBe(1);
expect(compressHelpers.getCompressionLevel('size')).toBe(9);
expect(compressHelpers.getCompressionLevel('balanced')).toBe(6);
expect(compressHelpers.getCompressionLevel()).toBe(6); // default
});
it('should validate config', () => {
const validConfig: CompressConfig = {
src: 'src/**/*',
filename: 'test.zip',
dest: 'dest'
};
expect(compressHelpers.validateConfig(validConfig)).toEqual([]);
const invalidConfig: CompressConfig = {
src: '',
filename: '',
dest: '',
level: 15
};
const errors = compressHelpers.validateConfig(invalidConfig);
expect(errors).toContain('缺少源文件路径');
expect(errors).toContain('缺少压缩包文件名');
expect(errors).toContain('缺少输出目录');
expect(errors).toContain('压缩级别必须在 0-9 之间');
});
});
describe('batchCompress', () => {
it('should handle multiple compress operations', async () => {
const configs: CompressConfig[] = [
{
src: path.join(srcDir, '*.txt'),
filename: 'texts.zip',
dest: destDir
},
{
src: path.join(srcDir, 'subdir/**/*'),
filename: 'subdir.zip',
dest: destDir
}
];
const results = await batchCompress(configs);
expect(results).toHaveLength(2);
expect(results[0].success).toBe(true);
expect(results[1].success).toBe(true);
expect(fs.existsSync(path.join(destDir, 'texts.zip'))).toBe(true);
expect(fs.existsSync(path.join(destDir, 'subdir.zip'))).toBe(true);
});
it('should handle errors gracefully', async () => {
const configs: CompressConfig[] = [
{
src: 'non-existent/**/*',
filename: 'test.zip',
dest: '/invalid/path'
}
];
const results = await batchCompress(configs);
expect(results).toHaveLength(1);
expect(results[0].success).toBe(false);
expect(results[0].error).toBeDefined();
});
});
describe('real-world scenarios', () => {
it('should compress build directory', async () => {
// 模拟构建目录结构
const buildDir = path.join(srcDir, 'build');
await fs.promises.mkdir(path.join(buildDir, 'js'), { recursive: true });
await fs.promises.mkdir(path.join(buildDir, 'css'), { recursive: true });
await fs.promises.mkdir(path.join(buildDir, 'assets'), { recursive: true });
await fs.promises.writeFile(path.join(buildDir, 'index.html'), '<html>...</html>');
await fs.promises.writeFile(path.join(buildDir, 'js', 'app.js'), 'console.log("app");');
await fs.promises.writeFile(path.join(buildDir, 'css', 'style.css'), '.app {}');
await fs.promises.writeFile(path.join(buildDir, 'assets', 'logo.png'), 'fake-png-data');
const config: CompressConfig = {
src: path.join(buildDir, '**/*'),
filename: compressHelpers.timestampedFilename('build'),
dest: destDir,
level: compressHelpers.getCompressionLevel('balanced')
};
const task = createCompressTask(config);
await new Promise<void>((resolve, reject) => {
task((error?: Error) => {
if (error) reject(error);
else resolve();
});
});
const files = await fs.promises.readdir(destDir);
const zipFile = files.find(f => f.startsWith('build-') && f.endsWith('.zip'));
expect(zipFile).toBeDefined();
if (zipFile) {
const stats = await fs.promises.stat(path.join(destDir, zipFile));
expect(stats.size).toBeGreaterThan(0);
}
});
it('should create release package with version', async () => {
const version = '1.2.3';
const config: CompressConfig = {
src: path.join(srcDir, '**/*'),
filename: `release-v${version}.tar.gz`,
dest: destDir,
type: 'gzip',
level: 9
};
const task = createCompressTask(config);
await new Promise<void>((resolve, reject) => {
task((error?: Error) => {
if (error) reject(error);
else resolve();
});
});
const releasePath = path.join(destDir, `release-v${version}.tar.gz`);
expect(fs.existsSync(releasePath)).toBe(true);
const stats = await fs.promises.stat(releasePath);
expect(stats.size).toBeGreaterThan(0);
});
});
});