rmsgen 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ require 'forwardable'
2
+
3
+ module ActsLike
4
+ module String
5
+ extend Forwardable
6
+
7
+ def initialize(str='')
8
+ @str = str
9
+ end
10
+
11
+ def_delegators :@str, :to_s, :gsub!, :[], :strip, :<<, :empty?
12
+ end
13
+ end
data/lib/rmsgen.rb CHANGED
@@ -2,6 +2,17 @@ require 'yaml'
2
2
  require 'erb'
3
3
 
4
4
  module Rmsgen
5
+ %w{ header
6
+ footer
7
+ plain_text
8
+ url
9
+ polnote_url_request
10
+ indented_line
11
+ duration
12
+ }.each do |fname|
13
+ require File.join(File.dirname(__FILE__), 'rmsgen', 'parts', fname)
14
+ end
15
+
5
16
  %w{ part_group
6
17
  polnote
7
18
  titleizer
@@ -9,13 +20,14 @@ module Rmsgen
9
20
  script
10
21
  inquirer
11
22
  runtime
23
+ part
12
24
  link
25
+ imap_client
13
26
  imap_polnote_group
14
27
  fs_polnote_group
28
+ polnote_group
29
+
15
30
  }.each do |fname|
16
31
  require File.join(File.dirname(__FILE__), 'rmsgen', fname)
17
32
  end
18
33
  end
19
-
20
-
21
-
@@ -1,13 +1,12 @@
1
1
  module Rmsgen
2
2
  class Compresser
3
- def initialize(polnote)
4
- @polnote = polnote
5
- @parts = polnote.parts
3
+ def initialize(part_group=[])
4
+ @part_group = part_group
6
5
  run!
7
6
  end
8
7
 
9
8
  def body
10
- @parts.join PartGroup::DELIMETER
9
+ @part_group.join PartGroup::DELIMETER
11
10
  end
12
11
 
13
12
  private
@@ -19,15 +18,15 @@ module Rmsgen
19
18
  end
20
19
 
21
20
  def rm_header
22
- @parts.delete_if { |x| x =~ /Return-Path:/ }
21
+ @part_group.delete_if { |x| x.is_a?(Rmsgen::Parts::Header) }
23
22
  end
24
23
 
25
24
  def rm_footer
26
- @parts.delete_if { |x| x =~ /Dr Richard Stallman/ }
25
+ @part_group.delete_if { |x| x.is_a?(Rmsgen::Parts::Footer) }
27
26
  end
28
27
 
29
28
  def single_line_paragraphs
30
- @parts.each { |part| part.gsub!("\n", '') }
29
+ @part_group.each { |part| part.gsub!("\n", ' ') }
31
30
  end
32
31
  end
33
32
  end
@@ -1,12 +1,22 @@
1
1
  module Rmsgen
2
2
  class FsPolnoteGroup
3
3
  def initialize(dir=nil)
4
- splat_dir = "#{dir}/*"
5
- @raw_notes = Dir[splat_dir].map { |f| File.read(f) }
6
- @notes = @raw_notes.map { |note| Rmsgen::Polnote.new(:body => note) }
4
+ @note_bodies = note_bodies_from_directory(dir)
5
+ @notes = build_many_polnotes(@note_bodies)
7
6
  end
7
+
8
8
  def all
9
9
  @notes
10
10
  end
11
+
12
+ private
13
+
14
+ def note_bodies_from_directory(dir)
15
+ Dir["#{dir}/*"].map { |f| File.read(f) }
16
+ end
17
+
18
+ def build_many_polnotes(note_bodies)
19
+ note_bodies.map { |body| Rmsgen::Polnote.new(:body => body) }
20
+ end
11
21
  end
12
22
  end
