import test from 'brittle'
import { TriggerEngine } from '../lib/triggers.js'
test('TriggerEngine - register and fire', async (t) => {
const engine = new TriggerEngine()
let called = false
engine.register('test1', {
type: 'message',
action: async (data) => {
called = true
return data.text
}
})
const results = await engine.fire('message', { text: 'hello' })
t.ok(called)
t.is(results.length, 1)
t.is(results[0].id, 'test1')
t.ok(results[0].ok)
t.is(results[0].result, 'hello')
engine.destroy()
})
test('TriggerEngine - no match for different event type', async (t) => {
const engine = new TriggerEngine()
engine.register('msg-handler', {
type: 'message',
action: async () => 'handled'
})
const results = await engine.fire('file-change', {})
t.is(results.length, 0)
engine.destroy()
})
test('TriggerEngine - filter by channel', async (t) => {
const engine = new TriggerEngine()
engine.register('chan-filter', {
type: 'message',
filter: { channel: '#important' },
action: async () => 'matched'
})
const r1 = await engine.fire('message', { channel: '#important', text: 'hi' })
t.is(r1.length, 1)
const r2 = await engine.fire('message', { channel: '#general', text: 'hi' })
t.is(r2.length, 0)
engine.destroy()
})
test('TriggerEngine - filter by contains', async (t) => {
const engine = new TriggerEngine()
engine.register('keyword', {
type: 'message',
filter: { contains: '#public' },
action: async () => 'matched'
})
const r1 = await engine.fire('message', { text: 'Hey everyone #public' })
t.is(r1.length, 1)
const r2 = await engine.fire('message', { text: 'private message' })
t.is(r2.length, 0)
engine.destroy()
})
test('TriggerEngine - filter by pattern', async (t) => {
const engine = new TriggerEngine()
engine.register('url-detect', {
type: 'message',
filter: { pattern: 'https?://\\S+' },
action: async () => 'url found'
})
const r1 = await engine.fire('message', { text: 'Check https://example.com' })
t.is(r1.length, 1)
const r2 = await engine.fire('message', { text: 'no urls here' })
t.is(r2.length, 0)
engine.destroy()
})
test('TriggerEngine - filter by author', async (t) => {
const engine = new TriggerEngine()
engine.register('alice-only', {
type: 'message',
filter: { author: 'alice' },
action: async () => 'from alice'
})
const r1 = await engine.fire('message', { author: 'alice', text: 'hi' })
t.is(r1.length, 1)
const r2 = await engine.fire('message', { author: 'bob', text: 'hi' })
t.is(r2.length, 0)
engine.destroy()
})
test('TriggerEngine - filter by tags', async (t) => {
const engine = new TriggerEngine()
engine.register('tagged', {
type: 'message',
filter: { tags: ['urgent', 'critical'] },
action: async () => 'tagged'
})
const r1 = await engine.fire('message', { text: 'This is URGENT please help' })
t.is(r1.length, 1)
const r2 = await engine.fire('message', { text: 'normal message' })
t.is(r2.length, 0)
engine.destroy()
})
test('TriggerEngine - enable/disable', async (t) => {
const engine = new TriggerEngine()
engine.register('toggle', {
type: 'message',
action: async () => 'fired'
})
engine.disable('toggle')
const r1 = await engine.fire('message', { text: 'hi' })
t.is(r1.length, 0)
engine.enable('toggle')
const r2 = await engine.fire('message', { text: 'hi' })
t.is(r2.length, 1)
engine.destroy()
})
test('TriggerEngine - unregister', async (t) => {
const engine = new TriggerEngine()
engine.register('temp', {
type: 'message',
action: async () => 'fired'
})
t.is(engine.count, 1)
engine.unregister('temp')
t.is(engine.count, 0)
const results = await engine.fire('message', {})
t.is(results.length, 0)
engine.destroy()
})
test('TriggerEngine - list triggers', (t) => {
const engine = new TriggerEngine()
engine.register('a', { type: 'message', action: async () => {} })
engine.register('b', { type: 'file-change', filter: { channel: 'x' }, action: async () => {} })
const list = engine.list()
t.is(list.length, 2)
t.ok(list.find(t => t.id === 'a' && t.type === 'message'))
t.ok(list.find(t => t.id === 'b' && t.hasFilter === true))
engine.destroy()
})
test('TriggerEngine - multiple triggers fire in order', async (t) => {
const engine = new TriggerEngine()
const order = []
engine.register('first', {
type: 'message',
action: async () => { order.push('first') }
})
engine.register('second', {
type: 'message',
action: async () => { order.push('second') }
})
await engine.fire('message', {})
t.alike(order, ['first', 'second'])
engine.destroy()
})
test('TriggerEngine - action error captured', async (t) => {
const engine = new TriggerEngine()
engine.register('broken', {
type: 'message',
action: async () => { throw new Error('boom') }
})
const results = await engine.fire('message', {})
t.is(results.length, 1)
t.absent(results[0].ok)
t.is(results[0].error, 'boom')
engine.destroy()
})
test('TriggerEngine - schedule trigger', async (t) => {
const engine = new TriggerEngine()
let count = 0
engine.startSchedule('ticker', 30, async () => {
count++
})
await new Promise(r => setTimeout(r, 80))
t.ok(count >= 2, `scheduled ran ${count} times`)
engine.destroy()
})