@ordojs/cli
Version:
Command-line interface for OrdoJS framework
306 lines (268 loc) • 9.32 kB
text/typescript
/**
* @fileoverview Tests for the asset optimizer
*/
import { describe, expect, it, vi } from 'vitest';
import { AssetOptimizer } from './asset-optimizer.js';
import * as fs from './fs.js';
// Mock the fs module
vi.mock('./fs.js', () => ({
readFile: vi.fn(),
writeFile: vi.fn(),
mkdir: vi.fn()
}));
// Mock the terser module
vi.mock('terser', () => ({
Terser: {
minify: vi.fn()
}
}));
// Mock the brotli module
vi.mock('brotli', () => ({
compress: vi.fn()
}));
// Mock the gzip-size module
vi.mock('gzip-size', () => ({
default: vi.fn()
}));
describe('AssetOptimizer', () => {
beforeEach(() => {
vi.resetAllMocks();
});
describe('constructor', () => {
it('should create an instance with default options', () => {
const optimizer = new AssetOptimizer();
expect(optimizer).toBeDefined();
});
it('should create an instance with custom options', () => {
const optimizer = new AssetOptimizer({
minifyJs: false,
minifyCss: false,
brotli: false,
gzip: false
});
expect(optimizer).toBeDefined();
});
});
describe('optimizeJavaScript', () => {
it('should optimize JavaScript files', async () => {
// Mock the readFile function
vi.mocked(fs.readFile).mockResolvedValue('function test() { console.log("test"); }');
// Mock the Terser.minify function
vi.mocked(require('terser').Terser.minify).mockResolvedValue({
code: 'function test(){console.log("test")}',
map: undefined
});
// Mock the gzip-size function
vi.mocked(require('gzip-size').default).mockResolvedValue(30);
// Mock the brotli.compress function
vi.mocked(require('brotli').compress).mockReturnValue(Buffer.from('compressed'));
const optimizer = new AssetOptimizer({
minifyJs: true,
minifyCss: true,
brotli: true,
gzip: true
});
const result = await optimizer.optimizeJavaScript('test.js');
expect(result).toBeDefined();
expect(result.filePath).toBe('test.js');
expect(result.type).toBe('js');
expect(result.minified).toBe(true);
expect(result.gzipped).toBe(true);
expect(result.brotlified).toBe(true);
expect(result.sizes.originalSize).toBeGreaterThan(0);
expect(result.sizes.minifiedSize).toBeGreaterThan(0);
expect(result.sizes.gzipSize).toBe(30);
expect(result.sizes.brotliSize).toBe(10); // Length of 'compressed'
});
});
describe('optimizeCSS', () => {
it('should optimize CSS files', async () => {
// Mock the readFile function
vi.mocked(fs.readFile).mockResolvedValue('body { color: red; }');
// Mock the gzip-size function
vi.mocked(require('gzip-size').default).mockResolvedValue(20);
// Mock the brotli.compress function
vi.mocked(require('brotli').compress).mockReturnValue(Buffer.from('compressed'));
const optimizer = new AssetOptimizer({
minifyJs: true,
minifyCss: true,
brotli: true,
gzip: true
});
const result = await optimizer.optimizeCSS('test.css');
expect(result).toBeDefined();
expect(result.filePath).toBe('test.css');
expect(result.type).toBe('css');
expect(result.minified).toBe(true);
expect(result.gzipped).toBe(true);
expect(result.brotlified).toBe(true);
expect(result.sizes.originalSize).toBeGreaterThan(0);
expect(result.sizes.gzipSize).toBe(20);
expect(result.sizes.brotliSize).toBe(10); // Length of 'compressed'
});
});
describe('optimizeHTML', () => {
it('should optimize HTML files', async () => {
// Mock the readFile function
vi.mocked(fs.readFile).mockResolvedValue('<!DOCTYPE html><html><body>Test</body></html>');
// Mock the gzip-size function
vi.mocked(require('gzip-size').default).mockResolvedValue(25);
// Mock the brotli.compress function
vi.mocked(require('brotli').compress).mockReturnValue(Buffer.from('compressed'));
const optimizer = new AssetOptimizer({
minifyJs: true,
minifyCss: true,
brotli: true,
gzip: true
});
const result = await optimizer.optimizeHTML('test.html');
expect(result).toBeDefined();
expect(result.filePath).toBe('test.html');
expect(result.type).toBe('html');
expect(result.minified).toBe(true);
expect(result.gzipped).toBe(true);
expect(result.brotlified).toBe(true);
expect(result.sizes.originalSize).toBeGreaterThan(0);
expect(result.sizes.gzipSize).toBe(25);
expect(result.sizes.brotliSize).toBe(10); // Length of 'compressed'
});
});
describe('optimizeDirectory', () => {
it('should optimize all files in a directory', async () => {
// Mock the glob function
vi.mock('glob', () => ({
default: vi.fn().mockResolvedValue(['test.js', 'test.css', 'test.html'])
}));
// Create a spy on the optimizer methods
const optimizer = new AssetOptimizer();
const jsOptimizeSpy = vi.spyOn(optimizer, 'optimizeJavaScript').mockResolvedValue({
filePath: 'test.js',
type: 'js',
sizes: {
originalSize: 100,
minifiedSize: 50,
gzipSize: 30,
brotliSize: 20,
compressionRatio: 0.5,
originalSizeHuman: '100 B',
minifiedSizeHuman: '50 B',
gzipSizeHuman: '30 B',
brotliSizeHuman: '20 B'
},
minified: true,
gzipped: true,
brotlified: true
});
const cssOptimizeSpy = vi.spyOn(optimizer, 'optimizeCSS').mockResolvedValue({
filePath: 'test.css',
type: 'css',
sizes: {
originalSize: 80,
minifiedSize: 40,
gzipSize: 25,
brotliSize: 15,
compressionRatio: 0.5,
originalSizeHuman: '80 B',
minifiedSizeHuman: '40 B',
gzipSizeHuman: '25 B',
brotliSizeHuman: '15 B'
},
minified: true,
gzipped: true,
brotlified: true
});
const htmlOptimizeSpy = vi.spyOn(optimizer, 'optimizeHTML').mockResolvedValue({
filePath: 'test.html',
type: 'html',
sizes: {
originalSize: 120,
minifiedSize: 60,
gzipSize: 35,
brotliSize: 25,
compressionRatio: 0.5,
originalSizeHuman: '120 B',
minifiedSizeHuman: '60 B',
gzipSizeHuman: '35 B',
brotliSizeHuman: '25 B'
},
minified: true,
gzipped: true,
brotlified: true
});
const results = await optimizer.optimizeDirectory('dist');
expect(results).toBeDefined();
expect(results.assets.length).toBe(3);
expect(results.totalOriginalSize).toBe(300);
expect(results.totalMinifiedSize).toBe(150);
expect(results.totalGzipSize).toBe(90);
expect(results.totalBrotliSize).toBe(60);
expect(results.overallCompressionRatio).toBe(0.5);
expect(jsOptimizeSpy).toHaveBeenCalledWith('test.js');
expect(cssOptimizeSpy).toHaveBeenCalledWith('test.css');
expect(htmlOptimizeSpy).toHaveBeenCalledWith('test.html');
});
});
describe('generateSizeReport', () => {
it('should generate a size report', () => {
const optimizer = new AssetOptimizer();
const results = {
assets: [
{
filePath: 'test.js',
type: 'js',
sizes: {
originalSize: 100,
minifiedSize: 50,
gzipSize: 30,
brotliSize: 20,
compressionRatio: 0.5,
originalSizeHuman: '100 B',
minifiedSizeHuman: '50 B',
gzipSizeHuman: '30 B',
brotliSizeHuman: '20 B'
},
minified: true,
gzipped: true,
brotlified: true
},
{
filePath: 'test.css',
type: 'css',
sizes: {
originalSize: 80,
minifiedSize: 40,
gzipSize: 25,
brotliSize: 15,
compressionRatio: 0.5,
originalSizeHuman: '80 B',
minifiedSizeHuman: '40 B',
gzipSizeHuman: '25 B',
brotliSizeHuman: '15 B'
},
minified: true,
gzipped: true,
brotlified: true
}
],
totalOriginalSize: 180,
totalMinifiedSize: 90,
totalGzipSize: 55,
totalBrotliSize: 35,
overallCompressionRatio: 0.5,
totalOriginalSizeHuman: '180 B',
totalMinifiedSizeHuman: '90 B',
totalGzipSizeHuman: '55 B',
totalBrotliSizeHuman: '35 B'
};
const report = optimizer.generateSizeReport(results);
expect(report).toBeDefined();
expect(report).toContain('Asset Size Report');
expect(report).toContain('Total Original Size: 180 B');
expect(report).toContain('Total Minified Size: 90 B (50% reduction)');
expect(report).toContain('Total Gzip Size: 55 B');
expect(report).toContain('Total Brotli Size: 35 B');
expect(report).toContain('JavaScript Assets:');
expect(report).toContain('CSS Assets:');
});
});
});