This commit is contained in:
seb
2026-10-22 14:39:45 +02:00
parent 9495ad51cc
commit e9b4ac5d79
31 changed files with 3405 additions and 3392 deletions

View File

@@ -174,8 +174,8 @@ async function run() {
() => store.article.getBySku(googleAuthId, artOnlySub.sku),
/Article not found/
);
// tombstone for artOnlySub exists
const t1 = provider.db.prepare("SELECT * FROM posterminaltombstone WHERE posterminal_id = ? AND entity_type = 'article' AND entity_id = ?").all(posTerminal.id, artOnlySub.id);
// obituary for artOnlySub exists
const t1 = provider.db.prepare("SELECT * FROM posterminalobituary WHERE posterminal_id = ? AND entity_type = 'article' AND entity_id = ?").all(posTerminal.id, artOnlySub.id);
assert.equal(t1.length, 1);
// artParent and its child artChild: both deleted
@@ -187,8 +187,8 @@ async function run() {
() => store.article.getBySku(googleAuthId, artChild.article.sku),
/Article not found/
);
const tParent = provider.db.prepare("SELECT * FROM posterminaltombstone WHERE posterminal_id = ? AND entity_type = 'article' AND entity_id = ?").all(posTerminal.id, artParent.id);
const tChild = provider.db.prepare("SELECT * FROM posterminaltombstone WHERE posterminal_id = ? AND entity_type = 'article' AND entity_id = ?").all(posTerminal.id, artChild.article.id);
const tParent = provider.db.prepare("SELECT * FROM posterminalobituary WHERE posterminal_id = ? AND entity_type = 'article' AND entity_id = ?").all(posTerminal.id, artParent.id);
const tChild = provider.db.prepare("SELECT * FROM posterminalobituary WHERE posterminal_id = ? AND entity_type = 'article' AND entity_id = ?").all(posTerminal.id, artChild.article.id);
assert.equal(tParent.length, 1);
assert.equal(tChild.length, 1);

View File

