spec/ezmlm/list_spec.rb
changeset 14 cba9fb39bcdb
parent 12 3cc813140c80
child 15 a38e6916504c
equal deleted inserted replaced
13:a03c08c289e9 14:cba9fb39bcdb
    10 require_relative '../spec_helpers'
    10 require_relative '../spec_helpers'
    11 require 'ezmlm'
    11 require 'ezmlm'
    12 
    12 
    13 describe Ezmlm::List do
    13 describe Ezmlm::List do
    14 
    14 
    15 	# Testing constants
    15 	before( :each ) do
    16 	TEST_LISTDIR               = Pathname.new( 'list' )
    16 		@listdir = make_listdir()
    17 	TEST_LIST_NAME             = 'waffle-lovers'
    17 	end
    18 	TEST_LIST_HOST             = 'lists.syrup.info'
    18 
    19 	TEST_OWNER                 = 'listowner@rumpus-the-whale.info'
    19 	after( :each ) do
    20 	TEST_CUSTOM_MODERATORS_DIR = '/foo/bar/clowns'
    20 		rm_r( @listdir )
    21 
    21 	end
    22 	TEST_SUBSCRIBERS = %w[
    22 
    23 		pete.chaffee@toadsmackers.com
    23 	let( :list ) do
    24 		dolphinzombie@alahalohamorra.com
    24 		described_class.new( @listdir )
    25 		piratebanker@yahoo.com
    25 	end
    26 	  ]
    26 
    27 
    27 
    28 	TEST_MODERATORS = %w[
    28 	it "can return the list name" do
    29 		dolphinzombie@alahalohamorra.com
    29 		expect( list.name ).to eq( TEST_LIST_NAME )
    30 	  ]
    30 	end
    31 
    31 
    32 	TEST_CONFIG = <<-"EOF".gsub( /^\t+/, '' )
    32 	it "can return the list host" do
    33 		F:-aBCDeFGHijKlMnOpQrStUVWXYZ
    33 		expect( list.host ).to eq( TEST_LIST_HOST )
    34 		X:
    34 	end
    35 		D:/var/qmail/alias/lists/waffle-lovers/
    35 
    36 		T:/var/qmail/alias/.qmail-waffle-lovers
    36 	it "can return the list address" do
    37 		L:#{TEST_LIST_NAME}
    37 		expect( list.address ).to eq( TEST_LIST_NAME + '@' + TEST_LIST_HOST )
    38 		H:#{TEST_LIST_HOST}
    38 	end
    39 		C:
    39 
    40 		0:
    40 	it "returns nil if the list owner isn't an email address" do
    41 		3:
    41 		expect( list.owner ).to eq( nil )
    42 		4:
    42 	end
    43 		5:#{TEST_OWNER}
    43 
    44 		6:
    44 	it "can return an email address owner" do
    45 		7:
    45 		expect( list ).to receive( :read ).with( 'owner' ).and_return( TEST_OWNER )
    46 		8:
    46 		expect( list.owner ).to eq( TEST_OWNER )
    47 		9:
    47 	end
    48 	EOF
    48 
    49 
    49 
    50 
    50 	it "can add a new subscriber" do
    51 	it "can create a list"
    51 		list.add_subscriber( *TEST_SUBSCRIBERS )
    52 	it "can add a new subscriber"
    52 		expect( list.is_subscriber?( TEST_SUBSCRIBERS.first ) ).to be_truthy
    53 	it "can remove a current subscriber"
    53 	end
    54 	it "can edit the list's text files"
    54 
    55 
    55 	it "can return the list of subscibers" do
    56 
    56 		list.add_subscriber( *TEST_SUBSCRIBERS )
    57 	###
    57 		list.add_subscriber( 'notanemailaddress' )
    58 	### List manager functions
    58 		expect( list.subscribers.length ).to eq( 3 )
    59 	###
    59 		expect( list.subscribers ).to include( TEST_SUBSCRIBERS.first )
    60 	describe "list manager functions" do
    60 	end
    61 
    61 
    62 		before( :each ) do
    62 	it "can remove a current subscriber" do
    63 			@listpath = TEST_LISTDIR.dup
    63 		list.add_subscriber( *TEST_SUBSCRIBERS )
    64 			@list = Ezmlm::List.new( @listpath )
    64 		list.remove_subscriber( 'notanemailaddress' )
    65 		end
    65 		list.remove_subscriber( TEST_MODERATORS.first )
    66 
    66 		expect( list.subscribers.length ).to eq( 2 )
    67 
    67 	end
    68 		it "can return the configured list name" do
    68 
    69 			allow(@list).to receive( :config ).and_return({ 'L' => :the_list_name })
    69 
    70 			expect(@list.name).to eq(:the_list_name)
    70 	it "can add a new moderator" do
    71 		end
    71 		list.add_moderator( *TEST_MODERATORS )
    72 
    72 		expect( list.is_moderator?( TEST_MODERATORS.first ) ).to be_truthy
    73 
    73 	end
    74 		it "can return the configured list host" do
    74 
    75 			allow(@list).to receive( :config ).and_return({ 'H' => :the_list_host })
    75 	it "can return the list of moderators" do
    76 			expect(@list.host).to eq(:the_list_host)
    76 		list.add_moderator( *TEST_MODERATORS )
    77 		end
    77 		expect( list.moderators.length ).to eq( 1 )
    78 
    78 		expect( list.moderators ).to include( TEST_MODERATORS.first )
    79 
    79 	end
    80 		it "can return the configured list address" do
    80 
    81 			allow(@list).to receive( :config ).and_return({ 'L' => TEST_LIST_NAME, 'H' => TEST_LIST_HOST })
    81 	it "can remove a current moderator" do
    82 			expect(@list.address).to eq("%s@%s" % [ TEST_LIST_NAME, TEST_LIST_HOST ])
    82 		list.add_moderator( *TEST_MODERATORS )
    83 		end
    83 		list.remove_moderator( TEST_MODERATORS.first )
    84 
    84 		expect( list.moderators ).to be_empty
    85 
    85 	end
    86 		CONFIG_KEYS = %w[ F X D T L H C 0 3 4 5 6 7 8 9 ]
    86 
    87 
    87 
    88 		it "can fetch the list config as a Hash" do
    88 	it "can add a blacklisted address" do
    89 			config_path = double( "Mock config path" )
    89 		list.add_blacklisted( *TEST_MODERATORS )
    90 			expect(@listpath).to receive( :+ ).with( 'config' ).and_return( config_path )
    90 		expect( list.is_blacklisted?( TEST_MODERATORS.first ) ).to be_truthy
    91 			expect(config_path).to receive( :exist? ).and_return( true )
    91 	end
    92 			expect(config_path).to receive( :read ).and_return( TEST_CONFIG )
    92 
    93 
    93 	it "can return the list of blacklisted addresses" do
    94 			expect(@list.config).to be_an_instance_of( Hash )
    94 		list.add_blacklisted( *TEST_MODERATORS )
    95 			expect(@list.config.size).to eq(CONFIG_KEYS.length)
    95 		expect( list.blacklisted.length ).to eq( 1 )
    96 			expect(@list.config.keys).to include( *CONFIG_KEYS )
    96 		expect( list.blacklisted ).to include( TEST_MODERATORS.first )
    97 		end
    97 	end
    98 
    98 
    99 
    99 	it "can remove a blacklisted address" do
   100 		it "raises an error if the list config file doesn't exist" do
   100 		list.add_blacklisted( *TEST_MODERATORS )
   101 			config_path = double( "Mock config path" )
   101 		list.remove_blacklisted( TEST_MODERATORS.first )
   102 			expect(@listpath).to receive( :+ ).with( 'config' ).and_return( config_path )
   102 		expect( list.blacklisted ).to be_empty
   103 			expect(config_path).to receive( :exist? ).and_return( false )
   103 	end
   104 
   104 
   105 			expect {
   105 
   106 				@list.config
   106 	it "can add an allowed address" do
   107 			}.to raise_error( RuntimeError, /does not exist/ )
   107 		list.add_allowed( *TEST_MODERATORS )
   108 		end
   108 		expect( list.is_allowed?( TEST_MODERATORS.first ) ).to be_truthy
   109 
   109 	end
   110 
   110 
   111 		it "can return a list of subscribers' email addresses" do
   111 	it "can return the list of allowed addresses" do
   112 			subscribers_dir = TEST_LISTDIR + 'subscribers'
   112 		list.add_allowed( *TEST_MODERATORS )
   113 
   113 		expect( list.allowed.length ).to eq( 1 )
   114 			expectation = expect(Pathname).to receive( :glob ).with( subscribers_dir + '*' )
   114 		expect( list.allowed ).to include( TEST_MODERATORS.first )
   115 
   115 	end
   116 			TEST_SUBSCRIBERS.each do |email|
   116 
   117 				mock_subfile = double( "Mock subscribers file for '#{email}'" )
   117 	it "can remove a allowed address" do
   118 				expect(mock_subfile).to receive( :read ).and_return( "T#{email}\0" )
   118 		list.add_allowed( *TEST_MODERATORS )
   119 
   119 		list.remove_allowed( TEST_MODERATORS.first )
   120 				expectation.and_yield( mock_subfile )
   120 		expect( list.allowed ).to be_empty
   121 			end
   121 	end
   122 
   122 
   123 			subscribers = @list.subscribers
   123 
   124 
   124 	it 'can return the current threading state' do
   125 			expect(subscribers.size).to eq(TEST_SUBSCRIBERS.length)
   125 		expect( list.threaded? ).to be_falsey
   126 			expect(subscribers).to include( *TEST_SUBSCRIBERS )
   126 	end
   127 		end
   127 
   128 
   128 	it 'can set the threading state' do
   129 
   129 		list.threaded = true
   130 		### Subscriber moderation
   130 		expect( list.threaded? ).to be_truthy
   131 
   131 	end
   132 		it "knows that subscription moderation is enabled if the dir/modsub file exists" do
   132 
   133 			modsub_path_obj = double( "Mock 'modsub' path object" )
   133 
   134 			expect(@listpath).to receive( :+ ).with( 'modsub' ).and_return( modsub_path_obj )
   134 	it 'can return the current public/private state' do
   135 			expect(modsub_path_obj).to receive( :exist? ).and_return( true )
   135 		expect( list.public? ).to be_truthy
   136 
   136 		expect( list.private? ).to be_falsey
   137 			expect(@list).to be_closed()
   137 	end
   138 		end
   138 
   139 
   139 	it 'can set the privacy state' do
   140 		it "knows that subscription moderation is enabled if the dir/remote file exists" do
   140 		list.public = false
   141 			modsub_path_obj = double( "Mock 'modsub' path object" )
   141 		expect( list.public? ).to be_falsey
   142 			expect(@listpath).to receive( :+ ).with( 'modsub' ).and_return( modsub_path_obj )
   142 		expect( list.private? ).to be_truthy
   143 			expect(modsub_path_obj).to receive( :exist? ).and_return( false )
   143 
   144 
   144 		list.private = false
   145 			remote_path_obj = double( "Mock 'remote' path object" )
   145 		expect( list.private? ).to be_falsey
   146 			expect(@listpath).to receive( :+ ).with( 'remote' ).and_return( remote_path_obj )
   146 		expect( list.public? ).to be_truthy
   147 			expect(remote_path_obj).to receive( :exist? ).and_return( true )
   147 	end
   148 
   148 
   149 			expect(@list).to be_closed()
   149 
   150 		end
   150 	it 'can set the remote subscription state' do
   151 
   151 		expect( list.remote_subscriptions? ).to be_falsey
   152 
   152 		list.remote_subscriptions = true
   153 		it "knows that subscription moderation is disabled if neither the dir/modsub nor " +
   153 		expect( list.remote_subscriptions? ).to be_truthy
   154 		   "dir/remote files exist" do
   154 		list.remote_subscriptions = false
   155 			modsub_path_obj = double( "Mock 'modsub' path object" )
   155 		expect( list.remote_subscriptions? ).to be_falsey
   156 			expect(@listpath).to receive( :+ ).with( 'modsub' ).and_return( modsub_path_obj )
   156 	end
   157 			expect(modsub_path_obj).to receive( :exist? ).and_return( false )
   157 
   158 
   158 
   159 			remote_path_obj = double( "Mock 'remote' path object" )
   159 	it 'can set subscription moderation state' do
   160 			expect(@listpath).to receive( :+ ).with( 'remote' ).and_return( remote_path_obj )
   160 		expect( list.moderated_subscriptions? ).to be_falsey
   161 			expect(remote_path_obj).to receive( :exist? ).and_return( false )
   161 		list.moderated_subscriptions = true
   162 
   162 		expect( list.moderated_subscriptions? ).to be_truthy
   163 			expect(@list).not_to be_closed()
   163 		list.moderated_subscriptions = false
   164 		end
   164 		expect( list.moderated_subscriptions? ).to be_falsey
   165 
   165 	end
   166 
   166 
   167 		it "returns an empty array of subscription moderators for an open list" do
   167 
   168 			modsub_path_obj = double( "Mock 'modsub' path object" )
   168 	it 'can set posting moderation state' do
   169 			expect(@listpath).to receive( :+ ).with( 'modsub' ).and_return( modsub_path_obj )
   169 		expect( list.moderated? ).to be_falsey
   170 			expect(modsub_path_obj).to receive( :exist? ).and_return( false )
   170 		list.moderated = true
   171 
   171 		expect( list.moderated? ).to be_truthy
   172 			remote_path_obj = double( "Mock 'remote' path object" )
   172 		list.moderated = false
   173 			expect(@listpath).to receive( :+ ).with( 'remote' ).and_return( remote_path_obj )
   173 		expect( list.moderated? ).to be_falsey
   174 			expect(remote_path_obj).to receive( :exist? ).and_return( false )
   174 	end
   175 
   175 
   176 			expect(@list.subscription_moderators).to be_empty()
   176 
   177 		end
   177 	it 'can set moderation-only posting' do
   178 
   178 		expect( list.moderator_posts_only? ).to be_falsey
   179 		it "can return a list of subscription moderators' email addresses" do
   179 		list.moderator_posts_only = true
   180 			# Test the moderation config files for existence
   180 		expect( list.moderator_posts_only? ).to be_truthy
   181 			modsub_path_obj = double( "Mock 'modsub' path object" )
   181 		list.moderator_posts_only = false
   182 			expect(@listpath).to receive( :+ ).with( 'modsub' ).twice.and_return( modsub_path_obj )
   182 		expect( list.moderator_posts_only? ).to be_falsey
   183 			expect(modsub_path_obj).to receive( :exist? ).twice.and_return( true )
   183 	end
   184 			remote_path_obj = double( "Mock 'remote' path object" )
   184 
   185 			expect(@listpath).to receive( :+ ).with( 'remote' ).and_return( remote_path_obj )
   185 
   186 			expect(remote_path_obj).to receive( :exist? ).once.and_return( true )
   186 	it 'can set user-only posting' do
   187 
   187 		expect( list.user_posts_only? ).to be_falsey
   188 			# Try to read directory names from both config files
   188 		list.user_posts_only = true
   189 			expect(modsub_path_obj).to receive( :read ).with( 1 ).and_return( nil )
   189 		expect( list.user_posts_only? ).to be_truthy
   190 			expect(remote_path_obj).to receive( :read ).with( 1 ).and_return( nil )
   190 		list.user_posts_only = false
   191 
   191 		expect( list.user_posts_only? ).to be_falsey
   192 			# Read subscribers from the default directory
   192 	end
   193 			subscribers_dir = double( "Mock moderator subscribers directory" )
   193 
   194 			expect(@listpath).to receive( :+ ).with( 'mod/subscribers' ).and_return( subscribers_dir )
   194 
   195 			expect(subscribers_dir).to receive( :+ ).with( '*' ).and_return( :mod_sub_dir )
   195 	it 'user+moderation together sets non-subscriber moderation' do
   196 			expectation = expect(Pathname).to receive( :glob ).with( :mod_sub_dir )
   196 		expect( list.user_posts_only? ).to be_falsey
   197 
   197 		expect( list.moderated? ).to be_falsey
   198 			TEST_MODERATORS.each do |email|
   198 
   199 				mock_subfile = double( "Mock subscribers file for '#{email}'" )
   199 		list.moderated = true
   200 				expect(mock_subfile).to receive( :read ).and_return( "T#{email}\0" )
   200 		list.user_posts_only = true
   201 
   201 
   202 				expectation.and_yield( mock_subfile )
   202 		expect( list.listdir + 'noreturnposts' ).to exist
   203 			end
   203 
   204 
   204 		list.moderated = false
   205 			mods = @list.subscription_moderators
   205 		expect( list.listdir + 'noreturnposts' ).to_not exist
   206 			expect(mods.size).to eq(TEST_MODERATORS.length)
   206 	end
   207 			expect(mods).to include( *TEST_MODERATORS )
   207 
   208 		end
   208 
   209 
   209 	it 'can set archival status' do
   210 
   210 		expect( list.archived? ).to be_truthy
   211 		it "can return a list of subscription moderators' email addresses when the moderators " +
   211 		list.archive = false
   212 		   "directory has been customized" do
   212 		expect( list.archived? ).to be_falsey
   213 			# Test the moderation config files for existence
   213 		list.archive = true
   214 			modsub_path_obj = double( "Mock 'modsub' path object" )
   214 		expect( list.archived? ).to be_truthy
   215 			expect(@listpath).to receive( :+ ).with( 'modsub' ).twice.and_return( modsub_path_obj )
   215 	end
   216 			expect(modsub_path_obj).to receive( :exist? ).twice.and_return( true )
   216 
   217 			expect(@listpath).to receive( :+ ).with( 'remote' )
   217 
   218 
   218 	it 'can limit archive access to moderators only' do
   219 			# Try to read directory names from both config files
   219 		expect( list.private_archive? ).to be_falsey
   220 			expect(modsub_path_obj).to receive( :read ).with( 1 ).and_return( '/' )
   220 		list.private_archive = true
   221 			expect(modsub_path_obj).to receive( :read ).with().and_return( TEST_CUSTOM_MODERATORS_DIR )
   221 		expect( list.private_archive? ).to be_truthy
   222 
   222 		list.private_archive = false
   223 			custom_mod_path = double( "Mock path object for customized moderator dir" )
   223 		expect( list.private_archive? ).to be_falsey
   224 			expect(Pathname).to receive( :new ).with( TEST_CUSTOM_MODERATORS_DIR ).and_return( custom_mod_path )
   224 	end
   225 
   225 
   226 			# Read subscribers from the default file
   226 
   227 			expect(custom_mod_path).to receive( :+ ).with( '*' ).and_return( :mod_sub_dir )
   227 	it 'can limit archive access to list subscribers only' do
   228 			expectation = expect(Pathname).to receive( :glob ).with( :mod_sub_dir )
   228 		expect( list.guarded_archive? ).to be_falsey
   229 
   229 		list.guarded_archive = true
   230 			TEST_MODERATORS.each do |email|
   230 		expect( list.guarded_archive? ).to be_truthy
   231 				mock_subfile = double( "Mock subscribers file for '#{email}'" )
   231 		list.guarded_archive = false
   232 				expect(mock_subfile).to receive( :read ).and_return( "T#{email}\0" )
   232 		expect( list.guarded_archive? ).to be_falsey
   233 
   233 	end
   234 				expectation.and_yield( mock_subfile )
   234 
   235 			end
   235 
   236 
   236 	it 'can toggle digest status' do
   237 			mods = @list.subscription_moderators
   237 		expect( list.digested? ).to be_falsey
   238 			expect(mods.size).to eq(TEST_MODERATORS.length)
   238 		list.digest = true
   239 			expect(mods).to include( *TEST_MODERATORS )
   239 		expect( list.digested? ).to be_truthy
   240 		end
   240 		list.digest = false
   241 
   241 		expect( list.digested? ).to be_falsey
   242 		it "can get a list of modererators when remote subscription moderation is enabled" +
   242 	end
   243            " and the modsub configuration is empty" do
   243 
   244 			# Test the moderation config files for existence
   244 	it 'returns a default digest kbyte size' do
   245 			modsub_path_obj = double( "Mock 'modsub' path object" )
   245 		expect( list.digest_kbytesize ).to eq( 64 )
   246 			expect(@listpath).to receive( :+ ).with( 'modsub' ).twice.and_return( modsub_path_obj )
   246 	end
   247 			expect(modsub_path_obj).to receive( :exist? ).twice.and_return( false )
   247 
   248             remote_path_obj = double( "Mock 'remote' path object" )
   248 	it 'can set a new digest kbyte size' do
   249 			expect(@listpath).to receive( :+ ).with( 'remote' ).twice.and_return( remote_path_obj )
   249 		list.digest_kbytesize = 300
   250             expect(remote_path_obj).to receive( :exist? ).twice.and_return( true )
   250 		expect( list.digest_kbytesize ).to eq( 300 )
   251 
   251 	end
   252 			# Try to read directory names from both config files
   252 
   253 			expect(remote_path_obj).to receive( :read ).with( 1 ).and_return( '/' )
   253 	it 'returns a default digest message count' do
   254 			expect(remote_path_obj).to receive( :read ).with().and_return( TEST_CUSTOM_MODERATORS_DIR )
   254 		expect( list.digest_count ).to eq( 10 )
   255 
   255 	end
   256 			custom_mod_path = double( "Mock path object for customized moderator dir" )
   256 
   257 			expect(Pathname).to receive( :new ).with( TEST_CUSTOM_MODERATORS_DIR ).and_return( custom_mod_path )
   257 	it 'can set a new digest message count' do
   258 
   258 		list.digest_count = 25
   259 			# Read subscribers from the default file
   259 		expect( list.digest_count ).to eq( 25 )
   260 			expect(custom_mod_path).to receive( :+ ).with( '*' ).and_return( :mod_sub_dir )
   260 	end
   261 			expectation = expect(Pathname).to receive( :glob ).with( :mod_sub_dir )
   261 
   262 
   262 	it 'returns a default digest timeout' do
   263 			TEST_MODERATORS.each do |email|
   263 		expect( list.digest_timeout ).to eq( 48 )
   264 				mock_subfile = double( "Mock subscribers file for '#{email}'" )
   264 	end
   265 				expect(mock_subfile).to receive( :read ).and_return( "T#{email}\0" )
   265 
   266 
   266 	it 'can set a new digest timeout' do
   267 				expectation.and_yield( mock_subfile )
   267 		list.digest_timeout = 24
   268 			end
   268 		expect( list.digest_timeout ).to eq( 24 )
   269 
   269 	end
   270 			mods = @list.subscription_moderators
   270 
   271 			expect(mods.size).to eq(TEST_MODERATORS.length)
   271 
   272 			expect(mods).to include( *TEST_MODERATORS )
   272 	it 'can set subscription confirmation' do
   273 		end
   273 		expect( list.confirm_subscriptions? ).to be_truthy
   274 
   274 		list.confirm_subscriptions = false
   275 		### Message moderation
   275 		expect( list.confirm_subscriptions? ).to be_falsey
   276 
   276 		list.confirm_subscriptions = true
   277 		it "knows that subscription moderation is enabled if the dir/modpost file exists" do
   277 		expect( list.confirm_subscriptions? ).to be_truthy
   278 			modpost_path_obj = double( "Mock 'modpost' path object" )
   278 	end
   279 			expect(@listpath).to receive( :+ ).with( 'modpost' ).and_return( modpost_path_obj )
   279 
   280 			expect(modpost_path_obj).to receive( :exist? ).and_return( true )
   280 	it 'can set unsubscription confirmation' do
   281 
   281 		expect( list.confirm_unsubscriptions? ).to be_truthy
   282 			expect(@list).to be_moderated()
   282 		list.confirm_unsubscriptions = false
   283 		end
   283 		expect( list.confirm_unsubscriptions? ).to be_falsey
   284 
   284 		list.confirm_unsubscriptions = true
   285 		it "knows that subscription moderation is disabled if the dir/modpost file doesn't exist" do
   285 		expect( list.confirm_unsubscriptions? ).to be_truthy
   286 			modpost_path_obj = double( "Mock 'modpost' path object" )
   286 	end
   287 			expect(@listpath).to receive( :+ ).with( 'modpost' ).and_return( modpost_path_obj )
   287 
   288 			expect(modpost_path_obj).to receive( :exist? ).and_return( false )
   288 
   289 
   289 	it 'can set message posting confirmation' do
   290 			expect(@list).not_to be_moderated()
   290 		expect( list.confirm_postings? ).to be_falsey
   291 		end
   291 		list.confirm_postings = true
   292 
   292 		expect( list.confirm_postings? ).to be_truthy
   293 
   293 		list.confirm_postings = false
   294 		it "returns an empty array of message moderators for an open list" do
   294 		expect( list.confirm_postings? ).to be_falsey
   295 			modpost_path_obj = double( "Mock 'modpost' path object" )
   295 	end
   296 			expect(@listpath).to receive( :+ ).with( 'modpost' ).and_return( modpost_path_obj )
   296 
   297 			expect(modpost_path_obj).to receive( :exist? ).and_return( false )
   297 
   298 
   298 	it 'can toggle remote subscriber lists for moderators' do
   299 			expect(@list.message_moderators).to be_empty()
   299 		expect( list.allow_remote_listing? ).to be_falsey
   300 		end
   300 		list.allow_remote_listing = true
   301 
   301 		expect( list.allow_remote_listing? ).to be_truthy
   302 
   302 		list.allow_remote_listing = false
   303 		it "can return a list of message moderators' email addresses" do
   303 		expect( list.allow_remote_listing? ).to be_falsey
   304 			# Test the moderation config file for existence
   304 	end
   305 			modpost_path_obj = double( "Mock 'modpost' path object" )
   305 
   306 			expect(@listpath).to receive( :+ ).with( 'modpost' ).twice.and_return( modpost_path_obj )
   306 
   307 			expect(modpost_path_obj).to receive( :exist? ).twice.and_return( true )
   307 	it 'can toggle bounce management' do
   308 
   308 		expect( list.bounce_warnings? ).to be_truthy
   309 			# Try to read directory names from the config file
   309 		list.bounce_warnings = false
   310 			expect(modpost_path_obj).to receive( :read ).with( 1 ).and_return( nil )
   310 		expect( list.bounce_warnings? ).to be_falsey
   311 
   311 		list.bounce_warnings = true
   312 			# Read subscribers from the default directory
   312 		expect( list.bounce_warnings? ).to be_truthy
   313 			subscribers_dir = double( "Mock moderator subscribers directory" )
   313 	end
   314 			expect(@listpath).to receive( :+ ).with( 'mod/subscribers' ).and_return( subscribers_dir )
   314 
   315 			expect(subscribers_dir).to receive( :+ ).with( '*' ).and_return( :mod_sub_dir )
   315 
   316 			expectation = expect(Pathname).to receive( :glob ).with( :mod_sub_dir )
   316 	it 'returns a default max message size' do
   317 
   317 		expect( list.maximum_message_size ).to eq( 0 )
   318 			TEST_MODERATORS.each do |email|
   318 	end
   319 				mock_subfile = double( "Mock subscribers file for '#{email}'" )
   319 
   320 				expect(mock_subfile).to receive( :read ).and_return( "T#{email}\0" )
   320 	it 'can set a new max message size' do
   321 
   321 		list.maximum_message_size = 1024 * 300
   322 				expectation.and_yield( mock_subfile )
   322 		expect( list.maximum_message_size ).to eq( 307200 )
   323 			end
   323 	end
   324 
   324 
   325 			mods = @list.message_moderators
   325 
   326 			expect(mods.size).to eq(TEST_MODERATORS.length)
   326 	it 'can return the message count for a pristine list' do
   327 			expect(mods).to include( *TEST_MODERATORS )
   327 		expect( list.message_count ).to eq( 0 )
   328 		end
   328 	end
   329 
       
   330 
       
   331 		it "can return a list of message moderators' email addresses when the moderators " +
       
   332 		   "directory has been customized" do
       
   333 			# Test the moderation config files for existence
       
   334 			modpost_path_obj = double( "Mock 'modpost' path object" )
       
   335 			expect(@listpath).to receive( :+ ).with( 'modpost' ).twice.and_return( modpost_path_obj )
       
   336 			expect(modpost_path_obj).to receive( :exist? ).twice.and_return( true )
       
   337 
       
   338 			# Try to read directory names from both config files
       
   339 			expect(modpost_path_obj).to receive( :read ).with( 1 ).and_return( '/' )
       
   340 			expect(modpost_path_obj).to receive( :read ).with().and_return( TEST_CUSTOM_MODERATORS_DIR )
       
   341 
       
   342 			custom_mod_path = double( "Mock path object for customized moderator dir" )
       
   343 			expect(Pathname).to receive( :new ).with( TEST_CUSTOM_MODERATORS_DIR ).and_return( custom_mod_path )
       
   344 
       
   345 			# Read subscribers from the default file
       
   346 			expect(custom_mod_path).to receive( :+ ).with( '*' ).and_return( :mod_sub_dir )
       
   347 			expectation = expect(Pathname).to receive( :glob ).with( :mod_sub_dir )
       
   348 
       
   349 			TEST_MODERATORS.each do |email|
       
   350 				mock_subfile = double( "Mock subscribers file for '#{email}'" )
       
   351 				expect(mock_subfile).to receive( :read ).and_return( "T#{email}\0" )
       
   352 
       
   353 				expectation.and_yield( mock_subfile )
       
   354 			end
       
   355 
       
   356 			mods = @list.message_moderators
       
   357 			expect(mods.size).to eq(TEST_MODERATORS.length)
       
   358 			expect(mods).to include( *TEST_MODERATORS )
       
   359 		end
       
   360 
       
   361 
       
   362 		### List owner
       
   363 
       
   364 		it "returns nil when the list doesn't have an owner in its config" do
       
   365 			allow(@list).to receive( :config ).and_return({ '5' => nil })
       
   366 			expect(@list.owner).to eq(nil)
       
   367 		end
       
   368 
       
   369 
       
   370 		it "can return the email address of the list owner" do
       
   371 			allow(@list).to receive( :config ).and_return({ '5' => TEST_OWNER })
       
   372 			expect(@list.owner).to eq(TEST_OWNER)
       
   373 		end
       
   374 
       
   375 	end
       
   376 
       
   377 
       
   378 	###
       
   379 	### Archive functions
       
   380 	###
       
   381 	describe "archive functions" do
       
   382 
       
   383 		before( :each ) do
       
   384 			@listpath = TEST_LISTDIR.dup
       
   385 			@list = Ezmlm::List.new( @listpath )
       
   386 		end
       
   387 
       
   388 
       
   389 		it "can return the count of archived posts" do
       
   390 			numpath_obj = double( "num file path object" )
       
   391 			expect(@listpath).to receive( :+ ).with( 'num' ).and_return( numpath_obj )
       
   392 
       
   393 			expect(numpath_obj).to receive( :exist? ).and_return( true )
       
   394 			expect(numpath_obj).to receive( :read ).and_return( "1723:123123123" )
       
   395 
       
   396 			expect(@list.message_count).to eq(1723)
       
   397 		end
       
   398 
       
   399 		it "can return the count of archived posts to a list that hasn't been posted to" do
       
   400 			numpath_obj = double( "num file path object" )
       
   401 			expect(@listpath).to receive( :+ ).with( 'num' ).and_return( numpath_obj )
       
   402 
       
   403 			expect(numpath_obj).to receive( :exist? ).and_return( false )
       
   404 
       
   405 			expect(@list.message_count).to eq(0)
       
   406 		end
       
   407 
       
   408 
       
   409 
       
   410 		TEST_ARCHIVE_DIR = TEST_LISTDIR + 'archive'
       
   411 		TEST_ARCHIVE_SUBDIRS = %w[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 ]
       
   412 		TEST_POST_FILES = %w[ 00 01 02 03 04 05 06 07 08 09 10 11 12 13 ]
       
   413 
       
   414 		before( :each ) do
       
   415 			@archive_dir = TEST_ARCHIVE_DIR.dup
       
   416 			@archive_subdirs = TEST_ARCHIVE_SUBDIRS.dup
       
   417 			@archive_subdir_paths = TEST_ARCHIVE_SUBDIRS.collect {|pn| TEST_ARCHIVE_DIR + pn }
       
   418 			@archive_post_paths = TEST_POST_FILES.collect {|pn|
       
   419 				TEST_ARCHIVE_DIR + TEST_ARCHIVE_SUBDIRS.last + pn
       
   420 			  }
       
   421 		end
       
   422 
       
   423 
       
   424 		it "can return a TMail::Mail object parsed from the last archived post" do
       
   425 			# need to find the last message
       
   426 			archive_path_obj = double( "archive path" )
       
   427 
       
   428 			expect(@listpath).to receive( :+ ).with( 'archive' ).and_return( archive_path_obj )
       
   429 			expect(archive_path_obj).to receive( :exist? ).and_return( true )
       
   430 
       
   431 			# Find the last numbered directory under the archive dir
       
   432 			expect(archive_path_obj).to receive( :+ ).with( '[0-9]*' ).
       
   433 				and_return( :archive_dir_globpath )
       
   434 			expect(Pathname).to receive( :glob ).with( :archive_dir_globpath ).
       
   435 				and_return( @archive_subdir_paths )
       
   436 
       
   437 			# Find the last numbered file under the last numbered directory we found
       
   438 			# above.
       
   439 			expect(@archive_subdir_paths.last).to receive( :+ ).with( '[0-9]*' ).
       
   440 				and_return( :archive_post_pathglob )
       
   441 			expect(Pathname).to receive( :glob ).with( :archive_post_pathglob ).
       
   442 				and_return( @archive_post_paths )
       
   443 
       
   444 			expect(TMail::Mail).to receive( :load ).with( @archive_post_paths.last.to_s ).
       
   445 				and_return( :mail_object )
       
   446 
       
   447 			expect(@list.last_post).to eq(:mail_object)
       
   448 		end
       
   449 
       
   450 
       
   451 		it "returns nil for the last post if there is no archive directory for the list" do
       
   452 			archive_path_obj = double( "archive path" )
       
   453 
       
   454 			expect(@listpath).to receive( :+ ).with( 'archive' ).and_return( archive_path_obj )
       
   455 			expect(archive_path_obj).to receive( :exist? ).and_return( false )
       
   456 			expect(@list.last_post).to eq(nil)
       
   457 		end
       
   458 
       
   459 
       
   460 		it "returns nil for the last post if there haven't been any posts to the list" do
       
   461 			archive_path_obj = double( "archive path" )
       
   462 			mail_object = double( "Mock TMail object" )
       
   463 
       
   464 			expect(@listpath).to receive( :+ ).with( 'archive' ).and_return( archive_path_obj )
       
   465 			expect(archive_path_obj).to receive( :exist? ).and_return( true )
       
   466 
       
   467 			# Find the last numbered directory under the archive dir
       
   468 			expect(archive_path_obj).to receive( :+ ).with( '[0-9]*' ).
       
   469 				and_return( :archive_dir_globpath )
       
   470 			expect(Pathname).to receive( :glob ).with( :archive_dir_globpath ).and_return( [] )
       
   471 
       
   472 			expect(@list.last_post).to eq(nil)
       
   473 		end
       
   474 
       
   475 
       
   476 		it "raises a RuntimeError if the last archive directory doesn't have any messages in it" do
       
   477 			archive_path_obj = double( "archive path" )
       
   478 			mail_object = double( "Mock TMail object" )
       
   479 
       
   480 			expect(@listpath).to receive( :+ ).with( 'archive' ).and_return( archive_path_obj )
       
   481 			expect(archive_path_obj).to receive( :exist? ).and_return( true )
       
   482 
       
   483 			# Find the last numbered directory under the archive dir
       
   484 			expect(archive_path_obj).to receive( :+ ).with( '[0-9]*' ).
       
   485 				and_return( :archive_dir_globpath )
       
   486 			expect(Pathname).to receive( :glob ).with( :archive_dir_globpath ).
       
   487 				and_return( @archive_subdir_paths )
       
   488 
       
   489 			expect(@archive_subdir_paths.last).to receive( :+ ).with( '[0-9]*' ).
       
   490 				and_return( :archive_post_pathglob )
       
   491 			expect(Pathname).to receive( :glob ).with( :archive_post_pathglob ).
       
   492 				and_return( [] )
       
   493 
       
   494 			expect {
       
   495 				@list.last_post
       
   496 			}.to raise_error( RuntimeError, /unexpectedly empty/i )
       
   497 		end
       
   498 
       
   499 
       
   500 		it "can fetch the date of the last archived post" do
       
   501 			mail_object = double( "Mock TMail object" )
       
   502 
       
   503 			expect(@list).to receive( :last_post ).and_return( mail_object )
       
   504 			expect(mail_object).to receive( :date ).and_return( :the_message_date )
       
   505 
       
   506 			expect(@list.last_message_date).to eq(:the_message_date)
       
   507 		end
       
   508 
       
   509 
       
   510 		it "can fetch the date of the last archived post" do
       
   511 			mail_object = double( "Mock TMail object" )
       
   512 
       
   513 			expect(@list).to receive( :last_post ).and_return( mail_object )
       
   514 			expect(mail_object).to receive( :date ).and_return( :the_message_date )
       
   515 
       
   516 			expect(@list.last_message_date).to eq(:the_message_date)
       
   517 		end
       
   518 
       
   519 
       
   520 		it "can fetch the author of the last archived post" do
       
   521 			mail_object = double( "Mock TMail object" )
       
   522 
       
   523 			expect(@list).to receive( :last_post ).and_return( mail_object )
       
   524 			expect(mail_object).to receive( :from ).and_return( :the_message_author )
       
   525 
       
   526 			expect(@list.last_message_author).to eq(:the_message_author)
       
   527 		end
       
   528 
       
   529 
       
   530 		it "can fetch the subject of the last archived post" do
       
   531 			mail_object = double( "Mock TMail object" )
       
   532 
       
   533 			expect(@list).to receive( :last_post ).and_return( mail_object )
       
   534 			expect(mail_object).to receive( :from ).and_return( :the_message_author )
       
   535 
       
   536 			expect(@list.last_message_author).to eq(:the_message_author)
       
   537 		end
       
   538 
       
   539 	end
       
   540 
       
   541 
       
   542 	it "can fetch the body of an archived post by message id"
       
   543 	it "can fetch the header of an archived post by message id"
       
   544 
       
   545 	it "can return a hash of the subjects of all archived posts to message ids"
       
   546 	it "can return an Array of the subjects of all archived posts"
       
   547 
       
   548 	it "can return a hash of the threads of all archived posts to message ids"
       
   549 	it "can return an Array of the threads of all archived posts"
       
   550 
       
   551 	it "can return a hash of the authors of all archived posts to message ids"
       
   552 	it "can return an Array of the authors of all archived posts"
       
   553 
       
   554 end
   329 end
   555 
   330 
   556 
   331 
       
   332 
       
   333 	# it "can fetch the body of an archived post by message id"
       
   334 	# it "can fetch the header of an archived post by message id"
       
   335 
       
   336 	# it "can return a hash of the subjects of all archived posts to message ids"
       
   337 	# it "can return an Array of the subjects of all archived posts"
       
   338 
       
   339 	# it "can return a hash of the threads of all archived posts to message ids"
       
   340 	# it "can return an Array of the threads of all archived posts"
       
   341 
       
   342 	# it "can return a hash of the authors of all archived posts to message ids"
       
   343 	# it "can return an Array of the authors of all archived posts"
       
   344 
       
   345