test/integration/test_draft.rb (4094B) - raw
1 require "sup"
2 require "test_helper"
3
4 class TestDraft < Minitest::Test
5 include Redwood
6
7 def setup
8 @path = Dir.mktmpdir
9 start
10 @draft_dir = File.join @path, "drafts"
11 @test_message_1 = <<EOS
12 From: Some Person <someone@example.invalid>
13 To:
14 Cc:
15 Bcc:
16 Subject: draft
17 Date: Fri, 11 Apr 2025 22:34:05 +1000
18 Message-ID: <123@example.invalid>
19
20 My incomplete message
21 EOS
22 DraftManager.instance.instance_eval "@dir = '#{@draft_dir}'"
23 Index.init @path
24 Index.load
25 SourceManager.instance.instance_eval "@sources = {}"
26 @draft_source = DraftManager.new_source
27 SourceManager.add_source @draft_source
28 end
29
30 def teardown
31 ObjectSpace.each_object(Class).select {|a| a < Redwood::Singleton}.each do |klass|
32 klass.deinstantiate! unless klass == Redwood::Logger
33 end
34 FileUtils.rm_r @path
35 end
36
37 def test_write_draft
38 DraftManager.write_draft { |f| f.write @test_message_1 }
39
40 draft_filename = File.join @draft_dir, "0"
41 assert File.exist? draft_filename
42 assert_equal @test_message_1, (File.read draft_filename)
43
44 ## Check that it is loaded back into the index successfully too.
45 messages_in_index = Index.instance.enum_for(:each_message).to_a
46 assert_equal @test_message_1, messages_in_index.first.raw_message
47 assert_equal [:draft, :inbox].to_set, messages_in_index.first.labels
48 end
49
50 def test_discard_draft
51 DraftManager.write_draft { |f| f.write @test_message_1 }
52 draft_filename = File.join @draft_dir, "0"
53 assert File.exist? draft_filename
54 message_in_index = Index.instance.enum_for(:each_message).to_a.first
55
56 DraftManager.discard message_in_index
57 refute File.exist? draft_filename
58 end
59
60 def test_discard_already_deleted_from_disk
61 DraftManager.write_draft { |f| f.write @test_message_1 }
62 draft_filename = File.join @draft_dir, "0"
63 assert File.exist? draft_filename
64 message_in_index = Index.instance.enum_for(:each_message).to_a.first
65
66 File.delete draft_filename
67
68 DraftManager.discard message_in_index
69 refute File.exist? draft_filename
70 end
71
72 def test_load_malformed_draft
73 ## Sup always writes drafts by serialising a Message, meaning the draft is
74 ## guaranteed to have certain headers like Date. But it's always possible
75 ## for the user to edit the draft directly on the filesystem and leave it
76 ## in some kind of malformed state. Sup should handle it without crashing.
77 draft_filename = File.join @draft_dir, "0"
78 fallback_date = Time.new 2025, 5, 3, 15, 47, 41
79 File.write draft_filename, <<EOS
80 Some-Header: Value
81
82 body
83 EOS
84 File.utime fallback_date, fallback_date, draft_filename
85 PollManager.poll_from @draft_source
86 messages_in_index = Index.instance.enum_for(:each_message).to_a
87 assert_equal "", messages_in_index[0].subj
88 assert_equal fallback_date, messages_in_index[0].date
89
90 File.write (File.join @draft_dir, "1"), <<EOS
91 missing a header!
92 EOS
93 PollManager.poll_from @draft_source
94 messages_in_index = Index.instance.enum_for(:each_message).to_a
95 assert_equal "", messages_in_index[0].subj
96
97 File.write (File.join @draft_dir, "2"), ""
98 PollManager.poll_from @draft_source
99 messages_in_index = Index.instance.enum_for(:each_message).to_a
100 assert_equal "", messages_in_index[0].subj
101 end
102
103 def test_draft_with_non_ascii_chars
104 message = <<EOS
105 From: Some Person <someone@example.invalid>
106 To:
107 Cc:
108 Bcc:
109 Subject: UTF-8 draft 🤐
110 Date: Fri, 11 Apr 2025 22:34:05 +1000
111 Message-ID: <123@example.invalid>
112
113 ¡Buen día! Доброго ранку! おはよう!
114 EOS
115 DraftManager.write_draft { |f| f.write message }
116 draft_filename = File.join @draft_dir, "0"
117 assert_equal message, (File.read draft_filename)
118
119 PollManager.poll_from @draft_source
120 messages_in_index = Index.instance.enum_for(:each_message).to_a
121 assert_equal "UTF-8 draft 🤐", messages_in_index[0].subj
122 assert_equal message, messages_in_index.first.raw_message
123 assert_equal "¡Buen día! Доброго ранку! おはよう!", \
124 messages_in_index[0].chunks[0].lines[0]
125 end
126 end