91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
import { drizzle } from 'drizzle-orm/postgres-js'
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
import * as schema from '../schema'
|
|
import {
|
|
buildAccessibleFavoriteTargetQuery,
|
|
DrizzlePlaybookFavoriteStore,
|
|
type PlaybookFavoriteTransaction,
|
|
type PlaybookFavoriteTransactionRunner,
|
|
} from './playbook-favorite-store'
|
|
|
|
const workspaceId = '00000000-0000-4000-8000-000000000001'
|
|
const userId = '00000000-0000-4000-8000-000000000002'
|
|
const playbookId = '00000000-0000-4000-8000-000000000003'
|
|
|
|
class MemoryRunner implements PlaybookFavoriteTransactionRunner {
|
|
accessible = true
|
|
favorite = false
|
|
additions = 0
|
|
removals = 0
|
|
|
|
async run<T>(
|
|
work: (transaction: PlaybookFavoriteTransaction) => Promise<T>,
|
|
): Promise<T> {
|
|
return work({
|
|
targetIsAccessible: async () => this.accessible,
|
|
add: async () => {
|
|
if (!this.favorite) this.additions += 1
|
|
this.favorite = true
|
|
},
|
|
remove: async () => {
|
|
if (this.favorite) this.removals += 1
|
|
this.favorite = false
|
|
},
|
|
})
|
|
}
|
|
}
|
|
|
|
describe('favorite target query', () => {
|
|
it('accepts only the requested built-in or same-workspace playbook', () => {
|
|
const database = drizzle.mock({ schema })
|
|
const query = buildAccessibleFavoriteTargetQuery(database, {
|
|
workspaceId,
|
|
playbookId,
|
|
}).toSQL()
|
|
|
|
expect(query.sql).toContain('from "playbooks"')
|
|
expect(query.sql).toContain('"playbooks"."source_type" = $')
|
|
expect(query.sql).toContain('"playbooks"."workspace_id" = $')
|
|
expect(query.params).toEqual(
|
|
expect.arrayContaining([playbookId, 'built_in', workspaceId]),
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('DrizzlePlaybookFavoriteStore', () => {
|
|
it('adds and removes idempotently', async () => {
|
|
const runner = new MemoryRunner()
|
|
const store = new DrizzlePlaybookFavoriteStore(runner)
|
|
const input = { workspaceId, userId, playbookId }
|
|
|
|
await expect(
|
|
store.mutateFavorite({ ...input, mutation: 'add' }),
|
|
).resolves.toBe(true)
|
|
await store.mutateFavorite({ ...input, mutation: 'add' })
|
|
await expect(
|
|
store.mutateFavorite({ ...input, mutation: 'remove' }),
|
|
).resolves.toBe(true)
|
|
await store.mutateFavorite({ ...input, mutation: 'remove' })
|
|
|
|
expect(runner.additions).toBe(1)
|
|
expect(runner.removals).toBe(1)
|
|
})
|
|
|
|
it('does not mutate a missing or inaccessible target', async () => {
|
|
const runner = new MemoryRunner()
|
|
runner.accessible = false
|
|
const store = new DrizzlePlaybookFavoriteStore(runner)
|
|
|
|
await expect(
|
|
store.mutateFavorite({
|
|
workspaceId,
|
|
userId,
|
|
playbookId,
|
|
mutation: 'add',
|
|
}),
|
|
).resolves.toBe(false)
|
|
expect(runner.favorite).toBe(false)
|
|
})
|
|
})
|