mailmanager 1.0.14 → 1.0.15

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.
data/.gitignore CHANGED
@@ -3,3 +3,4 @@ pkg/mailmanager-*.gem
3
3
  html/*
4
4
  doc/*
5
5
  results/*
6
+ mailman
data/Changelog CHANGED
@@ -1,4 +1,10 @@
1
- Current version is 1.0.14
1
+ Current version is 1.0.15
2
+
3
+ changes since 1.0.14
4
+ - added a Cucumber integration test suite
5
+ - fixed a list creation bug when Mailman outputs to an aliases db directly
6
+ - added a delete_list method
7
+ - raise exception when attempting to create a mailing list that already exists
2
8
 
3
9
  changes since 1.0.13
4
10
  - more detailed error report when creating a new list fails
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mailmanager (1.0.13)
4
+ mailmanager (1.0.15)
5
5
  json (~> 1.4.6)
6
6
  open4 (~> 1.0.1)
7
7
 
@@ -14,7 +14,15 @@ GEM
14
14
  ci_reporter (1.6.4)
15
15
  builder (>= 2.1.2)
16
16
  columnize (0.3.2)
17
+ cucumber (0.10.0)
18
+ builder (>= 2.1.2)
19
+ diff-lcs (~> 1.1.2)
20
+ gherkin (~> 2.3.2)
21
+ json (~> 1.4.6)
22
+ term-ansicolor (~> 1.0.5)
17
23
  diff-lcs (1.1.2)
24
+ gherkin (2.3.3)
25
+ json (~> 1.4.6)
18
26
  json (1.4.6)
19
27
  linecache19 (0.5.11)
20
28
  ruby_core_source (>= 0.1.4)
@@ -37,6 +45,7 @@ GEM
37
45
  ruby-debug-base19 (>= 0.11.19)
38
46
  ruby_core_source (0.1.4)
39
47
  archive-tar-minitar (>= 0.5.2)
48
+ term-ansicolor (1.0.5)
40
49
 
41
50
  PLATFORMS
42
51
  ruby
@@ -44,6 +53,7 @@ PLATFORMS
44
53
  DEPENDENCIES
45
54
  ZenTest (~> 4.4.2)
46
55
  ci_reporter
56
+ cucumber
47
57
  mailmanager!
48
58
  rspec (~> 2.4.0)
49
59
  ruby-debug19
data/README.rdoc CHANGED
@@ -83,6 +83,25 @@ Exposing new list properties works something like this:
83
83
  That should get you started hacking on the gem. If you get stuck or are trying to
84
84
  do anything more complex, please feel free to e-mail me: cap10morgan@gmail.com.
85
85
 
86
+ == Testing
87
+
88
+ The RSpec suite should run out of the box with the 'rake spec' command.
89
+ Feel free to open a GitHub issue if they do not.
90
+
91
+ You'll need a local working installation of GNU Mailman 2.1.14 (or a later version
92
+ of 2.1.x, probably) to run the Cucumber integration tests. Make a symlink to the
93
+ root directory of your Mailman install in the mailmanager directory. It should be
94
+ named "mailman". So if you are in the top-level mailmanager directory and your
95
+ Mailman installation is in /usr/local/mailman, you would run this command:
96
+ ln -s /usr/local/mailman mailman
97
+
98
+ Once that's done, you should be able to just run 'cucumber' in the top-level
99
+ mailmanager directory.
100
+
101
+ _MAKE SURE THIS IS NOT A MAILMAN INSTALLATION YOU CARE ABOUT!_ The Cucumber test
102
+ suite will start by deleting all mailing lists so it can have a clean slate to
103
+ test with.
104
+
86
105
  == Contributing
87
106
 
88
107
  - Fork on GitHub
@@ -0,0 +1,11 @@
1
+ <%
2
+ all_opts = "--color"
3
+ rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
4
+ rerun_opts = "#{all_opts} " + (rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}")
5
+ std_opts = "#{all_opts} --format #{ENV['CUCUMBER_FORMAT'] || 'progress'} --strict --tags ~@wip"
6
+ %>
7
+ default: <%= std_opts %> features
8
+ wip: --tags @wip:3 --wip features
9
+ rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
10
+ autotest: <%= rerun_opts %>
11
+ autotest-all: <%= std_opts %>
@@ -0,0 +1,18 @@
1
+ Feature: Creating a new list
2
+ As a developer using MailManager
3
+ In order to create new mailing lists
4
+ I want MailManager to offer this feature
5
+
6
+ Background:
7
+ Given MailManager is initialized on "./mailman"
8
+
9
+ Scenario: Creating a new list
10
+ Given no lists exist
11
+ When I create a new list "foo"
12
+ Then I should have a list named "foo"
13
+
14
+ Scenario: Creating a list with the same name as an existing list
15
+ Given no lists exist
16
+ When I create a new list "foo"
17
+ Then it should raise MailManager::ListNameConflictError when I create a new list "foo"
18
+ And I should have 1 list
@@ -0,0 +1,4 @@
1
+ When /^I create a new list "([^"]*)"$/ do |list_name|
2
+ @mailmanager.create_list(:name => list_name, :admin_email => 'cuke@foo.org', :admin_password => 'greenisgood')
3
+ end
4
+
@@ -0,0 +1,24 @@
1
+ Given /^MailManager is initialized on "([^\"]+)"$/ do |mailman_root|
2
+ @mailmanager = MailManager.init(mailman_root)
3
+ end
4
+
5
+ Given /^no lists exist$/ do
6
+ @mailmanager.list_names.each do |list_name|
7
+ @mailmanager.delete_list(list_name)
8
+ end
9
+ end
10
+
11
+ Then /^it should raise (.+?) when (.+)$/ do |exception,when_step|
12
+ lambda {
13
+ When when_step
14
+ }.should raise_error(eval(exception))
15
+ end
16
+
17
+ Then /^I should have (\d+) lists?$/ do |num|
18
+ @mailmanager.should have(num.to_i).lists
19
+ end
20
+
21
+ Then /^I should have a list named "([^"]*)"$/ do |list_name|
22
+ @mailmanager.list_names.should include(list_name)
23
+ end
24
+
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', File.dirname(__FILE__))
2
+ require "mailmanager"
@@ -3,6 +3,12 @@ module MailManager
3
3
  class MailmanExecuteError < StandardError #:nodoc:
4
4
  end
5
5
 
6
+ class ListNotFoundError < StandardError #:nodoc:
7
+ end
8
+
9
+ class ListNameConflictError < StandardError #:nodoc:
10
+ end
11
+
6
12
  class Lib #:nodoc:all
7
13
 
8
14
  def mailmanager
@@ -15,8 +21,33 @@ module MailManager
15
21
  parse_output(cmd, out)
16
22
  end
17
23
 
24
+ def list_names
25
+ lists.map { |list| list.name }
26
+ end
27
+
18
28
  def create_list(params)
29
+ raise ArgumentError, "Missing :name param" if params[:name].nil?
30
+ list_name = params[:name]
31
+ raise ListNameConflictError, "List \"#{list_name}\" already exists" if list_names.include?(list_name)
19
32
  cmd = :newlist
33
+ # create the list
34
+ out = command(cmd, params)
35
+ # get the new list
36
+ begin
37
+ get_list(list_name)
38
+ rescue ListNotFoundError
39
+ raise MailmanExecuteError, "List creation failed: #{out}"
40
+ end
41
+ end
42
+
43
+ def get_list(list_name)
44
+ raise ListNotFoundError, "#{list_name} does not exist" unless list_names.include?(list_name)
45
+ MailManager::List.new(list_name)
46
+ end
47
+
48
+ def delete_list(params)
49
+ params = {:name => params} unless params.respond_to?(:has_key?)
50
+ cmd = :rmlist
20
51
  out = command(cmd, params)
21
52
  parse_output(cmd, out)
22
53
  end
@@ -141,7 +172,7 @@ module MailManager
141
172
  mailman_cmd = "#{mailmanager.root}/bin/#{cmd.to_s} "
142
173
  # delete opts as we handle them explicitly
143
174
  stdin = nil
144
- stdin = opts.delete(:stdin) if opts.has_key?(:stdin)
175
+ stdin = opts.delete(:stdin) if opts.respond_to?(:has_key?) && opts.has_key?(:stdin)
145
176
  case cmd
146
177
  when :newlist
147
178
  mailman_cmd += "-q "
@@ -152,6 +183,9 @@ module MailManager
152
183
  escape(opts.delete(key))
153
184
  }.join(' ')
154
185
  mailman_cmd += "#{mailman_cmd_suffix} "
186
+ when :rmlist
187
+ raise ArgumentError, "Missing :name param" if opts[:name].nil?
188
+ mailman_cmd += "#{escape(opts.delete(:name))} "
155
189
  when :withlist
156
190
  raise ArgumentError, "Missing :name param" if opts[:name].nil?
157
191
  proxy_path = File.dirname(__FILE__)
@@ -211,6 +245,8 @@ module MailManager
211
245
  end
212
246
  raise MailmanExecuteError, "Error getting name of newly created list. Mailman sent:\n#{output}" if list_name.nil?
213
247
  return_obj = MailManager::List.new(list_name)
248
+ when :rmlist
249
+ return_obj = output =~ /Removing list info/
214
250
  when :list_lists
215
251
  lists = []
216
252
  puts "Output from Mailman:\n#{output}" if MailManager.debug
@@ -35,6 +35,15 @@ module MailManager
35
35
  lib.create_list(params)
36
36
  end
37
37
 
38
+ def self.delete(list_name) #:nodoc:
39
+ lib.delete_list(list_name)
40
+ end
41
+
42
+ # Deletes the list, but not the archives
43
+ def delete
44
+ self.class.delete(self.name)
45
+ end
46
+
38
47
  # Returns the list's email address
39
48
  def address
40
49
  result = lib.list_address(self)
@@ -1,3 +1,3 @@
1
1
  module MailManager
2
- VERSION = '1.0.14'
2
+ VERSION = '1.0.15'
3
3
  end
data/lib/mailmanager.rb CHANGED
@@ -82,7 +82,7 @@ module MailManager
82
82
  # Only retrieves the list names, doesn't wrap them in MailManager::List
83
83
  # instances.
84
84
  def list_names
85
- lists.map { |list| list.name }
85
+ @lib.list_names
86
86
  end
87
87
 
88
88
  # Create a new list. Returns an instance of MailManager::List. Params are:
@@ -96,8 +96,11 @@ module MailManager
96
96
  # Get an existing list as a MailManager::List instance. Raises an exception if
97
97
  # the list doesn't exist.
98
98
  def get_list(list_name)
99
- raise "#{list_name} list does not exist" unless list_names.include?(list_name.downcase)
100
- MailManager::List.new(list_name)
99
+ @lib.get_list(list_name)
100
+ end
101
+
102
+ def delete_list(list_name)
103
+ MailManager::List.delete(list_name)
101
104
  end
102
105
  end
103
106
 
data/mailmanager.gemspec CHANGED
@@ -27,4 +27,5 @@ spec = Gem::Specification.new do |s|
27
27
  s.add_development_dependency('ZenTest', '~>4.4.2')
28
28
  s.add_development_dependency('ruby-debug19')
29
29
  s.add_development_dependency('ci_reporter')
30
+ s.add_development_dependency('cucumber')
30
31
  end
@@ -5,6 +5,14 @@ describe MailManager::Lib do
5
5
  let(:subject) { MailManager::Lib.new }
6
6
  let(:fake_root) { '/foo/bar' }
7
7
  let(:process) { mock(Process::Status) }
8
+ let(:list_result) { <<EOF
9
+ 3 matching mailing lists found:
10
+ Foo - [no description available]
11
+ BarBar - Dummy list
12
+ Mailman - Mailman site list
13
+ EOF
14
+ }
15
+ let(:list_result_after_create) { list_result + "\n Bar - [no description available]\n" }
8
16
 
9
17
  before :each do
10
18
  subject.stub(:mailmanager).and_return(mailmanager)
@@ -14,47 +22,48 @@ describe MailManager::Lib do
14
22
 
15
23
  describe "#lists" do
16
24
  it "should return all existing lists" do
17
- list_result = <<EOF
18
- 3 matching mailing lists found:
19
- Foo - [no description available]
20
- BarBar - Dummy list
21
- Mailman - Mailman site list
22
- EOF
23
25
  subject.stub(:run_command).with("#{fake_root}/bin/list_lists 2>&1", nil).
24
- and_return([list_result,process])
26
+ and_return([list_result, process])
25
27
  subject.lists.should have(3).lists
26
28
  end
27
29
  end
28
30
 
29
31
  describe "#create_list" do
32
+ before :each do
33
+ subject.stub(:run_command).with("#{fake_root}/bin/list_lists 2>&1", nil).
34
+ and_return([list_result, process])
35
+ end
36
+
30
37
  it "should raise an argument error if list name is missing" do
31
38
  lambda {
32
39
  subject.create_list(:admin_email => 'foo@bar.baz', :admin_password => 'qux')
33
40
  }.should raise_error(ArgumentError)
34
41
  end
42
+
35
43
  it "should raise an argument error if list admin email is missing" do
36
44
  lambda {
37
- subject.create_list(:name => 'foo', :admin_password => 'qux')
45
+ subject.create_list(:name => 'bar', :admin_password => 'qux')
38
46
  }.should raise_error(ArgumentError)
39
47
  end
48
+
40
49
  it "should raise an argument error if admin password is missing" do
41
50
  lambda {
42
- subject.create_list(:name => 'foo', :admin_email => 'foo@bar.baz')
51
+ subject.create_list(:name => 'bar', :admin_email => 'foo@bar.baz')
43
52
  }.should raise_error(ArgumentError)
44
53
  end
45
54
 
46
55
  context "with valid list params" do
47
56
  let(:new_aliases) {
48
- ['foo: "|/foo/bar/mail/mailman post foo"',
49
- 'foo-admin: "|/foo/bar/mail/mailman admin foo"',
50
- 'foo-bounces: "|/foo/bar/mail/mailman bounces foo"',
51
- 'foo-confirm: "|/foo/bar/mail/mailman confirm foo"',
52
- 'foo-join: "|/foo/bar/mail/mailman join foo"',
53
- 'foo-leave: "|/foo/bar/mail/mailman leave foo"',
54
- 'foo-owner: "|/foo/bar/mail/mailman owner foo"',
55
- 'foo-request: "|/foo/bar/mail/mailman request foo"',
56
- 'foo-subscribe: "|/foo/bar/mail/mailman subscribe foo"',
57
- 'foo-unsubscribe: "|/foo/bar/mail/mailman unsubscribe foo"']
57
+ ['bar: "|/foo/bar/mail/mailman post bar"',
58
+ 'bar-admin: "|/foo/bar/mail/mailman admin bar"',
59
+ 'bar-bounces: "|/foo/bar/mail/mailman bounces bar"',
60
+ 'bar-confirm: "|/foo/bar/mail/mailman confirm bar"',
61
+ 'bar-join: "|/foo/bar/mail/mailman join bar"',
62
+ 'bar-leave: "|/foo/bar/mail/mailman leave bar"',
63
+ 'bar-owner: "|/foo/bar/mail/mailman owner bar"',
64
+ 'bar-request: "|/foo/bar/mail/mailman request bar"',
65
+ 'bar-subscribe: "|/foo/bar/mail/mailman subscribe bar"',
66
+ 'bar-unsubscribe: "|/foo/bar/mail/mailman unsubscribe bar"']
58
67
  }
59
68
  let(:new_list_return) {
60
69
  prefix =<<EOF
@@ -62,24 +71,55 @@ To finish creating your mailing list, you must edit your /etc/aliases (or
62
71
  equivalent) file by adding the following lines, and possibly running the
63
72
  `newaliases' program:
64
73
 
65
- ## foo mailing list
74
+ ## bar mailing list
66
75
  EOF
67
76
  prefix+new_aliases.join("\n")
68
77
  }
69
- let(:fake_aliases_file) { mock(File) }
70
78
 
71
- before :each do
72
- File.stub(:open).with('/etc/aliases', 'a').and_return(fake_aliases_file)
73
- subject.stub(:run_newaliases_command)
79
+ it "should create the list" do
80
+ subject.should_receive(:run_command).
81
+ with("#{fake_root}/bin/newlist -q \"bar\" \"foo@bar.baz\" \"qux\" 2>&1", nil).
82
+ and_return([new_list_return, process])
83
+ subject.should_receive(:run_command).
84
+ with("#{fake_root}/bin/list_lists 2>&1", nil).
85
+ and_return([list_result, process], [list_result_after_create, process])
86
+ subject.create_list(:name => 'bar', :admin_email => 'foo@bar.baz',
87
+ :admin_password => 'qux')
74
88
  end
75
89
 
76
- it "should create the list" do
90
+ it "should not rely on the aliases setup output" do
91
+ # https://www.pivotaltracker.com/story/show/9422507
92
+ subject.should_receive(:run_command).
93
+ with("#{fake_root}/bin/newlist -q \"bar\" \"foo@bar.baz\" \"qux\" 2>&1", nil).
94
+ and_return(["", process])
77
95
  subject.should_receive(:run_command).
78
- with("#{fake_root}/bin/newlist -q \"foo\" \"foo@bar.baz\" \"qux\" 2>&1", nil).
79
- and_return([new_list_return,process])
80
- subject.create_list(:name => 'foo', :admin_email => 'foo@bar.baz',
96
+ with("#{fake_root}/bin/list_lists 2>&1", nil).
97
+ and_return([list_result, process], [list_result_after_create, process])
98
+ subject.create_list(:name => 'bar', :admin_email => 'foo@bar.baz',
81
99
  :admin_password => 'qux')
82
100
  end
101
+
102
+ it "should raise an exception if the list already exists" do
103
+ # https://www.pivotaltracker.com/story/show/9421449
104
+ subject.should_not_receive(:run_command).
105
+ with("#{fake_root}/bin/newlist -q \"foo\" \"foo@bar.baz\" \"qux\" 2>&1", nil)
106
+ subject.should_receive(:run_command).
107
+ with("#{fake_root}/bin/list_lists 2>&1", nil).
108
+ and_return([list_result, process])
109
+ lambda {
110
+ subject.create_list(:name => 'foo', :admin_email => 'foo@bar.baz',
111
+ :admin_password => 'qux')
112
+ }.should raise_error(MailManager::ListNameConflictError)
113
+ end
114
+ end
115
+ end
116
+
117
+ describe "#delete_list" do
118
+ it "should delete the list" do
119
+ subject.should_receive(:run_command).
120
+ with("#{fake_root}/bin/rmlist \"foo\" 2>&1", nil).
121
+ and_return(["Removing list info", process])
122
+ subject.delete_list('foo')
83
123
  end
84
124
  end
85
125
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 0
8
- - 14
9
- version: 1.0.14
8
+ - 15
9
+ version: 1.0.15
10
10
  platform: ruby
11
11
  authors:
12
12
  - Wes Morgan
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-31 00:00:00 -05:00
17
+ date: 2011-02-01 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -103,6 +103,19 @@ dependencies:
103
103
  version: "0"
104
104
  type: :development
105
105
  version_requirements: *id006
106
+ - !ruby/object:Gem::Dependency
107
+ name: cucumber
108
+ prerelease: false
109
+ requirement: &id007 !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ type: :development
118
+ version_requirements: *id007
106
119
  description: Ruby wrapper library for GNU Mailman's admin functions
107
120
  email: MorganW@dnc.org
108
121
  executables: []
@@ -121,6 +134,11 @@ files:
121
134
  - LICENSE
122
135
  - README.rdoc
123
136
  - Rakefile
137
+ - config/cucumber.yml
138
+ - features/create_list.feature
139
+ - features/step_definitions/create_list_steps.rb
140
+ - features/step_definitions/global_steps.rb
141
+ - features/support/env.rb
124
142
  - lib/mailmanager.rb
125
143
  - lib/mailmanager/lib.rb
126
144
  - lib/mailmanager/list.rb