sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/

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