Added new feature for document export, including API contracts, data model, implementation plan, and tests. Updated related configurations and instructions.
This commit is contained in:
176
tests/unit/export-headers.test.js
Normal file
176
tests/unit/export-headers.test.js
Normal file
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* Unit Tests: Export Headers Generation
|
||||
*
|
||||
* Tests Content-Disposition header generation logic
|
||||
* Verifies filename sanitization and extension handling
|
||||
*/
|
||||
|
||||
import { describe, it } from 'node:test';
|
||||
import assert from 'node:assert';
|
||||
|
||||
// Load helper functions using vm.Script pattern
|
||||
import { readFileSync } from 'fs';
|
||||
import { Script } from 'vm';
|
||||
|
||||
// Create VM context with required globals
|
||||
const vmContext = {
|
||||
crypto: globalThis.crypto,
|
||||
console: console
|
||||
};
|
||||
|
||||
// Load googleDriveAdapterHelper.js
|
||||
const helperCode = readFileSync('./src/globalVariables/googleDriveAdapterHelper.js', 'utf8');
|
||||
const wrappedCode = `(function() {\n${helperCode}\n})()`;
|
||||
const script = new Script(wrappedCode);
|
||||
const helpers = script.runInNewContext(vmContext);
|
||||
|
||||
describe('Export Headers', () => {
|
||||
describe('sanitizeFilename', () => {
|
||||
it('should preserve valid alphanumeric filenames', () => {
|
||||
const result = helpers.sanitizeFilename('MyDocument123');
|
||||
assert.strictEqual(result, 'MyDocument123');
|
||||
});
|
||||
|
||||
it('should replace spaces with underscores', () => {
|
||||
const result = helpers.sanitizeFilename('My Important Document');
|
||||
assert.strictEqual(result, 'My_Important_Document');
|
||||
});
|
||||
|
||||
it('should preserve hyphens and dots', () => {
|
||||
const result = helpers.sanitizeFilename('my-document.v2.final');
|
||||
assert.strictEqual(result, 'my-document.v2.final');
|
||||
});
|
||||
|
||||
it('should replace special characters with underscores', () => {
|
||||
const result = helpers.sanitizeFilename('My<>Document:with*chars?');
|
||||
assert.strictEqual(result, 'My__Document_with_chars_');
|
||||
});
|
||||
|
||||
it('should remove leading dots', () => {
|
||||
const result = helpers.sanitizeFilename('.hidden-file');
|
||||
assert.strictEqual(result, 'hidden-file');
|
||||
});
|
||||
|
||||
it('should remove trailing dots', () => {
|
||||
const result = helpers.sanitizeFilename('document...');
|
||||
assert.strictEqual(result, 'document');
|
||||
});
|
||||
|
||||
it('should collapse multiple dots', () => {
|
||||
const result = helpers.sanitizeFilename('my....document');
|
||||
assert.strictEqual(result, 'my.document');
|
||||
});
|
||||
|
||||
it('should handle null input', () => {
|
||||
const result = helpers.sanitizeFilename(null);
|
||||
assert.strictEqual(result, 'document');
|
||||
});
|
||||
|
||||
it('should handle undefined input', () => {
|
||||
const result = helpers.sanitizeFilename(undefined);
|
||||
assert.strictEqual(result, 'document');
|
||||
});
|
||||
|
||||
it('should handle empty string', () => {
|
||||
const result = helpers.sanitizeFilename('');
|
||||
assert.strictEqual(result, 'document');
|
||||
});
|
||||
|
||||
it('should truncate very long filenames to 255 characters', () => {
|
||||
const longName = 'a'.repeat(300);
|
||||
const result = helpers.sanitizeFilename(longName);
|
||||
assert.strictEqual(result.length, 255);
|
||||
});
|
||||
|
||||
it('should handle unicode characters', () => {
|
||||
const result = helpers.sanitizeFilename('Документ 文档');
|
||||
// Non-ASCII chars should be replaced
|
||||
assert.ok(result.includes('_'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFileExtension', () => {
|
||||
it('should return "md" for text/x-markdown', () => {
|
||||
const result = helpers.getFileExtension('text/x-markdown');
|
||||
assert.strictEqual(result, 'md');
|
||||
});
|
||||
|
||||
it('should return "html" for text/html', () => {
|
||||
const result = helpers.getFileExtension('text/html');
|
||||
assert.strictEqual(result, 'html');
|
||||
});
|
||||
|
||||
it('should return "pdf" for application/pdf', () => {
|
||||
const result = helpers.getFileExtension('application/pdf');
|
||||
assert.strictEqual(result, 'pdf');
|
||||
});
|
||||
|
||||
it('should return "txt" for text/plain', () => {
|
||||
const result = helpers.getFileExtension('text/plain');
|
||||
assert.strictEqual(result, 'txt');
|
||||
});
|
||||
|
||||
it('should return "json" for application/json', () => {
|
||||
const result = helpers.getFileExtension('application/json');
|
||||
assert.strictEqual(result, 'json');
|
||||
});
|
||||
|
||||
it('should return "bin" for unknown mime types', () => {
|
||||
const result = helpers.getFileExtension('application/octet-stream');
|
||||
assert.strictEqual(result, 'bin');
|
||||
});
|
||||
|
||||
it('should return "bin" for null input', () => {
|
||||
const result = helpers.getFileExtension(null);
|
||||
assert.strictEqual(result, 'bin');
|
||||
});
|
||||
|
||||
it('should return "bin" for undefined input', () => {
|
||||
const result = helpers.getFileExtension(undefined);
|
||||
assert.strictEqual(result, 'bin');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Content-Disposition header integration', () => {
|
||||
it('should generate correct header for markdown file', () => {
|
||||
const filename = 'Meeting Notes Q1 2026';
|
||||
const sanitized = helpers.sanitizeFilename(filename);
|
||||
const extension = helpers.getFileExtension('text/x-markdown');
|
||||
|
||||
const header = `inline; filename="${sanitized}.${extension}"`;
|
||||
|
||||
assert.strictEqual(header, 'inline; filename="Meeting_Notes_Q1_2026.md"');
|
||||
});
|
||||
|
||||
it('should generate correct header for html file', () => {
|
||||
const filename = 'Project<Plan>';
|
||||
const sanitized = helpers.sanitizeFilename(filename);
|
||||
const extension = helpers.getFileExtension('text/html');
|
||||
|
||||
const header = `inline; filename="${sanitized}.${extension}"`;
|
||||
|
||||
assert.strictEqual(header, 'inline; filename="Project_Plan_.html"');
|
||||
});
|
||||
|
||||
it('should generate correct header for pdf file', () => {
|
||||
const filename = 'Annual Report 2026';
|
||||
const sanitized = helpers.sanitizeFilename(filename);
|
||||
const extension = helpers.getFileExtension('application/pdf');
|
||||
|
||||
const header = `inline; filename="${sanitized}.${extension}"`;
|
||||
|
||||
assert.strictEqual(header, 'inline; filename="Annual_Report_2026.pdf"');
|
||||
});
|
||||
|
||||
it('should handle filename with existing extension', () => {
|
||||
const filename = 'document.old.txt';
|
||||
const sanitized = helpers.sanitizeFilename(filename);
|
||||
const extension = helpers.getFileExtension('text/x-markdown');
|
||||
|
||||
const header = `inline; filename="${sanitized}.${extension}"`;
|
||||
|
||||
// Should preserve the dots in filename and add new extension
|
||||
assert.strictEqual(header, 'inline; filename="document.old.txt.md"');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user