feat: Phase 5 — filtres, actions Ntfy, outgoing webhooks, state file
CI / test (push) Successful in 2m34s
CI / test (push) Successful in 2m34s
- Filtres avancés: drop, set_priority, add_tag avec wildcard * (filter_outgoing.v) - Notifications structurées: click_url + actions (ntfy.v + sources/event.v) - Webhook sortant: Slack, Discord, JSON (filter_outgoing.v) - Fichier d'état: persistance poll_state + silence_until (filter_outgoing.v) - Config: sections filters, outgoing, state (config.v) - Tests: 9 nouveaux tests unitaires (filter_outgoing_test.v) - Docs: ROADMAP Phase 5 4/8, version 0.5.0
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
module main
|
||||
|
||||
import sources
|
||||
|
||||
fn test_glob_match() {
|
||||
assert glob_match('hello', 'hello')
|
||||
assert glob_match('hello', '*')
|
||||
assert glob_match('hello', 'hel*')
|
||||
assert glob_match('hello', 'h*o')
|
||||
assert !glob_match('hello', 'world')
|
||||
}
|
||||
|
||||
fn test_apply_filters_drop() {
|
||||
mut app := new_test_app()
|
||||
app.cfg.filters.rules = [
|
||||
FilterRule{match_source: 'test', action: 'drop'},
|
||||
]
|
||||
|
||||
mut event := sources.Event{
|
||||
source: 'test', name: 'source1', topic: 'alerts', priority: 3, message: 'hello',
|
||||
}
|
||||
assert !app.apply_filters(mut event)
|
||||
}
|
||||
|
||||
fn test_apply_filters_pass() {
|
||||
mut app := new_test_app()
|
||||
app.cfg.filters.rules = [
|
||||
FilterRule{match_source: 'other', action: 'drop'},
|
||||
]
|
||||
|
||||
mut event := sources.Event{
|
||||
source: 'test', name: 'source1', topic: 'alerts', priority: 3,
|
||||
}
|
||||
assert app.apply_filters(mut event)
|
||||
}
|
||||
|
||||
fn test_apply_filters_set_priority() {
|
||||
mut app := new_test_app()
|
||||
app.cfg.filters.rules = [
|
||||
FilterRule{match_source: 'test', action: 'set_priority', value: '5'},
|
||||
]
|
||||
|
||||
mut event := sources.Event{
|
||||
source: 'test', name: 'source1', topic: 'alerts', priority: 3,
|
||||
}
|
||||
assert app.apply_filters(mut event)
|
||||
assert event.priority == 5
|
||||
}
|
||||
|
||||
fn test_apply_filters_add_tag() {
|
||||
mut app := new_test_app()
|
||||
app.cfg.filters.rules = [
|
||||
FilterRule{match_source: 'test', action: 'add_tag', value: 'skull'},
|
||||
]
|
||||
|
||||
mut event := sources.Event{
|
||||
source: 'test', name: 'source1', topic: 'alerts', priority: 3,
|
||||
}
|
||||
assert app.apply_filters(mut event)
|
||||
assert event.tags.len == 1
|
||||
assert event.tags[0] == 'skull'
|
||||
}
|
||||
|
||||
fn test_format_outgoing_slack() {
|
||||
event := sources.Event{
|
||||
source: 'docker', name: 'watchtower', topic: 'alerts', priority: 5, message: 'Container died',
|
||||
}
|
||||
result := format_outgoing(event, 'slack')
|
||||
assert result.contains('Container died')
|
||||
assert result.contains('🔴')
|
||||
}
|
||||
|
||||
fn test_format_outgoing_discord() {
|
||||
event := sources.Event{
|
||||
source: 'http_poll', name: 'mysite', topic: 'status', priority: 3, message: 'down',
|
||||
}
|
||||
result := format_outgoing(event, 'discord')
|
||||
assert result.contains('down')
|
||||
}
|
||||
|
||||
fn test_json_encode_map() {
|
||||
mut m := map[string]string{}
|
||||
m['a'] = '1'
|
||||
m['b'] = '2'
|
||||
result := json_encode_map(m)
|
||||
assert result.contains('"a":"1"')
|
||||
assert result.contains('"b":"2"')
|
||||
}
|
||||
|
||||
fn test_json_decode_map() {
|
||||
result := json_decode_map('{"a":"1","b":"hello"}')!
|
||||
assert result.len == 2
|
||||
assert result['a'] == '1'
|
||||
assert result['b'] == 'hello'
|
||||
|
||||
empty := json_decode_map('{}')!
|
||||
assert empty.len == 0
|
||||
}
|
||||
|
||||
fn new_test_app() App {
|
||||
mut app := App{
|
||||
logger: new_logger(.info, false)
|
||||
cfg: Config{
|
||||
filters: FilterConfig{}
|
||||
outgoing: OutgoingConfig{}
|
||||
state: StateConfig{}
|
||||
}
|
||||
poll_state: map[string]bool{}
|
||||
}
|
||||
return app
|
||||
}
|
||||
Reference in New Issue
Block a user