aboutsummaryrefslogtreecommitdiffstats
path: root/internal/notify/store_test.go
blob: 4e4dd790dc7ac2048d2fc75fa0babefd3f32932d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

package notify

import "testing"

type event struct {
	id     uint32
	reason uint32
}

func newTestStore() (*Store, *[]event) {
	emitted := &[]event{}
	s := NewStore(
		func(id, reason uint32) { *emitted = append(*emitted, event{id, reason}) },
		func(live, history []Popup) {},
	)
	return s, emitted
}

func popup(app string) *Popup {
	return &Popup{App: app, Urgency: Normal, Created: 1}
}

func TestAddAssignsIdsFromOne(t *testing.T) {
	s, _ := newTestStore()
	a, replaced := s.Add(popup("a"), "", 0)
	b, _ := s.Add(popup("b"), "", 0)
	if replaced {
		t.Fatal("first add reported replaced")
	}
	if a != 1 || b != 2 {
		t.Errorf("ids = %d, %d, want 1, 2", a, b)
	}
}

func TestReplaceByIDReusesTheIDAndEmitsNothing(t *testing.T) {
	s, emitted := newTestStore()
	id, _ := s.Add(popup("a"), "", 0)
	*emitted = nil
	again, replaced := s.Add(popup("a2"), "", id)
	if !replaced {
		t.Fatal("replace by id not reported")
	}
	if again != id {
		t.Errorf("replace id = %d, want %d", again, id)
	}
	if len(*emitted) != 0 {
		t.Errorf("replace emitted %v, want none", *emitted)
	}
}

func TestReplaceByStackTag(t *testing.T) {
	s, _ := newTestStore()
	first, _ := s.Add(popup("mail"), "mail-account", 0)
	second, replaced := s.Add(popup("mail"), "mail-account", 0)
	if !replaced || second != first {
		t.Errorf("stack replace = id %d replaced %v, want id %d replaced true", second, replaced, first)
	}
}

func TestExpireClosesOnceAndKeepsTheEntry(t *testing.T) {
	s, emitted := newTestStore()
	id, _ := s.Add(popup("a"), "", 0)
	s.Expire(id)
	s.Expire(id)
	if len(*emitted) != 1 || (*emitted)[0].reason != 1 {
		t.Fatalf("emitted = %v, want one reason 1", *emitted)
	}
	if s.Actionable(id) {
		t.Error("expired entry still actionable")
	}
}

func TestDismissFilesHistoryAndEmitsDismissed(t *testing.T) {
	s, emitted := newTestStore()
	id, _ := s.Add(popup("a"), "", 0)
	s.Dismiss(id, 2)
	if len(*emitted) != 1 || (*emitted)[0].reason != 2 {
		t.Fatalf("emitted = %v, want one reason 2", *emitted)
	}
	if s.Actionable(id) {
		t.Error("dismissed entry still live")
	}
}

func TestDismissAfterExpireEmitsNothingMore(t *testing.T) {
	s, emitted := newTestStore()
	id, _ := s.Add(popup("a"), "", 0)
	s.Expire(id)
	*emitted = nil
	s.Dismiss(id, 2)
	if len(*emitted) != 0 {
		t.Errorf("dismiss after expire emitted %v, want none", *emitted)
	}
}

func TestQueueCapEvictsToHistory(t *testing.T) {
	s, emitted := newTestStore()
	for i := 0; i < 21; i++ {
		s.Add(popup("a"), "", 0)
	}
	if len(*emitted) == 0 {
		t.Fatal("eviction emitted nothing")
	}
}

func TestHistoryRingCapsAtTwenty(t *testing.T) {
	s, _ := newTestStore()
	for i := 0; i < 30; i++ {
		id, _ := s.Add(popup("a"), "", 0)
		s.Dismiss(id, 2)
	}
	if got := len(s.historySnapshot()); got != 20 {
		t.Errorf("history length = %d, want 20", got)
	}
}