@@ -0,0 +1,60 @@
1
+ require 'rmsgen'
2
+ require 'net/imap'
3
+ require 'forwardable'
4
+
5
+ module Rmsgen
6
+ class IMAPClient
7
+ INBOX = 'INBOX'
8
+ RMS_EMAIL = 'rms@gnu.org'
9
+ RFC822 = 'RFC822'
10
+
11
+ extend Forwardable
12
+
13
+ def initialize(options)
14
+ @server = options['imap_server']
15
+ @login = options['imap_login']
16
+ @password = options['imap_password']
17
+ @imap_client = Net::IMAP.new(@server)
18
+ end
19
+
20
+ def_delegators :@imap_client, :select, :search, :fetch, :copy, :store, :expunge
21
+
22
+ def authenticate
23
+ @imap_client.authenticate('LOGIN', @login, @password)
24
+ end
25
+
26
+ def fetch_polnote_messages_from_inbox(&block)
27
+ authenticate
28
+ select INBOX
29
+ find_all_from_rms(&block)
30
+ end
31
+
32
+ def find_by_id(id)
33
+ select INBOX
34
+ fetch_message_body(id)
35
+ end
36
+
37
+ private
38
+
39
+ def find_all_from_rms
40
+ search_for_notes.map do |id|
41
+ if block_given?
42
+ yield(fetch_message_body(id), id)
43
+ else
44
+ fetch_message_body(id)
45
+ end
46
+ end
47
+ end
48
+
49
+ def search_for_notes(&block)
50
+ search(["FROM", RMS_EMAIL], &block)
51
+ end
52
+
53
+ def fetch_message_body(id)
54
+ fetch_result = fetch id, RFC822
55
+ if fetch_result && fetch_result.any?
56
+ fetch_result[0].attr[RFC822]
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,26 +1,14 @@
1
1
  module Rmsgen
2
2
  class IMAPPolnoteGroup
3
- require 'net/imap'
4
3
 
5
- attr_reader :note_ids
6
-
7
- def initialize(options={})
8
- @imap_options = options
9
- @login = options['imap_login']
10
- @password = options['imap_password']
11
- @note_ids = init_note_ids || []
12
- end
13
-
14
- def fetch_notes
15
- authenticate
16
- follow_inbox
17
- find_all_from_rms
4
+ def initialize(imap_client)
5
+ @imap_client = imap_client
18
6
  end
19
7
 
20
- def init_note_ids
21
- authenticate
22
- follow_inbox
23
- imap.search(["FROM", 'rms@gnu.org'])
8
+ def all
9
+ @imap_client.fetch_polnote_messages_from_inbox do |body, id|
10
+ Polnote.new :body => body, :id => id
11
+ end
24
12
  end
25
13
 
26
14
  def find(id)
@@ -29,42 +17,21 @@ module Rmsgen
29
17
  end
30
18
 
31
19
  def archive_polnote(id)
20
+ @imap_client.authenticate
32
21
  follow_inbox
33
- archived = false
34
- imap.search(["FROM", 'rms@gnu.org']).each do |note_id|
35
- if note_id.to_i == id.to_i
36
- imap.copy id.to_i, 'INBOX.old-messages'
37
- imap.store(id.to_i, "+FLAGS", [:Deleted])
38
- imap.expunge
39
- archived = true
40
- end
41
- end
42
- archived
22
+ move_to_archives(id)
43
23
  end
44
24
 
45
25
  private
46
-
47
- def imap
48
- @imap ||= Net::IMAP.new(@imap_options['imap_server'])
49
- end
50
-
51
- def authenticate
52
- imap.authenticate 'LOGIN', @login, @password
26
+
27
+ def move_to_archives(id)
28
+ @imap_client.copy id.to_i, 'INBOX.old-messages'
29
+ @imap_client.store(id.to_i, "+FLAGS", [:Deleted])
30
+ @imap_client.expunge
53
31
  end
54
32
 
55
33
  def follow_inbox
56
- imap.select 'INBOX'
57
- end
58
-
59
- def find_all_from_rms
60
- @note_ids.map { |id| fetch_message_body(id) }
61
- end
62
-
63
- def fetch_message_body(id)
64
- fetch_result = imap.fetch id, 'RFC822'
65
- if fetch_result && fetch_result.any?
66
- fetch_result[0].attr['RFC822']
67
- end
34
+ @imap_client.select 'INBOX'
68
35
  end
69
36
  end
70
37
  end
@@ -1,11 +1,5 @@
1
1
  module Rmsgen
2
2
  class Inquirer