@@ -6,9 +6,9 @@ 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 ---');
console.log('--- Testing posterminalobituary table and deletion flow ---');
const tempDir = mkdtempSync(join(tmpdir(), 'test-tombstone-'));
const tempDir = mkdtempSync(join(tmpdir(), 'test-obituary-'));
const dbFile = join(tempDir, 'test.db');
const storageDir = join(tempDir, 'storage');
@@ -21,11 +21,11 @@ async function run() {
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")');
// 1. Verify posterminalobituary table exists and has expected columns
console.log('1. Checking posterminalobituary schema...');
const tableInfo = provider.db.pragma('table_info("posterminalobituary")');
const colNames = tableInfo.map((c) => c.name);
console.log('posterminaltombstone columns:', colNames);
console.log('posterminalobituary columns:', colNames);
assert.deepEqual(colNames, [
'id',
'posterminal_id',
@@ -36,9 +36,9 @@ async function run() {
// Setup company first
console.log('2. Setting up base data...');
const googleAuthId = await store.google_auth.add('tombstone-tester@example.com');
const googleAuthId = await store.google_auth.add('obituary-tester@example.com');
const company = await store.company.create({
name: 'Tombstone Corp',
name: 'Obituary Corp',
iso639: 'de',
taxrate: 19,
reducedtaxrate: 7,
@@ -58,7 +58,7 @@ async function run() {
});
// 3. Test article deletion flow
console.log('3. Testing article deletion tombstone...');
console.log('3. Testing article deletion obituary...');
const article = await store.article.createUnderParent({
googleAuthId,
parentId: company.rootCategoryId,
@@ -67,7 +67,7 @@ async function run() {
await store.article.delete(googleAuthId, article.sku);
// 4. Test category deletion flow
console.log('4. Testing category deletion tombstone...');
console.log('4. Testing category deletion obituary...');
const cat = await store.category.createUnderParent({
googleAuthId,
parentId: company.rootCategoryId,
@@ -76,7 +76,7 @@ async function run() {
await store.category.delete({ googleAuthId, id: cat.id });
// 5. Test customer deletion flow
console.log('5. Testing customer deletion tombstone...');
console.log('5. Testing customer deletion obituary...');
const customer = await store.entity.create(googleAuthId, {
name: 'Mustermann',
firstName: 'Max',
@@ -85,31 +85,31 @@ async function run() {
await store.entity.delete(googleAuthId, customer.id);
// 6. Test customer group deletion flow
console.log('6. Testing customer group deletion tombstone...');
console.log('6. Testing customer group deletion obituary...');
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')
// 7. Verify all obituaries exist in posterminalobituary
console.log('7. Verifying obituaries in database...');
const allObituaries = provider.db
.prepare('SELECT * FROM posterminalobituary WHERE posterminal_id = ? ORDER BY id ASC')
.all(terminal.id);
console.log('Created tombstones:', allTombstones);
assert.equal(allTombstones.length, 4);
console.log('Created obituaries:', allObituaries);
assert.equal(allObituaries.length, 4);
assert.equal(allTombstones[0].entity_type, 'article');
assert.equal(allTombstones[0].entity_id, article.id);
assert.equal(allObituaries[0].entity_type, 'article');
assert.equal(allObituaries[0].entity_id, article.id);
assert.equal(allTombstones[1].entity_type, 'category');
assert.equal(allTombstones[1].entity_id, cat.id);
assert.equal(allObituaries[1].entity_type, 'category');
assert.equal(allObituaries[1].entity_id, cat.id);
assert.equal(allTombstones[2].entity_type, 'customer');
assert.equal(allTombstones[2].entity_id, customer.id);
assert.equal(allObituaries[2].entity_type, 'customer');
assert.equal(allObituaries[2].entity_id, customer.id);
assert.equal(allTombstones[3].entity_type, 'customergroup');
assert.equal(allTombstones[3].entity_id, cg.id);
assert.equal(allObituaries[3].entity_type, 'customergroup');
assert.equal(allObituaries[3].entity_id, cg.id);
// 8. Test getDeletedEntityCount & getDeletedEntityList APIs
console.log('8. Testing posterminal.getDeletedEntityCount & getDeletedEntityList...');
@@ -132,7 +132,7 @@ async function run() {
assert.equal(list[3].entityType, 'customergroup');
// Test cursor pagination
const cursor = allTombstones[1].id;
const cursor = allObituaries[1].id;
const countAfterCursor = await store.posterminal.getDeletedEntityCount({
posterminalId: terminal.id,
cursor,
@@ -145,16 +145,16 @@ async function run() {
limit: 10,
});
assert.equal(listAfterCursor.length, 2);
assert.equal(listAfterCursor[0].id, allTombstones[2].id);
assert.equal(listAfterCursor[1].id, allTombstones[3].id);
assert.equal(listAfterCursor[0].id, allObituaries[2].id);
assert.equal(listAfterCursor[1].id, allObituaries[3].id);
// 9. Test maxknowntombstoneid
console.log('9. Testing maxknowntombstoneid...');
await store.posterminal.setMaxKnownTombstoneId(terminal.id, allTombstones[3].id);
// 9. Test maxknownobituaryid
console.log('9. Testing maxknownobituaryid...');
await store.posterminal.setMaxKnownObituaryId(terminal.id, allObituaries[3].id);
const updatedTerminal = await store.posterminal.findByToken('pos-token-123');
assert.equal(updatedTerminal.maxknowntombstoneid, allTombstones[3].id);
assert.equal(updatedTerminal.maxknownobituaryid, allObituaries[3].id);
// 10. Test setOff category & orphaned article tombstone generation
// 10. Test setOff category & orphaned article obituary generation
console.log('10. Testing setOff with orphaned and non-orphaned articles...');
// Create Cat A and Cat B
const catA = await store.category.createUnderParent({
@@ -187,60 +187,60 @@ async function run() {
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);
// Clear previous obituaries to test cleanly
provider.db.prepare('DELETE FROM posterminalobituary 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)
// - Cat A should get an obituary
// - Art A should get an obituary (orphaned on this terminal)
// - Art AB should NOT get an obituary (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')
const obituariesAfterSetOff = provider.db
.prepare('SELECT entity_type, entity_id FROM posterminalobituary 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, [
console.log('Obituaries after setOff(Cat A):', obituariesAfterSetOff);
assert.equal(obituariesAfterSetOff.length, 2);
assert.deepEqual(obituariesAfterSetOff, [
{ 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...');
// 11. Test setOn category clears pending obituaries for that category and its articles
console.log('11. Testing setOn clears pending category and article obituaries...');
await store.posterminal.setOn(googleAuthId, terminal.id, catA.id);
const tombstonesAfterSetOn = provider.db
.prepare('SELECT entity_type, entity_id FROM posterminaltombstone WHERE posterminal_id = ?')
const obituariesAfterSetOn = provider.db
.prepare('SELECT entity_type, entity_id FROM posterminalobituary WHERE posterminal_id = ?')
.all(terminal.id);
console.log('Tombstones after setOn(Cat A):', tombstonesAfterSetOn);
assert.equal(tombstonesAfterSetOn.length, 0);
console.log('Obituaries after setOn(Cat A):', obituariesAfterSetOn);
assert.equal(obituariesAfterSetOn.length, 0);
// 12. Test setOffAll generates tombstones for all active categories and all their articles
console.log('12. Testing setOffAll tombstones...');
// 12. Test setOffAll generates obituaries for all active categories and all their articles
console.log('12. Testing setOffAll obituaries...');
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')
const obituariesAfterSetOffAll = provider.db
.prepare('SELECT entity_type, entity_id FROM posterminalobituary WHERE posterminal_id = ? ORDER BY id ASC')
.all(terminal.id);
console.log('Tombstones after setOffAll:', tombstonesAfterSetOffAll);
console.log('Obituaries after setOffAll:', obituariesAfterSetOffAll);
// 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));
const catObituaries = obituariesAfterSetOffAll.filter((t) => t.entity_type === 'category').map((t) => t.entity_id);
const artObituaries = obituariesAfterSetOffAll.filter((t) => t.entity_type === 'article').map((t) => t.entity_id);
assert(catObituaries.includes(catA.id));
assert(catObituaries.includes(catB.id));
assert(artObituaries.includes(artA.id));
assert(artObituaries.includes(artAB.id));
// 13. Test setOnAll clears category and article tombstones
console.log('13. Testing setOnAll clears all category & article tombstones...');
// 13. Test setOnAll clears category and article obituaries
console.log('13. Testing setOnAll clears all category & article obituaries...');
await store.posterminal.setOnAll(googleAuthId, terminal.id);
const tombstonesAfterSetOnAll = provider.db
.prepare('SELECT entity_type, entity_id FROM posterminaltombstone WHERE posterminal_id = ?')
const obituariesAfterSetOnAll = provider.db
.prepare('SELECT entity_type, entity_id FROM posterminalobituary WHERE posterminal_id = ?')
.all(terminal.id);
console.log('Tombstones after setOnAll:', tombstonesAfterSetOnAll);
assert.equal(tombstonesAfterSetOnAll.length, 0);
console.log('Obituaries after setOnAll:', obituariesAfterSetOnAll);
assert.equal(obituariesAfterSetOnAll.length, 0);
console.log('✅ ALL POSTERMINALTOMBSTONE TESTS PASSED');
console.log('✅ ALL POSTERMINALOBITUARY TESTS PASSED');
} finally {
try {
rmSync(tempDir, { recursive: true, force: true });