rmsgen 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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