3
- PARTS = { :url => /^http/,
4
- :note =>/\[Link/,
5
- :duration => /^For.*week.*$/,
6
- :indendation => /^ /
7
- }
8
-
9
3
  attr_reader :polnote
10
4
 
11
5
  def initialize polnote, stdout=$stdout, answers=nil
@@ -35,13 +29,13 @@ module Rmsgen
35
29
 
36
30
  def run!
37
31
  @parts.each do |part|
38
- if part =~ PARTS[:duration]
32
+ if part.is_a?(Rmsgen::Parts::Duration)
39
33
  inquire_about_expiration
40
- elsif part =~ PARTS[:url]
34
+ elsif part.is_a?(Rmsgen::Parts::Url)
41
35
  inquire_about_link part
42
- elsif part =~ PARTS[:note]
36
+ elsif part.is_a?(Rmsgen::Parts::PolnoteUrlRequest)
43
37
  inquire_about_polnote_link part
44
- elsif part =~ PARTS[:indendation]
38
+ elsif part.is_a?(Rmsgen::Parts::IndentedLine)
45
39
  append_to_previous_paragraph part
46
40
  else
47
41
  @parts_seen << part
@@ -0,0 +1,19 @@
1
+ module Rmsgen
2
+ module Part
3
+
4
+ TOKEN_PARTS = {
5
+ /^http/ => Rmsgen::Parts::Url,
6
+ /Return-Path:/ => Rmsgen::Parts::Header,
7
+ /\[Link/i => Rmsgen::Parts::PolnoteUrlRequest,
8
+ /Dr Richard Stallman/ => Rmsgen::Parts::Footer,
9
+ /^ / => Rmsgen::Parts::IndentedLine,
10
+ /^For.*week.*$/ => Rmsgen::Parts::Duration
11
+ }
12
+
13
+ def self.parse(raw)
14
+ token_part = TOKEN_PARTS.find { |pattern, part| raw =~ pattern }
15
+ return Rmsgen::Parts::PlainText.new(raw) unless token_part
16
+ token_part[1].new(raw)
17
+ end
18
+ end
19
+ end
@@ -1,23 +1,51 @@
1
- class PartGroup < Array
2
- attr_reader :text
1
+ require 'forwardable'
3
2
 
4
- DELIMETER = "\n\n"
3
+ class PartGroup
4
+ extend Forwardable
5
+ include Comparable
6
+
7
+ # Carriage return new line.
8
+ #
9
+ CRNL = /\r\n/
10
+ CRNL_CRNL = /\r\n\r\n/
11
+ DELIMETER = "\n\n"
12
+ NL = /\n/
13
+ NL_NL = /\n\n/
14
+ NL_PLACEHOLDER = '[newline]'
15
+ SPACE = ' '
16
+
17
+ attr_reader :text, :parts
18
+
19
+ def_delegators :@parts, :delete_if, :<<, :each, :join,
20
+ :inject, :each_with_index, :[], :map, :size
5
21
 
6
22
  def initialize(text)
7
23
  @text = text
24
+ @parts = []
8
25
  assign_parts!
9
26
  end
10
27
 
28
+ def <=>(other)
29
+ parts.map(&:to_s) <=> other.map(&:to_s)
30
+ end
31
+
32
+ private
33
+
11
34
  def assign_parts!
12
- if @text.match /\r\n\r\n/
13
- @text.gsub!(/\r\n\r\n/, "\n\n")
14
- @text.gsub!(/\r\n/, " ")
15
- @text.gsub!(/\n\n\n\n/, "")
16
- else
17
- @text.gsub!(/\n\n/, '[newline]')
18
- @text.gsub!(/\n/, ' ')
19
- @text.gsub!('[newline]', "\n\n")
20
- end
21
- @text.split(DELIMETER).delete_if(&:empty?).each { |p| self << p }
35
+ massage_linebreaks
36
+ parts = @text.split(DELIMETER)
37
+ assign_parsed_parts(parts)
38
+ @parts.delete_if(&:empty?)
39
+ end
40
+
41
+ def assign_parsed_parts(parts)
42
+ parts.each { |p| @parts << Rmsgen::Part.parse(p) }
43
+ end
44
+
45
+ def massage_linebreaks
46
+ @text.gsub!(CRNL_CRNL, DELIMETER)
47
+ @text.gsub!(CRNL, SPACE)
48
+ @text.gsub!(NL_NL, NL_PLACEHOLDER)
49
+ @text.gsub!(NL_PLACEHOLDER, DELIMETER)
22
50
  end
23
51
  end
@@ -0,0 +1,7 @@
1
+ module Rmsgen
2
+ module Parts
3
+ class Duration
4
+ include ActsLike::String
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Rmsgen
2
+ module Parts
3
+ class Footer
4
+ include ActsLike::String
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ require 'acts_like/string'
2
+
3
+ module Rmsgen
4
+ module Parts
5
+ class Header
6
+ include ActsLike::String
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Rmsgen
2
+ module Parts
3
+ class IndentedLine
4
+ include ActsLike::String
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module Rmsgen::Parts
2
+ class PlainText
3
+ include ActsLike::String
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ module Rmsgen
2
+ module Parts
3
+ class PolnoteUrlRequest
4
+ include ActsLike::String
5
+ end
6
+ end
7
+ end
8
+
@@ -0,0 +1,5 @@
1
+ module Rmsgen::Parts
2
+ class Url
3
+ include ActsLike::String
4
+ end
5
+ end
@@ -19,15 +19,23 @@ module Rmsgen
19
19
  end
20
20
 
21
21
  def titleize
22
- @title = Titleizer.new(self).body
22
+ @title = Titleizer.new(self).to_html
23
23
  end
24
24
 
25
25
  def inquire
26
26
  @body = Inquirer.new(self).body
27
27
  end
28
28
 
29
- def parts
30
- PartGroup.new(@body)
29
+ def include?(pattern)
30
+ @body.include?(pattern)
31
+ end
32
+
33
+ def gsub!(x, y)
34
+ @body.gsub!(x, y)
35
+ end
36
+
37
+ def split(x)
38
+ @body.split(x)
31
39
  end
32
40
 
33
41
  def to_html
@@ -38,10 +46,14 @@ module Rmsgen
38
46
  ERB.new(File.read(URGENT_TEMPLATE)).result(binding)
39
47
  end
40
48
 
49
+ def parts
50
+ PartGroup.new(@body)
51
+ end
52
+
41
53
  private
42
54
 
43
55
  def compress!
44
- @body = Compresser.new(self).body
56
+ @body = Compresser.new(parts).body
45
57
  end
46
58
 
47
59
  def sanitize_urgent_attribute(attribute)
@@ -0,0 +1,19 @@
1
+ module Rmsgen
2
+ module PolnoteGroup
3
+ def self.fetch(source)
4
+ polnote_group = group(source)
5
+ polnote_group.all
6
+ end
7
+
8
+
9
+ private
10
+
11
+ def self.group(source)
12
+ case source
13
+ when String then Rmsgen::FsPolnoteGroup.new(source)
14
+ else
15
+ Rmsgen::IMAPPolnoteGroup.new(source)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,10 +1,11 @@
1
1
  module Rmsgen
2
2
  class Runtime
3
+
3
4
  def initialize(config)
4
5
  @config = config
5
6
  raise "Ensure you have populated a config file" unless @config
6
- @output = @config['output_file']
7
- @notes = fetch_notes
7
+ @output = config['output_file']
8
+ @notes = PolnoteGroup.fetch(polnote_source)
8
9
  run!
9
10
  end
10
11
 
@@ -12,13 +13,26 @@ module Rmsgen
12
13
  puts 'no polnotes in queue' if @notes.empty?
13
14
  @notes.each do |note|
14
15
  system('clear')
15
- polnote = Rmsgen::Inquirer.inquire_about_note(note)
16
+ polnote = Rmsgen::Polnote.new(:body => note)
17
+ Rmsgen::Inquirer.inquire_about_note(polnote)
16
18
  write(polnote)
17
19
  end
18
20
  end
19
21
 
20
22
  private
21
23
 
24
+ def polnote_source
25
+ @config['email_dir'] || Rmsgen::IMAPClient.new(imap_options)
26
+ end
27
+
28
+ def imap_options
29
+ {
30
+ 'imap_server' => @config['imap_server'],
31
+ 'imap_login' => @config['imap_login'],
32
+ 'imap_password' => @config['imap_password']
33
+ }
34
+ end
35
+
22
36
  def write(note)
23
37
  if @output
24
38
  File.open(@output, 'a') do |file|
@@ -29,24 +43,5 @@ module Rmsgen
29
43
  puts
30
44
  end
31
45
  end
32
-
33
- def fetch_notes
34
- if @config['email_dir']
35
- notes = Dir["#{@config['email_dir']}/*"].map { |f| File.read(f) }
36
- else
37
- notes = fetch_notes_from_imap
38
- end
39
- notes.map { |note| Rmsgen::Polnote.new(:body => note) } if notes
40
- end
41
-
42
- def fetch_notes_from_imap
43
- options = {
44
- 'imap_server' => @config['imap_server'],
45
- 'imap_login' => @config['imap_login'],
46
- 'imap_password' => @config['imap_password']
47
- }
48
-
49
- Rmsgen::IMAPPolnoteGroup.new(options).fetch_notes
50
- end
51
46
  end
52
47
  end
@@ -11,16 +11,11 @@ module Rmsgen
11
11
  @title = options[:title]
12
12
  @body = polnote.body
13
13
  @script = Script.new($stdout)
14
-
15
14
  run!
16
15
  end
17
16
 
18
- def body
19
- ERB.new(File.read(TEMPLATE)).result(binding)
20
- end
21
-
22
17
  def to_html
23
- body
18
+ ERB.new(File.read(TEMPLATE)).result(binding)
24
19
  end
25
20
 
26
21
  private
@@ -29,12 +24,12 @@ module Rmsgen
29
24
  @title = capitalize(get_title_from_options_or_script)
30
25
  end
31
26
 
32
- def get_title_from_options_or_script
33
- @title || @script.prompt_for_title
27
+ def capitalize(str)
28
+ str.split(SPACE).map(&:capitalize).join(SPACE)
34
29
  end
35
30
 
36
- def capitalize(title=SPACE)
37
- title.split(SPACE).map(&:capitalize).join(SPACE)
31
+ def get_title_from_options_or_script
32
+ @title || @script.prompt_for_title
38
33
  end
39
34
 
40
35
  def today_format
@@ -1,3 +1,3 @@
1
1
  module Rmsgen
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -25,8 +25,7 @@ for raising the debt ceiling.
25
25
 
26
26
  http://
27
27
 
28
- Once in a while, when enough people demand it, Obama does what he
29
- ought to do.
28
+ Once in a while, when enough people demand it, Obama does what he ought to do.
30
29
 
31
30
  --
32
31
  Dr Richard Stallman
@@ -0,0 +1,70 @@
1
+ require 'rmsgen'
2
+
3
+ describe Rmsgen::IMAPClient do
4
+ let(:imap_options) do
5
+ {
6
+ 'imap_server' => 'mail.example.com',
7
+ 'imap_login' => 'login',
8
+ 'imap_password' => 'password'
9
+ }
10
+ end
11
+
12
+ it 'authenticates with the server' do
13
+ net_imap_instance = mock
14
+ Net::IMAP.should_receive(:new).with('mail.example.com').and_return(net_imap_instance)
15
+ net_imap_instance.should_receive(:authenticate).with('LOGIN', 'login', 'password').and_return(nil)
16
+ imap_client = Rmsgen::IMAPClient.new(imap_options)
17
+ imap_client.authenticate
18
+ end
19
+
20
+ context 'fetches messages from the inbox' do
21
+ before do
22
+ @net_imap_instance = mock(:search => [], :select => [])
23
+ @message_collection = mock(:message_collection)
24
+ Net::IMAP.should_receive(:new).with('mail.example.com').and_return(@net_imap_instance)
25
+ @client = Rmsgen::IMAPClient.new(imap_options)
26
+ @client.should_receive(:authenticate).once
27
+ end
28
+
29
+ after do
30
+ @client.fetch_polnote_messages_from_inbox
31
+ end
32
+
33
+ it 'delegates select to the imap client' do
34
+ @net_imap_instance.should_receive(:select).once.with('INBOX')
35
+ end
36
+
37
+ it 'delegates search to ' do
38
+ @net_imap_instance.should_receive(:search).once.with(["FROM", 'rms@gnu.org'])
39
+ end
40
+
41
+ it 'delegates fetch to imap client and uses RFC822' do
42
+ @net_imap_instance.should_receive(:search).and_return([1])
43
+ fetch_result = [mock(:notes, :attr => { "RFC822" => 'Hello World'} )]
44
+ @net_imap_instance.should_receive(:fetch).once.with(1, 'RFC822').and_return(fetch_result)
45
+ end
46
+ end
47
+
48
+ context 'finding a single message body' do
49
+ let(:net_imap_instance) { mock(:net_imap, :select => nil, :fetch => []) }
50
+ let(:client) do
51
+ Rmsgen::IMAPClient.new(imap_options)
52
+ end
53
+
54
+ before do
55
+ Net::IMAP.should_receive(:new).with('mail.example.com').and_return(net_imap_instance)
56
+ end
57
+
58
+ after do
59
+ client.find_by_id(1)
60
+ end
61
+
62
+ it 'delegates select to imap client' do
63
+ net_imap_instance.should_receive(:select).once.with('INBOX')
64
+ end
65
+
66
+ it 'calls fetch for the id' do
67
+ net_imap_instance.should_receive(:fetch).with(1, 'RFC822').once
68
+ end
69
+ end
70
+ end
@@ -1,45 +1,34 @@
1
1
  require 'rmsgen'
2
2
 
3
3
  describe Rmsgen::IMAPPolnoteGroup do
4
- context 'fetching notes' do
5
- let(:imap) { double('foo') }
6
- let(:options) do {
7
- 'imap_server' => 'foo.bar.com',
8
- 'imap_login' => 'login',
9
- 'imap_password' => 'password'}
10
- end
4
+ context 'fetching notes from an imap server' do
5
+ let(:imap) { double('imap client') }
11
6
 
12
- let(:do_fetch) do
13
- imap.should_receive(:search).any_number_of_times
7
+ let(:set_imap_expectations_and_get_all) do
8
+ imap.should_receive(:fetch_polnote_messages_from_inbox).any_number_of_times
14
9
  imap.should_receive(:authenticate).any_number_of_times
10
+ imap.should_receive(:search).any_number_of_times
15
11
  Net::IMAP.should_receive(:new).any_number_of_times.and_return(imap)
16
12
  imap.should_receive(:select).any_number_of_times
17
- Rmsgen::IMAPPolnoteGroup.new(options).fetch_notes
13
+ Rmsgen::IMAPPolnoteGroup.new(imap).all
18
14
  end
19
15
 
20
- it 'authenticates with imap server' do
21
- imap.should_receive(:authenticate).any_number_of_times.with('LOGIN', 'login', 'password')
22
- do_fetch
16
+ after(:each) do
17
+ set_imap_expectations_and_get_all
23
18
  end
24
19
 
25
20
  it 'selects the inbox folder' do
26
21
  imap.should_receive(:select).any_number_of_times.with('INBOX')
27
- do_fetch
28
- end
29
-
30
- it 'searches for messages from rms' do
31
- imap.should_receive(:search).once.with(["FROM", 'rms@gnu.org'])
32
- do_fetch
33
22
  end
34
23
 
35
24
  it 'fetches each message' do
36
- message_id = double('message_id')
37
- search_result = [message_id]
38
25
 
39
- imap.stub(:search) { search_result }
26
+ # message_id = double('message_id')
27
+ # search_result = [message_id]
28
+
29
+ # imap.stub(:search) { search_result }
40
30
 
41
- imap.should_receive(:fetch).with(message_id, 'RFC822')
42
- do_fetch
31
+ # imap.should_receive(:fetch).with(message_id, 'RFC822')
43
32
  end
44
33
  end
45
34
  end
@@ -3,19 +3,16 @@ require 'rmsgen'
3
3
  describe PartGroup do
4
4
  it "accepts text as input" do
5
5
  input = "hello\n\nworld"
6
- p = PartGroup.new(input)
7
- p.text.should be == input
6
+ PartGroup.new(input).text.should be == input
8
7
  end
9
8
 
10
9
  it "output list of parts ordered by appearance" do
11
10
  input = "\n\n\n\n1\n\n2\n\n3\n\n4"
12
- p = PartGroup.new(input)
13
- p.should == ['1', '2', '3', '4']
11
+ PartGroup.new(input).should == ['1', '2', '3', '4']
14
12
  end
15
13
 
16
14
  it "splits input into parts based on carriage return and newline" do
17
15
  input = "1\r\n\r\n2\r\n\r\n3\r\n\r\n4"
18
- p = PartGroup.new(input)
19
- p.should == ['1', '2', '3', '4']
16
+ PartGroup.new(input).should == ['1', '2', '3', '4']
20
17
  end
21
18
  end
data/spec/part_spec.rb ADDED
@@ -0,0 +1,51 @@
1
+ require 'rmsgen'
2
+
3
+ describe Rmsgen::Parts::PlainText do
4
+ context 'behaving like a string' do
5
+ it 'returns the input string' do
6
+ p = Rmsgen::Parts::PlainText.new('foo')
7
+ p.to_s.should == 'foo'
8
+ end
9
+ end
10
+ end
11
+
12
+ describe Rmsgen::Parts::PolnoteUrlRequest do
13
+ context 'behaving like a string' do
14
+ it 'returns the input string' do
15
+ p = Rmsgen::Parts::PolnoteUrlRequest.new('foo')
16
+ p.to_s.should == 'foo'
17
+ end
18
+ end
19
+ end
20
+
21
+ describe Rmsgen::Part do
22
+ context 'parse' do
23
+ it 'detects a url' do
24
+ subject.parse('http').should be_instance_of(Rmsgen::Parts::Url)
25
+ end
26
+
27
+ it 'detects the headers' do
28
+ subject.parse('Return-Path:').should be_instance_of(Rmsgen::Parts::Header)
29
+ end
30
+
31
+ it 'detects an indented line' do
32
+ subject.parse(' hello world').should be_instance_of(Rmsgen::Parts::IndentedLine)
33
+ end
34
+
35
+ it 'detects a duration' do
36
+ subject.parse('For one week').should be_instance_of(Rmsgen::Parts::Duration)
37
+ end
38
+
39
+ it 'detects plain text' do
40
+ subject.parse('bla blah blah').should be_instance_of(Rmsgen::Parts::PlainText)
41
+ end
42
+
43
+ it 'detects a polnote url request' do
44
+ subject.parse('[Link to a polnote]').should be_instance_of(Rmsgen::Parts::PolnoteUrlRequest)
45
+ end
46
+
47
+ it 'detects a downcased polnote url request' do
48
+ subject.parse('[link').should be_instance_of(Rmsgen::Parts::PolnoteUrlRequest)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,24 @@
1
+ require 'rmsgen'
2
+
3
+ describe Rmsgen::PolnoteGroup do
4
+ context '.fetch' do
5
+ context 'from a file system' do
6
+ it 'collects file contents' do
7
+ file_system_polnote_group = mock
8
+ file_system_polnote_group.should_receive(:all)
9
+ Rmsgen::PolnoteGroup.should_receive(:group).and_return(file_system_polnote_group)
10
+ Rmsgen::PolnoteGroup.fetch('/some/path')
11
+ end
12
+ end
13
+
14
+ context 'from an imap server' do
15
+ it 'collects email contents' do
16
+ imap_polnote_group = mock
17
+ imap_polnote_group.should_receive(:all)
18
+ Rmsgen::PolnoteGroup.should_receive(:group).and_return(imap_polnote_group)
19
+ imap_options = { 'imap_server' => 'foo.test.com', 'imap_login' => 'login', 'imap_password' => 'password' }
20
+ Rmsgen::PolnoteGroup.fetch(imap_options)
21
+ end
22
+ end
23
+ end
24
+ end
data/spec/polnote_spec.rb CHANGED
@@ -2,7 +2,6 @@ require 'rmsgen'
2
2
  require 'fake_gets'
3
3
 
4
4
  describe Rmsgen::Polnote do
5
-
6
5
  def fixture(name)
7
6
  File.read("spec/fixtures/#{name}")
8
7
  end
@@ -21,7 +20,7 @@ describe Rmsgen::Polnote do
21
20
 
22
21
  it "has parts" do
23
22
  note = Rmsgen::Polnote.new(:body => imap_note)
24
- note.parts.should == ['hello', 'world']
23
+ note.parts.size.should be == 2
25
24
  end
26
25
  end
27
26
 
@@ -29,12 +28,8 @@ describe Rmsgen::Polnote do
29
28
  let(:note) { fixture(:link_to_polnote) }
30
29
 
31
30
  it 'parses the body' do
32
- text_a = "rainbow"
33
- polnote_url = "http://somenote"
34
- text_b = "blue"
35
-
36
31
  $stdout = StringIO.new
37
- $stdin = FakeGetMany.new(text_a, polnote_url, text_b)
32
+ $stdin = FakeGetMany.new('rainbow', 'http://somenote', 'blue')
38
33
  polnote = Rmsgen::Polnote.new(:body => note)
39
34
  polnote.inquire
40
35
  polnote.to_html.should ==
data/spec/runtime_spec.rb CHANGED
@@ -12,23 +12,13 @@ describe Rmsgen::Runtime do
12
12
 
13
13
  context 'when and there is a note' do
14
14
  let(:runtime) { Rmsgen::Runtime }
15
- let(:imap) { mock(:imap) }
16
- let(:search_result) { mock(:search_result) }
15
+ let(:imap) { stub(:imap) }
17
16
 
18
17
  it 'fetches the note' do
19
18
  $stdout = StringIO.new
20
19
  $stdin = FakeGet.new('hello')
21
- Net::IMAP.should_receive(:new).with('mail.test.org') { imap }
22
- runtime.any_instance.stub(:system)
23
- imap_note = mock(:note)
24
- notes = [imap_note]
25
-
26
- imap_note.stub(:attr) { {"RFC822"=>"hello world"} }
27
- imap.stub(:authenticate)
28
- imap.stub(:select)
29
-
30
- imap.stub(:search) { [search_result] }
31
- imap.stub(:fetch) { notes }
20
+ Rmsgen::IMAPClient.should_receive(:new).and_return(imap)
21
+ imap.should_receive(:fetch_polnote_messages_from_inbox).and_return([])
32
22
  expect { runtime.new(config).run! }.to_not raise_error
33
23
  end
34
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rmsgen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-19 00:00:00.000000000Z
12
+ date: 2011-09-30 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description: A library to help generate html markup from RMS emails
15
15
  email:
@@ -46,15 +46,26 @@ files:
46
46
  - features/support/env.rb
47
47
  - features/support/hooks.rb
48
48
  - features/urgent_polnote.feature
49
+ - lib/acts_like/string.rb
49
50
  - lib/rmsgen.rb
50
51
  - lib/rmsgen/cli/main.rb
51
52
  - lib/rmsgen/compresser.rb
52
53
  - lib/rmsgen/fs_polnote_group.rb
54
+ - lib/rmsgen/imap_client.rb
53
55
  - lib/rmsgen/imap_polnote_group.rb
54
56
  - lib/rmsgen/inquirer.rb
55
57
  - lib/rmsgen/link.rb
58
+ - lib/rmsgen/part.rb
56
59
  - lib/rmsgen/part_group.rb
60
+ - lib/rmsgen/parts/duration.rb
61
+ - lib/rmsgen/parts/footer.rb
62
+ - lib/rmsgen/parts/header.rb
63
+ - lib/rmsgen/parts/indented_line.rb
64
+ - lib/rmsgen/parts/plain_text.rb
65
+ - lib/rmsgen/parts/polnote_url_request.rb
66
+ - lib/rmsgen/parts/url.rb
57
67
  - lib/rmsgen/polnote.rb
68
+ - lib/rmsgen/polnote_group.rb
58
69
  - lib/rmsgen/runtime.rb
59
70
  - lib/rmsgen/script.rb
60
71
  - lib/rmsgen/titleizer.rb
@@ -69,9 +80,12 @@ files:
69
80
  - spec/fixtures/multiline_note
70
81
  - spec/fixtures/urgent_note
71
82
  - spec/fs_polnote_group_spec.rb
83
+ - spec/imap_client_spec.rb
72
84
  - spec/imap_polnote_group_spec.rb
73
85
  - spec/inqirer_spec.rb
74
86
  - spec/part_group_spec.rb
87
+ - spec/part_spec.rb
88
+ - spec/polnote_group.rb
75
89
  - spec/polnote_spec.rb
76
90
  - spec/runtime_spec.rb
77
91
  - spec/support/fake_gets.rb