sqlite
This commit is contained in:
220
scripts/test-sqlite-storage.js
Normal file
220
scripts/test-sqlite-storage.js
Normal file
@@ -0,0 +1,220 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { mkdtempSync, existsSync, readFileSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import sharp from 'sharp';
|
||||
import LibDashStore from '../src/index.js';
|
||||
import { BetterSqlite3Provider } from '../src/providers/sqlite3/index.js';
|
||||
|
||||
async function runTests() {
|
||||
console.log('--- Starting SQLite file and pic directory storage tests ---');
|
||||
|
||||
const tempDir = mkdtempSync(join(tmpdir(), 'test-sqlite-store-'));
|
||||
const dbFile = join(tempDir, 'test.db');
|
||||
const storageDir = join(tempDir, 'custom-storage');
|
||||
|
||||
const provider = new BetterSqlite3Provider({
|
||||
filename: dbFile,
|
||||
storageDir,
|
||||
});
|
||||
|
||||
await provider.initialize();
|
||||
const store = await new LibDashStore(provider);
|
||||
|
||||
try {
|
||||
// Verify storage subdirectories exist
|
||||
assert(existsSync(join(storageDir, 'content')), 'content dir should exist');
|
||||
assert(existsSync(join(storageDir, 'thumbavif')), 'thumbavif dir should exist');
|
||||
assert(existsSync(join(storageDir, 'fullbinary')), 'fullbinary dir should exist');
|
||||
assert(existsSync(join(storageDir, 'thumbbinary')), 'thumbbinary dir should exist');
|
||||
|
||||
// Verify sqlite tables do NOT contain blob columns
|
||||
const fileTableInfo = provider.db.pragma('table_info("file")');
|
||||
const fileColNames = fileTableInfo.map((c) => c.name);
|
||||
console.log('file table columns:', fileColNames);
|
||||
assert(!fileColNames.includes('content'), 'file table should NOT have content column');
|
||||
assert(!fileColNames.includes('thumbavif'), 'file table should NOT have thumbavif column');
|
||||
|
||||
const picTableInfo = provider.db.pragma('table_info("pic")');
|
||||
const picColNames = picTableInfo.map((c) => c.name);
|
||||
console.log('pic table columns:', picColNames);
|
||||
assert(!picColNames.includes('fullbinary'), 'pic table should NOT have fullbinary column');
|
||||
assert(!picColNames.includes('thumbbinary'), 'pic table should NOT have thumbbinary column');
|
||||
|
||||
// Setup base data: google_auth, company, unit, article, manifest
|
||||
const googleAuthId = await store.google_auth.add('test@example.com');
|
||||
const company = await store.company.create({
|
||||
name: 'Test Corp',
|
||||
iso639: 'de',
|
||||
taxrate: 19,
|
||||
reducedtaxrate: 7,
|
||||
googleAuthId,
|
||||
});
|
||||
await store.google_auth.setSelectedCompany(googleAuthId, company.id);
|
||||
|
||||
// 1. Test Manifest Attachment (file table)
|
||||
console.log('1. Testing manifestattachment with file table...');
|
||||
const delivery = await store.delivery.create(googleAuthId, {
|
||||
externalNumber: 'DEL-1',
|
||||
date: new Date().toISOString(),
|
||||
lines: [
|
||||
{
|
||||
name: 'Item A',
|
||||
amount: 5,
|
||||
net: 10,
|
||||
taxrate: 19,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const manifestId = delivery.id;
|
||||
const testContent = Buffer.from('Hello SQLite Storage Engine! PDF or text content test.');
|
||||
const testThumb = await sharp({
|
||||
create: {
|
||||
width: 64,
|
||||
height: 64,
|
||||
channels: 4,
|
||||
background: { r: 255, g: 0, b: 0, alpha: 1 },
|
||||
},
|
||||
})
|
||||
.avif()
|
||||
.toBuffer();
|
||||
|
||||
const attachment = await store.manifestattachment.add(googleAuthId, manifestId, {
|
||||
name: 'test-doc.txt',
|
||||
mimetype: 'text/plain',
|
||||
content: testContent,
|
||||
thumbavif: testThumb,
|
||||
thumbw: 64,
|
||||
thumbh: 64,
|
||||
});
|
||||
|
||||
console.log('Attachment created with hash:', attachment.hash);
|
||||
|
||||
// Verify files on disk have correct extensions according to mimetype
|
||||
const contentPath = join(storageDir, 'content', attachment.hash + '.txt');
|
||||
const thumbPath = join(storageDir, 'thumbavif', attachment.hash + '.avif');
|
||||
assert(existsSync(contentPath), 'Content file must exist on disk at ' + contentPath);
|
||||
assert(existsSync(thumbPath), 'Thumb file must exist on disk at ' + thumbPath);
|
||||
assert.deepEqual(readFileSync(contentPath), testContent, 'Content on disk must match');
|
||||
assert.deepEqual(readFileSync(thumbPath), testThumb, 'Thumb on disk must match');
|
||||
|
||||
// Verify getById
|
||||
const fetched = await store.manifestattachment.getById(googleAuthId, manifestId, attachment.id);
|
||||
assert.equal(fetched.name, 'test-doc.txt');
|
||||
assert(Buffer.isBuffer(fetched.content), 'Fetched content must be a Buffer');
|
||||
assert.deepEqual(fetched.content, testContent, 'Fetched content must match original');
|
||||
assert(Buffer.isBuffer(fetched.thumbavif), 'Fetched thumbavif must be a Buffer');
|
||||
assert.deepEqual(fetched.thumbavif, testThumb, 'Fetched thumbavif must match original');
|
||||
|
||||
// Verify listByManifestId
|
||||
const list = await store.manifestattachment.listByManifestId(googleAuthId, manifestId);
|
||||
assert.equal(list.length, 1);
|
||||
assert(Buffer.isBuffer(list[0].thumbavif), 'List thumbavif must be a Buffer');
|
||||
assert.deepEqual(list[0].thumbavif, testThumb);
|
||||
|
||||
// Verify remove
|
||||
await store.manifestattachment.remove(googleAuthId, manifestId, attachment.id);
|
||||
assert(!existsSync(contentPath), 'Content file should be deleted on remove');
|
||||
assert(!existsSync(thumbPath), 'Thumb file should be deleted on remove');
|
||||
|
||||
// Test delivery creation with inline attached files
|
||||
console.log('1b. Testing delivery.create with inline attached file...');
|
||||
const deliveryWithFile = await store.delivery.create(googleAuthId, {
|
||||
externalNumber: 'DEL-WITH-FILE',
|
||||
date: new Date().toISOString(),
|
||||
lines: [{ name: 'Item B', amount: 1, net: 5, taxrate: 19 }],
|
||||
files: [{
|
||||
name: 'inline.txt',
|
||||
mimetype: 'text/plain',
|
||||
content: Buffer.from('Inline delivery file content'),
|
||||
}],
|
||||
});
|
||||
assert(deliveryWithFile.files && deliveryWithFile.files.length === 1, 'Delivery should have 1 attached file');
|
||||
const inlineHash = deliveryWithFile.files[0].hash;
|
||||
const inlineContentPath = join(storageDir, 'content', inlineHash + '.txt');
|
||||
const inlineThumbPath = join(storageDir, 'thumbavif', inlineHash + '.avif');
|
||||
assert(existsSync(inlineContentPath), 'Inline file content must exist on disk with .txt extension');
|
||||
assert(existsSync(inlineThumbPath), 'Inline file thumb must exist on disk with .avif extension');
|
||||
|
||||
const fetchedDelivery = await store.delivery.getById(googleAuthId, deliveryWithFile.id);
|
||||
assert(fetchedDelivery.files && fetchedDelivery.files.length === 1);
|
||||
assert(fetchedDelivery.files[0].thumbavif, 'Fetched delivery file should include thumbavif');
|
||||
console.log('Manifest attachment tests passed!');
|
||||
|
||||
// 2. Test Article Image (pic table)
|
||||
console.log('2. Testing article.addImage with pic table...');
|
||||
const cat = await store.category.createUnderParent({
|
||||
googleAuthId,
|
||||
parentId: company.rootCategoryId,
|
||||
name: 'Sub Category',
|
||||
});
|
||||
const article = await store.article.createUnderParent({
|
||||
googleAuthId,
|
||||
parentId: cat.id,
|
||||
name: 'Test Article',
|
||||
});
|
||||
|
||||
const sampleImage = await sharp({
|
||||
create: {
|
||||
width: 300,
|
||||
height: 200,
|
||||
channels: 4,
|
||||
background: { r: 0, g: 128, b: 255, alpha: 1 },
|
||||
},
|
||||
})
|
||||
.png()
|
||||
.toBuffer();
|
||||
|
||||
const picResult = await store.article.addImage(googleAuthId, article.sku, sampleImage);
|
||||
const fullHash = picResult.fullHash;
|
||||
console.log('Article pic added with hash:', fullHash);
|
||||
|
||||
const fullPath = join(storageDir, 'fullbinary', fullHash + '.avif');
|
||||
const picThumbPath = join(storageDir, 'thumbbinary', fullHash + '.avif');
|
||||
assert(existsSync(fullPath), 'Full picture must exist on disk at ' + fullPath);
|
||||
assert(existsSync(picThumbPath), 'Thumb picture must exist on disk at ' + picThumbPath);
|
||||
|
||||
// Verify getImageByHash
|
||||
const fullPic = await store.pic.getImageByHash(googleAuthId, fullHash);
|
||||
assert(Buffer.isBuffer(fullPic.buffer), 'Image buffer must be returned');
|
||||
assert.deepEqual(fullPic.buffer, readFileSync(fullPath));
|
||||
|
||||
// Verify getThumbByHash
|
||||
const thumbPic = await store.pic.getThumbByHash(googleAuthId, fullHash);
|
||||
assert(Buffer.isBuffer(thumbPic.buffer), 'Thumbnail buffer must be returned');
|
||||
assert.deepEqual(thumbPic.buffer, readFileSync(picThumbPath));
|
||||
|
||||
// Verify deleteImage
|
||||
await store.article.deleteImage(googleAuthId, article.sku, fullHash);
|
||||
assert(!existsSync(fullPath), 'Full pic file should be deleted on deleteImage');
|
||||
assert(!existsSync(picThumbPath), 'Thumb pic file should be deleted on deleteImage');
|
||||
console.log('Article pic tests passed!');
|
||||
|
||||
// 3. Test purge
|
||||
console.log('3. Testing purge...');
|
||||
// Add one more file before purge
|
||||
await store.manifestattachment.add(googleAuthId, manifestId, {
|
||||
name: 'purge-test.txt',
|
||||
mimetype: 'text/plain',
|
||||
content: Buffer.from('To be purged'),
|
||||
});
|
||||
await provider.purge();
|
||||
assert(!existsSync(contentPath), 'Files should be purged');
|
||||
console.log('Purge tests passed!');
|
||||
|
||||
console.log('\nAll tests PASSED successfully!');
|
||||
} finally {
|
||||
provider.close();
|
||||
try {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runTests().catch((err) => {
|
||||
console.error('Test failed with error:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user