feat: add SQLite-backed products store

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013gwc3aCiyQxmCWQke8RvEz
This commit is contained in:
Sjoerd de Vries
2026-09-05 15:03:16 +02:00
parent a5073e6e74
commit 492833dda4
2 changed files with 122 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const {
openDb, listProducts, getProduct, addProduct, deleteProduct,
recordCheckSuccess, recordCheckFailure,
} = require('../src/db');
function freshDb() {
return openDb(':memory:');
}
test('addProduct inserts a row with defaults and returns it', () => {
const db = freshDb();
const product = addProduct(db, { name: 'Voorbeeld', url: 'https://example.com' });
assert.equal(product.name, 'Voorbeeld');
assert.equal(product.url, 'https://example.com');
assert.equal(product.last_price, null);
assert.equal(product.last_checked_at, null);
assert.ok(product.created_at);
assert.ok(product.id);
});
test('listProducts returns all inserted products in insertion order', () => {
const db = freshDb();
addProduct(db, { name: 'A', url: 'https://a' });
addProduct(db, { name: 'B', url: 'https://b' });
const products = listProducts(db);
assert.equal(products.length, 2);
assert.equal(products[0].name, 'A');
assert.equal(products[1].name, 'B');
});
test('getProduct returns undefined for an unknown id', () => {
const db = freshDb();
assert.equal(getProduct(db, 999), undefined);
});
test('deleteProduct removes the row', () => {
const db = freshDb();
const product = addProduct(db, { name: 'A', url: 'https://a' });
deleteProduct(db, product.id);
assert.equal(getProduct(db, product.id), undefined);
});
test('recordCheckSuccess updates price, timestamp and status', () => {
const db = freshDb();
const product = addProduct(db, { name: 'A', url: 'https://a' });
recordCheckSuccess(db, product.id, { price: 12.5, checkedAt: '2026-09-05T08:00:00.000Z' });
const updated = getProduct(db, product.id);
assert.equal(updated.last_price, 12.5);
assert.equal(updated.last_checked_at, '2026-09-05T08:00:00.000Z');
assert.equal(updated.last_check_status, 'ok');
});
test('recordCheckFailure only updates the status, leaving price and timestamp untouched', () => {
const db = freshDb();
const product = addProduct(db, { name: 'A', url: 'https://a' });
recordCheckSuccess(db, product.id, { price: 12.5, checkedAt: '2026-09-05T08:00:00.000Z' });
recordCheckFailure(db, product.id, 'fetch_error');
const updated = getProduct(db, product.id);
assert.equal(updated.last_price, 12.5);
assert.equal(updated.last_checked_at, '2026-09-05T08:00:00.000Z');
assert.equal(updated.last_check_status, 'fetch_error');
});