95 lines
3.7 KiB
JavaScript
95 lines
3.7 KiB
JavaScript
// Simple integration test for playlist public/private visibility
|
|
// Run with: npm run test:playlists
|
|
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import os from 'node:os';
|
|
|
|
// Create isolated temp DB file
|
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'newtube-test-'));
|
|
const dbPath = path.join(tmpDir, 'test.db');
|
|
process.env.NEWTUBE_DB_FILE = dbPath;
|
|
|
|
// Dynamically import DB after setting env
|
|
const dbMod = await import('../db.mjs');
|
|
const {
|
|
insertUser,
|
|
cryptoRandomUUID,
|
|
createPlaylist,
|
|
listPublicPlaylists,
|
|
listPlaylists,
|
|
getPlaylistWithItemsIfAllowed,
|
|
} = dbMod;
|
|
|
|
function expect(cond, msg) {
|
|
if (!cond) {
|
|
throw new Error(`Assertion failed: ${msg}`);
|
|
}
|
|
}
|
|
|
|
function logOk(msg) {
|
|
console.log(`✓ ${msg}`);
|
|
}
|
|
|
|
// Seed users
|
|
const ownerId = cryptoRandomUUID();
|
|
const otherId = cryptoRandomUUID();
|
|
insertUser({ id: ownerId, username: 'owner', email: 'owner@example.com', passwordHash: 'x' });
|
|
insertUser({ id: otherId, username: 'other', email: 'other@example.com', passwordHash: 'y' });
|
|
|
|
// Seed playlists
|
|
const pub1 = createPlaylist({ userId: ownerId, title: 'Pub A', description: 'public', thumbnail: null, isPrivate: false });
|
|
const pub2 = createPlaylist({ userId: ownerId, title: 'Pub B', description: 'public', thumbnail: null, isPrivate: 0 });
|
|
const priv1 = createPlaylist({ userId: ownerId, title: 'Priv A', description: 'private', thumbnail: null, isPrivate: true });
|
|
|
|
// 1) Anonymous lists public
|
|
{
|
|
const pubs = listPublicPlaylists({ limit: 50, offset: 0 });
|
|
expect(Array.isArray(pubs), 'listPublicPlaylists returns array');
|
|
const ids = new Set(pubs.map(p => p.id));
|
|
expect(ids.has(pub1.id) && ids.has(pub2.id), 'public playlists visible');
|
|
expect(!ids.has(priv1.id), 'private playlist not visible');
|
|
logOk('Anonymous sees public playlists only');
|
|
}
|
|
|
|
// 2) Other user lists own (none) + sees public via listPublicPlaylists
|
|
{
|
|
const ownOther = listPlaylists({ userId: otherId, limit: 50, offset: 0 });
|
|
expect(ownOther.length === 0, 'other user has no own playlists');
|
|
const pubs = listPublicPlaylists({ limit: 50, offset: 0 });
|
|
const ids = new Set(pubs.map(p => p.id));
|
|
expect(ids.has(pub1.id) && ids.has(pub2.id), 'other user sees public playlists');
|
|
logOk('Other user sees public playlists');
|
|
}
|
|
|
|
// 3) Owner lists own (public + private)
|
|
{
|
|
const ownOwner = listPlaylists({ userId: ownerId, limit: 50, offset: 0 });
|
|
const ids = new Set(ownOwner.map(p => p.id));
|
|
expect(ids.has(pub1.id) && ids.has(pub2.id) && ids.has(priv1.id), 'owner sees all own playlists, including private');
|
|
logOk('Owner sees own public + private playlists');
|
|
}
|
|
|
|
// 4) Public view endpoint logic: getPlaylistWithItemsIfAllowed
|
|
{
|
|
// Anonymous can view public
|
|
const viewPub = getPlaylistWithItemsIfAllowed({ viewerUserId: undefined, id: pub1.id, limit: 10, offset: 0 });
|
|
expect(viewPub && viewPub.id === pub1.id, 'anonymous can view public playlist details');
|
|
|
|
// Anonymous cannot view private
|
|
const viewPriv = getPlaylistWithItemsIfAllowed({ viewerUserId: undefined, id: priv1.id, limit: 10, offset: 0 });
|
|
expect(viewPriv === 'forbidden', 'anonymous cannot view private playlist');
|
|
|
|
// Other user can view public
|
|
const viewPubOther = getPlaylistWithItemsIfAllowed({ viewerUserId: otherId, id: pub2.id, limit: 10, offset: 0 });
|
|
expect(viewPubOther && viewPubOther.id === pub2.id, 'other user can view public playlist');
|
|
|
|
// Owner can view private
|
|
const viewPrivOwner = getPlaylistWithItemsIfAllowed({ viewerUserId: ownerId, id: priv1.id, limit: 10, offset: 0 });
|
|
expect(viewPrivOwner && viewPrivOwner.id === priv1.id, 'owner can view own private playlist');
|
|
|
|
logOk('Public view behavior correct for anonymous, other, and owner');
|
|
}
|
|
|
|
console.log('\nAll playlist visibility tests passed.');
|