255 lines
9.7 KiB
JavaScript
255 lines
9.7 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { mkdtempSync, rmSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import LibDashStore from '../src/index.js';
|
|
import { BetterSqlite3Provider } from '../src/providers/sqlite3/index.js';
|
|
|
|
async function run() {
|
|
console.log('--- Testing posterminaltombstone table and deletion flow ---');
|
|
|
|
const tempDir = mkdtempSync(join(tmpdir(), 'test-tombstone-'));
|
|
const dbFile = join(tempDir, 'test.db');
|
|
const storageDir = join(tempDir, 'storage');
|
|
|
|
const provider = new BetterSqlite3Provider({
|
|
filename: dbFile,
|
|
storageDir,
|
|
});
|
|
|
|
await provider.initialize();
|
|
const store = await new LibDashStore(provider);
|
|
|
|
try {
|
|
// 1. Verify posterminaltombstone table exists and has expected columns
|
|
console.log('1. Checking posterminaltombstone schema...');
|
|
const tableInfo = provider.db.pragma('table_info("posterminaltombstone")');
|
|
const colNames = tableInfo.map((c) => c.name);
|
|
console.log('posterminaltombstone columns:', colNames);
|
|
assert.deepEqual(colNames, [
|
|
'id',
|
|
'posterminal_id',
|
|
'entity_type',
|
|
'entity_id',
|
|
'created_at',
|
|
]);
|
|
|
|
// Setup company first
|
|
console.log('2. Setting up base data...');
|
|
const googleAuthId = await store.google_auth.add('tombstone-tester@example.com');
|
|
const company = await store.company.create({
|
|
name: 'Tombstone Corp',
|
|
iso639: 'de',
|
|
taxrate: 19,
|
|
reducedtaxrate: 7,
|
|
googleAuthId,
|
|
});
|
|
await store.google_auth.setSelectedCompany(googleAuthId, company.id);
|
|
|
|
// Setup active paired POS terminal
|
|
const terminal = await store.posterminal.upsert(googleAuthId, {
|
|
name: 'POS Terminal 1',
|
|
pairingpin: '1234',
|
|
});
|
|
await store.posterminal.pair(terminal.id, {
|
|
token: 'pos-token-123',
|
|
clientserial: 'SN-001',
|
|
pairedAt: new Date().toISOString(),
|
|
});
|
|
|
|
// 3. Test article deletion flow
|
|
console.log('3. Testing article deletion tombstone...');
|
|
const article = await store.article.createUnderParent({
|
|
googleAuthId,
|
|
parentId: company.rootCategoryId,
|
|
name: 'Coffee Mug',
|
|
});
|
|
await store.article.delete(googleAuthId, article.sku);
|
|
|
|
// 4. Test category deletion flow
|
|
console.log('4. Testing category deletion tombstone...');
|
|
const cat = await store.category.createUnderParent({
|
|
googleAuthId,
|
|
parentId: company.rootCategoryId,
|
|
name: 'Snacks',
|
|
});
|
|
await store.category.delete({ googleAuthId, id: cat.id });
|
|
|
|
// 5. Test customer deletion flow
|
|
console.log('5. Testing customer deletion tombstone...');
|
|
const customer = await store.entity.create(googleAuthId, {
|
|
name: 'Mustermann',
|
|
firstName: 'Max',
|
|
customergroupId: company.posCustomerGroupId,
|
|
});
|
|
await store.entity.delete(googleAuthId, customer.id);
|
|
|
|
// 6. Test customer group deletion flow
|
|
console.log('6. Testing customer group deletion tombstone...');
|
|
const cg = await store.customergroup.create(googleAuthId, {
|
|
name: 'VIP Guests',
|
|
});
|
|
await store.customergroup.delete(googleAuthId, cg.id);
|
|
|
|
// 7. Verify all tombstones exist in posterminaltombstone
|
|
console.log('7. Verifying tombstones in database...');
|
|
const allTombstones = provider.db
|
|
.prepare('SELECT * FROM posterminaltombstone WHERE posterminal_id = ? ORDER BY id ASC')
|
|
.all(terminal.id);
|
|
console.log('Created tombstones:', allTombstones);
|
|
assert.equal(allTombstones.length, 4);
|
|
|
|
assert.equal(allTombstones[0].entity_type, 'article');
|
|
assert.equal(allTombstones[0].entity_id, article.id);
|
|
|
|
assert.equal(allTombstones[1].entity_type, 'category');
|
|
assert.equal(allTombstones[1].entity_id, cat.id);
|
|
|
|
assert.equal(allTombstones[2].entity_type, 'customer');
|
|
assert.equal(allTombstones[2].entity_id, customer.id);
|
|
|
|
assert.equal(allTombstones[3].entity_type, 'customergroup');
|
|
assert.equal(allTombstones[3].entity_id, cg.id);
|
|
|
|
// 8. Test getDeletedEntityCount & getDeletedEntityList APIs
|
|
console.log('8. Testing posterminal.getDeletedEntityCount & getDeletedEntityList...');
|
|
const initialCount = await store.posterminal.getDeletedEntityCount({
|
|
posterminalId: terminal.id,
|
|
cursor: 0,
|
|
});
|
|
assert.equal(initialCount, 4);
|
|
|
|
const list = await store.posterminal.getDeletedEntityList({
|
|
posterminalId: terminal.id,
|
|
cursor: 0,
|
|
limit: 10,
|
|
});
|
|
assert.equal(list.length, 4);
|
|
assert.equal(list[0].entityType, 'article');
|
|
assert.equal(list[0].entityId, article.id);
|
|
assert.equal(list[1].entityType, 'category');
|
|
assert.equal(list[2].entityType, 'customer');
|
|
assert.equal(list[3].entityType, 'customergroup');
|
|
|
|
// Test cursor pagination
|
|
const cursor = allTombstones[1].id;
|
|
const countAfterCursor = await store.posterminal.getDeletedEntityCount({
|
|
posterminalId: terminal.id,
|
|
cursor,
|
|
});
|
|
assert.equal(countAfterCursor, 2);
|
|
|
|
const listAfterCursor = await store.posterminal.getDeletedEntityList({
|
|
posterminalId: terminal.id,
|
|
cursor,
|
|
limit: 10,
|
|
});
|
|
assert.equal(listAfterCursor.length, 2);
|
|
assert.equal(listAfterCursor[0].id, allTombstones[2].id);
|
|
assert.equal(listAfterCursor[1].id, allTombstones[3].id);
|
|
|
|
// 9. Test maxknowntombstoneid
|
|
console.log('9. Testing maxknowntombstoneid...');
|
|
await store.posterminal.setMaxKnownTombstoneId(terminal.id, allTombstones[3].id);
|
|
const updatedTerminal = await store.posterminal.findByToken('pos-token-123');
|
|
assert.equal(updatedTerminal.maxknowntombstoneid, allTombstones[3].id);
|
|
|
|
// 10. Test setOff category & orphaned article tombstone generation
|
|
console.log('10. Testing setOff with orphaned and non-orphaned articles...');
|
|
// Create Cat A and Cat B
|
|
const catA = await store.category.createUnderParent({
|
|
googleAuthId,
|
|
parentId: company.rootCategoryId,
|
|
name: 'Category A',
|
|
});
|
|
const catB = await store.category.createUnderParent({
|
|
googleAuthId,
|
|
parentId: company.rootCategoryId,
|
|
name: 'Category B',
|
|
});
|
|
|
|
// Art A only in Cat A
|
|
const artA = await store.article.createUnderParent({
|
|
googleAuthId,
|
|
parentId: catA.id,
|
|
name: 'Article A (only in Cat A)',
|
|
});
|
|
|
|
// Art AB in both Cat A and Cat B
|
|
const artAB = await store.article.createUnderParent({
|
|
googleAuthId,
|
|
parentId: catA.id,
|
|
name: 'Article AB (in Cat A and B)',
|
|
});
|
|
await store.article.setCategoryIdsBySku(googleAuthId, artAB.sku, [catA.id, catB.id]);
|
|
|
|
// Turn both categories on for the terminal
|
|
await store.posterminal.setOn(googleAuthId, terminal.id, catA.id);
|
|
await store.posterminal.setOn(googleAuthId, terminal.id, catB.id);
|
|
|
|
// Clear previous tombstones to test cleanly
|
|
provider.db.prepare('DELETE FROM posterminaltombstone WHERE posterminal_id = ?').run(terminal.id);
|
|
|
|
// Turn off Cat A:
|
|
// - Cat A should get a tombstone
|
|
// - Art A should get a tombstone (orphaned on this terminal)
|
|
// - Art AB should NOT get a tombstone (still has active Cat B on this terminal)
|
|
await store.posterminal.setOff(googleAuthId, terminal.id, catA.id);
|
|
|
|
const tombstonesAfterSetOff = provider.db
|
|
.prepare('SELECT entity_type, entity_id FROM posterminaltombstone WHERE posterminal_id = ? ORDER BY id ASC')
|
|
.all(terminal.id);
|
|
|
|
console.log('Tombstones after setOff(Cat A):', tombstonesAfterSetOff);
|
|
assert.equal(tombstonesAfterSetOff.length, 2);
|
|
assert.deepEqual(tombstonesAfterSetOff, [
|
|
{ entity_type: 'category', entity_id: catA.id },
|
|
{ entity_type: 'article', entity_id: artA.id },
|
|
]);
|
|
|
|
// 11. Test setOn category clears pending tombstones for that category and its articles
|
|
console.log('11. Testing setOn clears pending category and article tombstones...');
|
|
await store.posterminal.setOn(googleAuthId, terminal.id, catA.id);
|
|
const tombstonesAfterSetOn = provider.db
|
|
.prepare('SELECT entity_type, entity_id FROM posterminaltombstone WHERE posterminal_id = ?')
|
|
.all(terminal.id);
|
|
console.log('Tombstones after setOn(Cat A):', tombstonesAfterSetOn);
|
|
assert.equal(tombstonesAfterSetOn.length, 0);
|
|
|
|
// 12. Test setOffAll generates tombstones for all active categories and all their articles
|
|
console.log('12. Testing setOffAll tombstones...');
|
|
await store.posterminal.setOffAll(googleAuthId, terminal.id);
|
|
const tombstonesAfterSetOffAll = provider.db
|
|
.prepare('SELECT entity_type, entity_id FROM posterminaltombstone WHERE posterminal_id = ? ORDER BY id ASC')
|
|
.all(terminal.id);
|
|
console.log('Tombstones after setOffAll:', tombstonesAfterSetOffAll);
|
|
// Cat A, Cat B, Art A, Art AB
|
|
const catTombstones = tombstonesAfterSetOffAll.filter((t) => t.entity_type === 'category').map((t) => t.entity_id);
|
|
const artTombstones = tombstonesAfterSetOffAll.filter((t) => t.entity_type === 'article').map((t) => t.entity_id);
|
|
assert(catTombstones.includes(catA.id));
|
|
assert(catTombstones.includes(catB.id));
|
|
assert(artTombstones.includes(artA.id));
|
|
assert(artTombstones.includes(artAB.id));
|
|
|
|
// 13. Test setOnAll clears category and article tombstones
|
|
console.log('13. Testing setOnAll clears all category & article tombstones...');
|
|
await store.posterminal.setOnAll(googleAuthId, terminal.id);
|
|
const tombstonesAfterSetOnAll = provider.db
|
|
.prepare('SELECT entity_type, entity_id FROM posterminaltombstone WHERE posterminal_id = ?')
|
|
.all(terminal.id);
|
|
console.log('Tombstones after setOnAll:', tombstonesAfterSetOnAll);
|
|
assert.equal(tombstonesAfterSetOnAll.length, 0);
|
|
|
|
console.log('✅ ALL POSTERMINALTOMBSTONE TESTS PASSED');
|
|
} finally {
|
|
try {
|
|
rmSync(tempDir, { recursive: true, force: true });
|
|
} catch {}
|
|
}
|
|
}
|
|
|
|
run().catch((err) => {
|
|
console.error('Test failed:', err);
|
|
process.exit(1);
|
|
});
|