1package tui
2
3import (
4 "testing"
5 "time"
6
7 tea "charm.land/bubbletea/v2"
8 "github.com/floatpane/matcha/fetcher"
9)
10
11func TestEmailViewUpdate(t *testing.T) {
12 emailWithAttachments := fetcher.Email{
13 From: "test@example.com",
14 Subject: "Test Email with Attachments",
15 Body: "This is the body.",
16 Date: time.Now(),
17 Attachments: []fetcher.Attachment{
18 {Filename: "attachment1.txt", Data: []byte("attachment1")},
19 {Filename: "attachment2.txt", Data: []byte("attachment2")},
20 },
21 }
22
23 emailWithoutAttachments := fetcher.Email{
24 From: "test@example.com",
25 Subject: "Test Email without Attachments",
26 Body: "This is the body.",
27 Date: time.Now(),
28 }
29
30 t.Run("Focus on attachments", func(t *testing.T) {
31 emailView := NewEmailView(emailWithAttachments, 0, 80, 24, MailboxInbox, false)
32 if emailView.focusOnAttachments {
33 t.Error("focusOnAttachments should be initially false")
34 }
35
36 // Tab to focus on attachments
37 model, _ := emailView.Update(tea.KeyPressMsg{Code: tea.KeyTab})
38 emailView = model.(*EmailView)
39
40 if !emailView.focusOnAttachments {
41 t.Error("focusOnAttachments should be true after tabbing")
42 }
43
44 // Tab back to body
45 model, _ = emailView.Update(tea.KeyPressMsg{Code: tea.KeyTab})
46 emailView = model.(*EmailView)
47 if emailView.focusOnAttachments {
48 t.Error("focusOnAttachments should be false after tabbing again")
49 }
50 })
51
52 t.Run("No focus on attachments when there are none", func(t *testing.T) {
53 emailView := NewEmailView(emailWithoutAttachments, 0, 80, 24, MailboxInbox, false)
54 if emailView.focusOnAttachments {
55 t.Error("focusOnAttachments should be initially false")
56 }
57 // Tab
58 model, _ := emailView.Update(tea.KeyPressMsg{Code: tea.KeyTab})
59 emailView = model.(*EmailView)
60 if emailView.focusOnAttachments {
61 t.Error("focusOnAttachments should remain false when there are no attachments")
62 }
63 })
64
65 t.Run("Navigate attachments", func(t *testing.T) {
66 emailView := NewEmailView(emailWithAttachments, 0, 80, 24, MailboxInbox, false)
67 // Focus on attachments
68 model, _ := emailView.Update(tea.KeyPressMsg{Code: tea.KeyTab})
69 emailView = model.(*EmailView)
70
71 if emailView.attachmentCursor != 0 {
72 t.Errorf("Initial attachmentCursor should be 0, got %d", emailView.attachmentCursor)
73 }
74
75 // Move down
76 model, _ = emailView.Update(tea.KeyPressMsg{Code: tea.KeyDown})
77 emailView = model.(*EmailView)
78 if emailView.attachmentCursor != 1 {
79 t.Errorf("After one down arrow, attachmentCursor should be 1, got %d", emailView.attachmentCursor)
80 }
81
82 // Move down again (should wrap to the first attachment)
83 model, _ = emailView.Update(tea.KeyPressMsg{Code: tea.KeyDown})
84 emailView = model.(*EmailView)
85 if emailView.attachmentCursor != 0 {
86 t.Errorf("attachmentCursor should wrap to the start of the list, got %d", emailView.attachmentCursor)
87 }
88
89 // Move up (should wrap to the last attachment)
90 model, _ = emailView.Update(tea.KeyPressMsg{Code: tea.KeyUp})
91 emailView = model.(*EmailView)
92 if emailView.attachmentCursor != 1 {
93 t.Errorf("After one up arrow from the first item, attachmentCursor should be 1, got %d", emailView.attachmentCursor)
94 }
95 })
96
97 t.Run("Attachment navigation does not scroll body", func(t *testing.T) {
98 emailView := NewEmailView(emailWithAttachments, 0, 80, 24, MailboxInbox, false)
99 emailView.viewport.SetHeight(2)
100 emailView.viewport.SetContent("line 1\nline 2\nline 3\nline 4\nline 5\n")
101 emailView.viewport.SetYOffset(1)
102
103 model, _ := emailView.Update(tea.KeyPressMsg{Code: tea.KeyTab})
104 emailView = model.(*EmailView)
105 if !emailView.focusOnAttachments {
106 t.Fatal("focusOnAttachments should be true after tabbing")
107 }
108
109 before := emailView.viewport.YOffset()
110 model, _ = emailView.Update(tea.KeyPressMsg{Code: tea.KeyDown})
111 emailView = model.(*EmailView)
112 if got := emailView.viewport.YOffset(); got != before {
113 t.Fatalf("attachment navigation should not scroll the email body, got offset %d want %d", got, before)
114 }
115 })
116
117 t.Run("Download attachment", func(t *testing.T) {
118 emailView := NewEmailView(emailWithAttachments, 0, 80, 24, MailboxInbox, false)
119 // Focus on attachments
120 model, _ := emailView.Update(tea.KeyPressMsg{Code: tea.KeyTab})
121 emailView = model.(*EmailView)
122
123 // Move to the second attachment
124 model, _ = emailView.Update(tea.KeyPressMsg{Code: tea.KeyDown})
125 emailView = model.(*EmailView)
126
127 // Press enter
128 _, cmd := emailView.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
129 if cmd == nil {
130 t.Fatal("Expected a command, but got nil")
131 }
132
133 msg := cmd()
134 downloadMsg, ok := msg.(DownloadAttachmentMsg)
135 if !ok {
136 t.Fatalf("Expected a DownloadAttachmentMsg, but got %T", msg)
137 }
138 if downloadMsg.Filename != "attachment2.txt" {
139 t.Errorf("Expected to download 'attachment2.txt', but got '%s'", downloadMsg.Filename)
140 }
141 if downloadMsg.Mailbox != MailboxInbox {
142 t.Errorf("Expected mailbox to be MailboxInbox, got %s", downloadMsg.Mailbox)
143 }
144 })
145
146 t.Run("Reply to email", func(t *testing.T) {
147 emailView := NewEmailView(emailWithAttachments, 0, 80, 24, MailboxInbox, false)
148
149 _, cmd := emailView.Update(tea.KeyPressMsg{Code: 'r', Text: "r"})
150 if cmd == nil {
151 t.Fatal("Expected a command, but got nil")
152 }
153
154 msg := cmd()
155 replyMsg, ok := msg.(ReplyToEmailMsg)
156 if !ok {
157 t.Fatalf("Expected a ReplyToEmailMsg, but got %T", msg)
158 }
159 if replyMsg.Email.Subject != emailWithAttachments.Subject {
160 t.Errorf("Expected reply to have subject '%s', but got '%s'", emailWithAttachments.Subject, replyMsg.Email.Subject)
161 }
162 })
163}