mirror of
https://github.com/nestriness/nestri.git
synced 2026-09-19 09:15:19 +03:00
The formatter had never been run over these files, so `oxfmt` on a couple of touched files rewrote two dozen others and buried the real change. Running it everywhere once makes the next diff mean something. No behaviour changes: import ordering, line joining, and reindented JSON in the generated migration snapshots. Both test suites and both typechecks give the same answers as before, including the two type errors this does not fix.
86 lines
2.8 KiB
TypeScript
86 lines
2.8 KiB
TypeScript
import { afterAll, describe, expect, test } from 'bun:test';
|
|
|
|
import { Actor } from '../actor.js';
|
|
import { Fixtures } from '../db/fixtures.js';
|
|
import { testDb } from '../db/test.js';
|
|
import { Identifier } from '../id.js';
|
|
import { Team } from './index.js';
|
|
import { Member } from './member.js';
|
|
|
|
const sql = testDb();
|
|
|
|
const createdUserIds: string[] = [];
|
|
|
|
async function newOwner(label: string) {
|
|
const o = await Fixtures.owner(label);
|
|
createdUserIds.push(o.userId);
|
|
return o;
|
|
}
|
|
|
|
afterAll(async () => {
|
|
if (createdUserIds.length > 0) {
|
|
await sql`delete from "user" where id in ${sql(createdUserIds)}`;
|
|
createdUserIds.length = 0;
|
|
}
|
|
});
|
|
|
|
describe('Team.ensurePersonal', () => {
|
|
test('a new user gets exactly one team, and owns it', async () => {
|
|
const owner = await newOwner('team-first');
|
|
|
|
const team = await Team.personalFor(owner.userId);
|
|
expect(team?.id).toBe(owner.teamId);
|
|
expect(team?.ownerId).toBe(owner.userId);
|
|
|
|
const memberships = await Member.listByUser(owner.userId);
|
|
expect(memberships).toHaveLength(1);
|
|
expect(memberships[0]!.role).toBe('owner');
|
|
});
|
|
|
|
test('it is idempotent, because it runs on every login', async () => {
|
|
const owner = await newOwner('team-idempotent');
|
|
|
|
// The auth worker calls this each time somebody signs in, not only when
|
|
// the user is created — that is what backfills accounts made before the
|
|
// call existed. A second call must not mint a second team.
|
|
const again = await Actor.with(
|
|
{
|
|
type: 'user',
|
|
properties: { userID: owner.userId, linkedAccountID: owner.linkedAccountId }
|
|
},
|
|
() => Team.ensurePersonal({ displayName: 'team-idempotent' })
|
|
);
|
|
|
|
expect(again).toBe(owner.teamId);
|
|
const rows = await sql`select count(*)::int as n from team where owner_id = ${owner.userId}`;
|
|
expect(rows[0]!.n).toBe(1);
|
|
});
|
|
|
|
test('a user who predates the personal team gets one on next login', async () => {
|
|
// The legacy row the migration and this call between them repair: a user
|
|
// created by Steam sign-in before `ensurePersonal` was ever wired up.
|
|
const userId = Identifier.ascending('user');
|
|
createdUserIds.push(userId);
|
|
await sql`insert into "user" (id, name, email) values (${userId}, ${'legacy'}, ${`legacy-${userId}@example.test`})`;
|
|
|
|
expect(await Team.personalFor(userId)).toBeNull();
|
|
|
|
const teamId = await Actor.with(
|
|
{ type: 'user', properties: { userID: userId, linkedAccountID: 'lac_unused' } },
|
|
() => Team.ensurePersonal({ displayName: 'legacy' })
|
|
);
|
|
|
|
expect(teamId).toBeTruthy();
|
|
expect((await Team.personalFor(userId))?.id).toBe(teamId);
|
|
});
|
|
|
|
test('two users with the same display name get distinct slugs', async () => {
|
|
const a = await newOwner('same-name');
|
|
const b = await newOwner('same-name');
|
|
|
|
const teamA = await Team.personalFor(a.userId);
|
|
const teamB = await Team.personalFor(b.userId);
|
|
expect(teamA!.slug).not.toBe(teamB!.slug);
|
|
});
|
|
});
|