Add db seed and integration, update scripts in package.json
This commit is contained in:
1 parent
d505320c50
commit
45ca4de0ad
4 files changed
+112
-1
No files matched your search
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "tsx run-tests.ts",
|
"test": "node --import tsx --test \"src/**/*.test.ts\"",
|
||||||
"db:migrate": "dotenv dbmate up"
|
"db:migrate": "dotenv dbmate up"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import { describe, it, before, after } from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { Pool } from 'pg';
|
||||||
|
import { CategoryRepository } from './category.repository.ts';
|
||||||
|
import { seedCategoryTable, clearCategoryTable } from './test-seed.ts';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
import process from 'node:process';
|
||||||
|
|
||||||
|
// load the local .env file
|
||||||
|
try {
|
||||||
|
process.loadEnvFile(join(process.cwd(), '.env'));
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('⚠️ Warning: No local .env file found. Falling back to default system environment tokens.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const pool = new Pool({
|
||||||
|
connectionString: process.env.DATABASE_URL || process.env.INTERNAL_PROD_DB_URL
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('CategoryRepository - Live Database Integration Tests', () => {
|
||||||
|
const repository = new CategoryRepository(pool);
|
||||||
|
|
||||||
|
// Setup: Seed the database before executing integration items
|
||||||
|
before(async () => {
|
||||||
|
await seedCategoryTable(pool);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Teardown: Clean out the database after tests wrap up
|
||||||
|
after(async () => {
|
||||||
|
await clearCategoryTable(pool);
|
||||||
|
await pool.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fetch all deep descendants using the <@ ltree operator', async () => {
|
||||||
|
const results = await repository.findAllDescendants('Top.Science');
|
||||||
|
|
||||||
|
// Should return Science, Astronomy, and Astrophysics (3 nodes)
|
||||||
|
assert.equal(results.length, 3);
|
||||||
|
assert.equal(results[0].name, 'Science');
|
||||||
|
assert.equal(results[1].name, 'Astronomy');
|
||||||
|
assert.equal(results[2].name, 'Astrophysics');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should isolate only immediate structural child links via findDirectChildren()', async () => {
|
||||||
|
const results = await repository.findDirectChildren('Top');
|
||||||
|
|
||||||
|
// Top has two immediate children: Science and Hobbies
|
||||||
|
assert.equal(results.length, 2);
|
||||||
|
|
||||||
|
const names = results.map(r => r.name);
|
||||||
|
assert.ok(names.includes('Science'));
|
||||||
|
assert.ok(names.includes('Hobbies'));
|
||||||
|
assert.ok(!names.includes('Astronomy')); // Deeper descendant, should be skipped
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should resolve breadcrumb history using the @> ltree operator', async () => {
|
||||||
|
const results = await repository.findAncestors('Top.Science.Astronomy');
|
||||||
|
|
||||||
|
// Should trace: Root (Top) -> Science -> Astronomy
|
||||||
|
assert.equal(results.length, 3);
|
||||||
|
assert.equal(results[0].path, 'Top');
|
||||||
|
assert.equal(results[1].path, 'Top.Science');
|
||||||
|
assert.equal(results[2].path, 'Top.Science.Astronomy');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { Pool } from 'pg';
|
||||||
|
import { seedCategoryTable } from './test-seed.ts';
|
||||||
|
import 'dotenv/config'; // Requires npm install dotenv if you want to parse local .env assets
|
||||||
|
|
||||||
|
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
console.log('🌱 Seeding target database connection schema...');
|
||||||
|
try {
|
||||||
|
await seedCategoryTable(pool);
|
||||||
|
console.log('✅ Database hierarchy seed operations completed successfully.');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Database seed operations failed:', error);
|
||||||
|
} finally {
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { Pool } from 'pg';
|
||||||
|
|
||||||
|
export async function seedCategoryTable(pool: Pool): Promise<void> {
|
||||||
|
// 1. Wipe old records to ensure clean execution states
|
||||||
|
await pool.query('TRUNCATE TABLE categories RESTART IDENTITY CASCADE;');
|
||||||
|
|
||||||
|
// 2. Insert standard ltree seed records
|
||||||
|
const seedQueries = [
|
||||||
|
{ name: 'Root', path: 'Top' },
|
||||||
|
{ name: 'Science', path: 'Top.Science' },
|
||||||
|
{ name: 'Astronomy', path: 'Top.Science.Astronomy' },
|
||||||
|
{ name: 'Astrophysics', path: 'Top.Science.Astronomy.Astrophysics' },
|
||||||
|
{ name: 'Hobbies', path: 'Top.Hobbies' },
|
||||||
|
{ name: 'Gardening', path: 'Top.Hobbies.Gardening' },
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const record of seedQueries) {
|
||||||
|
await pool.query(
|
||||||
|
'INSERT INTO categories (name, path) VALUES ($1, $2::ltree);',
|
||||||
|
[record.name, record.path]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function clearCategoryTable(pool: Pool): Promise<void> {
|
||||||
|
await pool.query('TRUNCATE TABLE categories RESTART IDENTITY CASCADE;');
|
||||||
|
}
|
||||||
Reference in new issue
Block a user