bell 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/.gitignore +5 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +2 -0
  4. data/Gemfile.lock +47 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.org +128 -0
  7. data/Rakefile +16 -0
  8. data/bell.gemspec +30 -0
  9. data/bin/bell +5 -0
  10. data/features/create_user.feature +16 -0
  11. data/features/full_report.feature +84 -0
  12. data/features/import_public_contacts.feature +20 -0
  13. data/features/import_user_contacts.feature +43 -0
  14. data/features/list_all_contacts.feature +19 -0
  15. data/features/list_user_contacts.feature +27 -0
  16. data/features/list_users.feature +22 -0
  17. data/features/remove_user.feature +21 -0
  18. data/features/rename_user.feature +25 -0
  19. data/features/step_definitions/cli_steps.rb +59 -0
  20. data/features/step_definitions/contact_steps.rb +104 -0
  21. data/features/step_definitions/database_steps.rb +3 -0
  22. data/features/step_definitions/report_steps.rb +17 -0
  23. data/features/step_definitions/user_steps.rb +71 -0
  24. data/features/support/env.rb +65 -0
  25. data/features/user_report.feature +67 -0
  26. data/lib/bell/cli.rb +12 -0
  27. data/lib/bell/commands/command.rb +58 -0
  28. data/lib/bell/commands/contact_command.rb +91 -0
  29. data/lib/bell/commands/implosion_command.rb +14 -0
  30. data/lib/bell/commands/report_command.rb +69 -0
  31. data/lib/bell/commands/user_command.rb +74 -0
  32. data/lib/bell/commands.rb +5 -0
  33. data/lib/bell/csv_parser.rb +52 -0
  34. data/lib/bell/dispatcher.rb +13 -0
  35. data/lib/bell/displayable.rb +13 -0
  36. data/lib/bell/full_report.rb +145 -0
  37. data/lib/bell/handlers/contacts_handler.rb +79 -0
  38. data/lib/bell/handlers/implosions_handler.rb +9 -0
  39. data/lib/bell/handlers/reports_handler.rb +41 -0
  40. data/lib/bell/handlers/users_handler.rb +50 -0
  41. data/lib/bell/handlers.rb +4 -0
  42. data/lib/bell/message.rb +115 -0
  43. data/lib/bell/public_contact.rb +17 -0
  44. data/lib/bell/user.rb +16 -0
  45. data/lib/bell/user_contact.rb +18 -0
  46. data/lib/bell/user_report.rb +88 -0
  47. data/lib/bell/util.rb +31 -0
  48. data/lib/bell.rb +157 -0
  49. data/spec/bell/cli_spec.rb +4 -0
  50. data/spec/bell/commands/command_spec.rb +59 -0
  51. data/spec/bell/commands/contact_command_spec.rb +112 -0
  52. data/spec/bell/commands/implosion_command_spec.rb +31 -0
  53. data/spec/bell/commands/report_command_spec.rb +71 -0
  54. data/spec/bell/commands/user_command_spec.rb +128 -0
  55. data/spec/bell/csv_parser_spec.rb +167 -0
  56. data/spec/bell/dispatcher_spec.rb +4 -0
  57. data/spec/bell/full_report_spec.rb +4 -0
  58. data/spec/bell/handlers/contacts_handler_spec.rb +160 -0
  59. data/spec/bell/handlers/implosions_handler_spec.rb +11 -0
  60. data/spec/bell/handlers/reports_handler_spec.rb +183 -0
  61. data/spec/bell/handlers/users_handler_spec.rb +94 -0
  62. data/spec/bell/public_contact_spec.rb +4 -0
  63. data/spec/bell/user_contact_spec.rb +4 -0
  64. data/spec/bell/user_report_spec.rb +4 -0
  65. data/spec/bell/user_spec.rb +4 -0
  66. data/spec/spec_helper.rb +21 -0
  67. metadata +230 -0
@@ -0,0 +1,167 @@
1
+ require File.expand_path(File.dirname(__FILE__) << '/../spec_helper')
2
+
3
+ describe Bell::CSVParser do
4
+ describe ".parse_contacts" do
5
+ let(:options) { { :path => '/path/to/contacts.csv',
6
+ :user => { :name => 'foo' } } }
7
+ let(:described_module) { Bell::CSVParser }
8
+
9
+ context "when given a path to a non-existing file or directory" do
10
+ let(:no_such_file_or_directory_message) do
11
+ Bell::Message.no_such_file_or_directory(options[:path])
12
+ end
13
+
14
+ it "shows the 'no such file or directory' message" do
15
+ Bell::CSV.stub!(:read).and_raise(Errno::ENOENT)
16
+ described_module.
17
+ should_receive(:display).
18
+ with(no_such_file_or_directory_message)
19
+ described_module.parse_contacts(options)
20
+ end
21
+ end
22
+
23
+ context "when given a path to a directory" do
24
+ let(:path_is_a_directory_message) do
25
+ Bell::Message.path_is_a_directory(options[:path])
26
+ end
27
+
28
+ it "shows the 'path is a directory' message" do
29
+ Bell::CSV.stub!(:read).and_raise(Errno::EISDIR)
30
+ described_module.
31
+ should_receive(:display).
32
+ with(path_is_a_directory_message)
33
+ described_module.parse_contacts(options)
34
+ end
35
+ end
36
+
37
+ context "when given a path to a malformed csv file" do
38
+ let(:invalid_contacts_file_message) do
39
+ Bell::Message.invalid_contacts_file(options[:path])
40
+ end
41
+
42
+ it "shows the 'invalid contacts file' message" do
43
+ Bell::CSV.stub!(:read).and_raise(Bell::CSV::MalformedCSVError)
44
+ described_module.
45
+ should_receive(:display).
46
+ with(invalid_contacts_file_message)
47
+ described_module.parse_contacts(options)
48
+ end
49
+ end
50
+
51
+ context "when given a csv file with invalid rows" do
52
+ let(:user) { mock(Bell::User, :null_object => true) }
53
+
54
+ before do
55
+ described_module.stub!(:raise).with(Bell::InvalidContacts)
56
+ end
57
+
58
+ context "when there's a row with less than two columns" do
59
+ let(:first_row) { ['bob', '9876987698'] }
60
+ let(:second_row) { ['kennedy'] }
61
+ let(:row_with_few_columns_message) do
62
+ Bell::Message.row_with_few_columns(second_row, 2)
63
+ end
64
+
65
+ it "shows the 'row with few columns' message" do
66
+ Bell::CSV.stub!(:read).and_return([first_row, second_row])
67
+ Bell::User.stub!(:find).and_return(user)
68
+ described_module.
69
+ should_receive(:display).
70
+ with(row_with_few_columns_message)
71
+ described_module.parse_contacts(options)
72
+ end
73
+ end
74
+
75
+ context "when there's a row with more than two columns" do
76
+ let(:first_row) { ["1234123412", "john", "kennedy"] }
77
+ let(:second_row) { ["bob", "9876987698"] }
78
+ let(:row_with_extra_columns_message) do
79
+ Bell::Message.row_with_extra_columns(first_row, 1)
80
+ end
81
+
82
+ it "shows the 'row with extra columns' message" do
83
+ Bell::CSV.stub!(:read).and_return([first_row, second_row])
84
+ Bell::User.stub!(:find).and_return(user)
85
+ described_module.
86
+ should_receive(:display).
87
+ with(row_with_extra_columns_message)
88
+ described_module.parse_contacts(options)
89
+ end
90
+ end
91
+ end
92
+
93
+ context "when given a valid csv file" do
94
+ let(:user) { mock(Bell::User, :null_object => true) }
95
+
96
+ before do
97
+ described_module.stub!(:raise).with(Bell::InvalidContacts)
98
+ end
99
+
100
+ context "when there's a row with a short contact number" do
101
+ let(:first_row) { ["john", "1234123412"] }
102
+ let(:second_row) { ["bob", "987698769"] }
103
+ let(:contact) { Bell::UserContact.new(:name => second_row.first,
104
+ :number => second_row.last,
105
+ :user_id => user.id) }
106
+ let(:formatted_contact_errors_message) do
107
+ Bell::Message.formatted_contact_errors(contact, :line_number => 2)
108
+ end
109
+
110
+ it "shows the contact's errors" do
111
+ Bell::CSV.stub!(:read).and_return([first_row, second_row])
112
+ Bell::User.stub!(:find).and_return(user)
113
+ contact.valid?
114
+ described_module.
115
+ should_receive(:display).
116
+ with(formatted_contact_errors_message)
117
+ described_module.parse_contacts(options)
118
+ end
119
+ end
120
+
121
+ context "when there's a row with a long contact number" do
122
+ let(:first_row) { ["bob", "98769876989"] }
123
+ let(:second_row) { ["john", "1234123412"] }
124
+ let(:contact) { Bell::UserContact.new(:name => first_row.first,
125
+ :number => first_row.last,
126
+ :user_id => user.id) }
127
+ let(:formatted_contact_errors_message) do
128
+ Bell::Message.formatted_contact_errors(contact, :line_number => 1)
129
+ end
130
+
131
+ it "shows the contact's errors" do
132
+ Bell::CSV.stub!(:read).and_return([first_row, second_row])
133
+ Bell::User.stub!(:find).and_return(user)
134
+ contact.valid?
135
+ described_module.
136
+ should_receive(:display).
137
+ with(formatted_contact_errors_message)
138
+ described_module.parse_contacts(options)
139
+ end
140
+ end
141
+
142
+ context "with empty rows" do
143
+ it "returns nil" do
144
+ Bell::CSV.stub!(:read).and_return([])
145
+ described_module.parse_contacts(options).should be_nil
146
+ end
147
+ end
148
+
149
+ context "with valid rows" do
150
+ let(:first_row) { ["john", "1234123412"] }
151
+ let(:second_row) { ["bob", "9876987698"] }
152
+ let(:first_contact) { Bell::UserContact.new(:name => first_row.first,
153
+ :number => first_row.last,
154
+ :user_id => user.id) }
155
+ let(:second_contact) { Bell::UserContact.new(:name => second_row.first,
156
+ :number => second_row.last,
157
+ :user_id => user.id) }
158
+ it "returns an array with the contact instances" do
159
+ Bell::CSV.stub!(:read).and_return([first_row, second_row])
160
+ Bell::User.stub!(:find).and_return(user)
161
+ described_module.parse_contacts(options).
162
+ should == [first_contact, second_contact]
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,4 @@
1
+ require File.expand_path(File.dirname(__FILE__) << '/../spec_helper')
2
+
3
+ describe Bell::Dispatcher do
4
+ end
@@ -0,0 +1,4 @@
1
+ require File.expand_path(File.dirname(__FILE__) << '/../spec_helper')
2
+
3
+ describe Bell::FullReport do
4
+ end
@@ -0,0 +1,160 @@
1
+ require File.expand_path(File.dirname(__FILE__) << '/../../spec_helper')
2
+
3
+ describe Bell::Handlers::ContactsHandler do
4
+ let(:params) { mock("params").as_null_object }
5
+ let(:formatted_contact_list) { mock("formatted_contact_list") }
6
+ let(:user) do
7
+ mock(Bell::User, :id => 1,
8
+ :null_object => true,
9
+ :contacts => mock("contacts"))
10
+ end
11
+ let(:contact) { mock(Bell::UserContact).as_null_object }
12
+ let(:contacts_handler) { described_class }
13
+ let(:no_contacts_created_message) { Bell::Message.no_contacts_created }
14
+
15
+ describe ".list" do
16
+ context "called without extra arguments" do
17
+ context "there are no contacts created" do
18
+
19
+ it "shows the 'no contacts created' message" do
20
+ params.stub!(:empty?).and_return(true)
21
+ Bell::UserContact.stub!(:empty?).and_return(true)
22
+ contacts_handler.should_receive(:display).with(no_contacts_created_message)
23
+ contacts_handler.list
24
+ end
25
+ end
26
+
27
+ context "there are contacts created" do
28
+ it "shows a list with all contacts" do
29
+ params.stub!(:empty?).and_return(true)
30
+ Bell::UserContact.stub!(:empty?).and_return(false)
31
+ contacts_handler.should_receive(:formatted_contact_list).
32
+ and_return(formatted_contact_list)
33
+ contacts_handler.should_receive(:display).with(formatted_contact_list)
34
+ contacts_handler.list
35
+ end
36
+ end
37
+ end
38
+
39
+ context "called with a user name" do
40
+ context "when a user with the given doesn't exist" do
41
+ let(:user_does_not_exist_message) do
42
+ Bell::Message.user_does_not_exist(params[:user][:name])
43
+ end
44
+
45
+ it "shows the 'user does not exist' message" do
46
+ params.stub!(:empty?).and_return(false)
47
+ Bell::User.stub!(:find).and_return(false)
48
+ contacts_handler.should_receive(:display).with(user_does_not_exist_message)
49
+ contacts_handler.list(params)
50
+ end
51
+ end
52
+
53
+ context "when the given user exists" do
54
+ before do
55
+ params.stub!(:empty?).and_return(false)
56
+ Bell::User.stub!(:find).and_return(user)
57
+ end
58
+
59
+ context "when doesn't have contacts" do
60
+ let(:contact_list_empty_message) do
61
+ Bell::Message.contact_list_empty(user.name)
62
+ end
63
+
64
+ it "shows the 'contact list empty' message" do
65
+ user.stub_chain(:contacts, :empty?).and_return(true)
66
+ contacts_handler.should_receive(:display).with(contact_list_empty_message)
67
+ contacts_handler.list(params)
68
+ end
69
+ end
70
+
71
+ context "when it has contacts" do
72
+ it "shows a list with all the users' contacts" do
73
+ user.stub_chain(:contacts, :empty?).and_return(false)
74
+ contacts_handler.should_receive(:formatted_contact_list).
75
+ and_return(formatted_contact_list)
76
+ contacts_handler.should_receive(:display).with(formatted_contact_list)
77
+ contacts_handler.list(params)
78
+ end
79
+
80
+ context "when asked for the CSV format" do
81
+ let(:contacts) { mock("contacts", :empty? => false) }
82
+ let(:user) { mock(Bell::User, :name => 'bob', :contacts => contacts) }
83
+ let(:params) { { :user => { :name => user.name }, :csv => true } }
84
+
85
+ it "shows a list with all the users' contacts" do
86
+ contacts_handler.should_receive(:formatted_contact_list).
87
+ with(user.contacts, :user_contacts => true, :csv => true).
88
+ and_return(formatted_contact_list)
89
+ contacts_handler.should_receive(:display).
90
+ with(formatted_contact_list)
91
+ contacts_handler.list(params)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ describe ".import" do
100
+ context "when requesting a user contact import" do
101
+ let(:params) { { :user => { :name => 'foo' } } }
102
+
103
+ context "when the given user exists" do
104
+ let(:contacts) { [mock(Bell::User), mock(Bell::User) ]}
105
+
106
+ context "when the CSVParser returns contacts" do
107
+ it "saves them" do
108
+ Bell::User.stub!(:find).and_return(user)
109
+ Bell::CSVParser.stub!(:parse_contacts).and_return(contacts)
110
+ contacts.each { |contact| contact.should_receive(:save) }
111
+ described_class.import(params)
112
+ end
113
+ end
114
+
115
+ context "when CSVParser raises InvalidContacts" do
116
+ it "shows the 'no contacts created' message" do
117
+ Bell::User.stub!(:find).and_return(user)
118
+ Bell::CSVParser.stub!(:parse_contacts).and_raise(Bell::InvalidContacts)
119
+ described_class.should_receive(:display).with(no_contacts_created_message)
120
+ described_class.import(params)
121
+ end
122
+ end
123
+ end
124
+
125
+ context "when the given user doesn't exist" do
126
+ let(:user_does_not_exist_message) { mock('user_does_not_exist_message') }
127
+
128
+ it "shows the 'user does not exist' message" do
129
+ Bell::User.stub!(:find).and_return(nil)
130
+ Bell::Message.
131
+ should_receive(:user_does_not_exist).
132
+ and_return(user_does_not_exist_message)
133
+ described_class.import(params)
134
+ end
135
+ end
136
+ end
137
+
138
+ context "when requesting a public contact import" do
139
+ let(:params) { { :path => '/path/to/public_contacts.csv',
140
+ :public => true } }
141
+ let(:contacts) { [mock(Bell::User), mock(Bell::User) ]}
142
+
143
+ context "when the CSVParser returns contacts" do
144
+ it "saves them" do
145
+ Bell::CSVParser.stub!(:parse_contacts).and_return(contacts)
146
+ contacts.each { |contact| contact.should_receive(:save) }
147
+ described_class.import(params)
148
+ end
149
+ end
150
+
151
+ context "when CSVParser returns raises InvalidContacts" do
152
+ it "shows the 'no contacts created' message" do
153
+ Bell::CSVParser.stub!(:parse_contacts).and_raise(Bell::InvalidContacts)
154
+ described_class.should_receive(:display).with(no_contacts_created_message)
155
+ described_class.import(params)
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,11 @@
1
+ require File.expand_path(File.dirname(__FILE__) << '/../../spec_helper')
2
+
3
+ describe Bell::Handlers::ImplosionsHandler do
4
+ let(:params) { mock("params").as_null_object }
5
+ let(:implosions_handler) { described_class }
6
+
7
+ it "implodes the current bell databases" do
8
+ Bell.should_receive(:implode!)
9
+ implosions_handler.implode(params)
10
+ end
11
+ end
@@ -0,0 +1,183 @@
1
+ require File.expand_path(File.dirname(__FILE__) << '/../../spec_helper')
2
+
3
+ describe Bell::Handlers::ReportsHandler do
4
+ let(:no_such_file_or_directory_message) { mock("no_such_file_or_directory_message") }
5
+ let(:path_is_a_directory_message) { mock("path_is_a_directory_message") }
6
+ let(:non_csv_file_message) { mock("non_csv_file_message") }
7
+ let(:malformed_csv_message) { mock("malformed_csv_message") }
8
+ let(:invalid_rows_message) { mock("invalid_rows_message") }
9
+ let(:invalid_rows_exception_message) { 'Erro nas linhas 3, 4' }
10
+ let(:invalid_rows_exception) { Embratel::InvalidRowsError.new(invalid_rows_exception_message) }
11
+ let(:phone_bill) { mock(Embratel::PhoneBill) }
12
+
13
+ describe ".full_report" do
14
+ let(:params) { { :path => 'fatura.csv' } }
15
+
16
+ context "when given a path to a non-existing file or directory" do
17
+ it "shows the 'no such file or directory' message" do
18
+ Embratel::PhoneBill.stub!(:new).and_raise(Errno::ENOENT)
19
+ Bell::Message.should_receive(:no_such_file_or_directory).
20
+ with(params[:path]).
21
+ and_return(no_such_file_or_directory_message)
22
+ described_class.should_receive(:display).
23
+ with(no_such_file_or_directory_message)
24
+ described_class.full_report(params)
25
+ end
26
+ end
27
+
28
+ context "when given a path to a directory" do
29
+ it "shows the 'path is a directory' message" do
30
+ Embratel::PhoneBill.stub!(:new).and_raise(Errno::EISDIR)
31
+ Bell::Message.should_receive(:path_is_a_directory).
32
+ with(params[:path]).
33
+ and_return(path_is_a_directory_message)
34
+ described_class.should_receive(:display).
35
+ with(path_is_a_directory_message)
36
+ described_class.full_report(params)
37
+ end
38
+ end
39
+
40
+ context "when given a path to a malformed CSV file" do
41
+ it "shows the 'invalid phone bill file' message" do
42
+ Embratel::PhoneBill.stub!(:new).and_raise(Bell::CSV::MalformedCSVError)
43
+ Bell::Message.should_receive(:malformed_csv_file).
44
+ with(params[:path]).
45
+ and_return(malformed_csv_message)
46
+ described_class.should_receive(:display).
47
+ with(malformed_csv_message)
48
+ described_class.full_report(params)
49
+ end
50
+ end
51
+
52
+ context "when given a path to a non CSV file" do
53
+ it "shows the 'non csv file' message" do
54
+ Embratel::PhoneBill.stub!(:new).and_raise(Embratel::NonCSVFileError)
55
+ Bell::Message.should_receive(:non_csv_file).
56
+ with(params[:path]).
57
+ and_return(non_csv_file_message)
58
+ described_class.should_receive(:display).with(non_csv_file_message)
59
+ described_class.full_report(params)
60
+ end
61
+ end
62
+
63
+ context "when given a path to a phone bill file with invalid rows" do
64
+ it "shows the 'invalid rows' message" do
65
+ Embratel::PhoneBill.stub!(:new).and_raise(invalid_rows_exception)
66
+ Bell::Message.should_receive(:invalid_rows).
67
+ with(params[:path], invalid_rows_exception_message).
68
+ and_return(invalid_rows_message)
69
+ described_class.should_receive(:display).with(invalid_rows_message)
70
+ described_class.user_report(params)
71
+ end
72
+ end
73
+
74
+ context "when given a path to a valid phone bill file" do
75
+ let(:report) { mock(Bell::FullReport, :to_s => mock("string")) }
76
+
77
+ it "shows the report" do
78
+ Embratel::PhoneBill.stub!(:new).and_return(phone_bill)
79
+ Bell::FullReport.should_receive(:new).with(phone_bill).and_return(report)
80
+ described_class.should_receive(:display).with(report.to_s)
81
+ described_class.full_report(params)
82
+ end
83
+ end
84
+ end
85
+
86
+ describe ".user_report" do
87
+ let(:params) { { :path => 'fatura.csv', :user => { :name => 'bob' } } }
88
+
89
+ context "when given a path to a non-existing file or directory" do
90
+ it "shows the 'no such file or directory' message" do
91
+ Embratel::PhoneBill.stub!(:new).and_raise(Errno::ENOENT)
92
+ Bell::Message.should_receive(:no_such_file_or_directory).
93
+ with(params[:path]).
94
+ and_return(no_such_file_or_directory_message)
95
+ described_class.should_receive(:display).
96
+ with(no_such_file_or_directory_message)
97
+ described_class.user_report(params)
98
+ end
99
+ end
100
+
101
+ context "when given a path to a directory" do
102
+ it "shows the 'path is a directory' message" do
103
+ Embratel::PhoneBill.stub!(:new).and_raise(Errno::EISDIR)
104
+ Bell::Message.should_receive(:path_is_a_directory).
105
+ with(params[:path]).
106
+ and_return(path_is_a_directory_message)
107
+ described_class.should_receive(:display).
108
+ with(path_is_a_directory_message)
109
+ described_class.user_report(params)
110
+ end
111
+ end
112
+
113
+ context "when given a path to a malformed CSV file" do
114
+ it "shows the 'malformed csv file' message" do
115
+ Embratel::PhoneBill.stub!(:new).and_raise(Bell::CSV::MalformedCSVError)
116
+ Bell::Message.should_receive(:malformed_csv_file).
117
+ with(params[:path]).
118
+ and_return(malformed_csv_message)
119
+ described_class.should_receive(:display).
120
+ with(malformed_csv_message)
121
+ described_class.user_report(params)
122
+ end
123
+ end
124
+
125
+ context "when given a path to a non CSV file" do
126
+ it "shows the 'non csv file' message" do
127
+ Embratel::PhoneBill.stub!(:new).and_raise(Embratel::NonCSVFileError)
128
+ Bell::Message.should_receive(:non_csv_file).
129
+ with(params[:path]).
130
+ and_return(non_csv_file_message)
131
+ described_class.should_receive(:display).with(non_csv_file_message)
132
+ described_class.user_report(params)
133
+ end
134
+ end
135
+
136
+ context "when given a path to a phone bill file with invalid rows" do
137
+ it "shows the 'invalid rows' message" do
138
+ Embratel::PhoneBill.stub!(:new).and_raise(invalid_rows_exception)
139
+ Bell::Message.should_receive(:invalid_rows).
140
+ with(params[:path], invalid_rows_exception_message).
141
+ and_return(invalid_rows_message)
142
+ described_class.should_receive(:display).with(invalid_rows_message)
143
+ described_class.user_report(params)
144
+ end
145
+ end
146
+
147
+ context "when given a path to a valid phone bill file" do
148
+ context "when given user exists" do
149
+ let(:user) { mock(Bell::User) }
150
+ let(:user_report) { mock(Bell::UserReport, :to_s => mock("string")) }
151
+
152
+ it "shows the report" do
153
+ Embratel::PhoneBill.stub!(:new).and_return(phone_bill)
154
+ Bell::User.stub!(:find).
155
+ with(:name => params[:user][:name]).
156
+ and_return(user)
157
+ Bell::UserReport.should_receive(:new).
158
+ with(phone_bill, params[:user][:name]).
159
+ and_return(user_report)
160
+ described_class.should_receive(:display).with(user_report.to_s)
161
+ described_class.user_report(params)
162
+ end
163
+ end
164
+
165
+ context "when given user doesn't exist" do
166
+ let(:user_does_not_exist_message) { mock("user_does_not_exist_message") }
167
+
168
+ it "shows the 'user does not exist' message" do
169
+ Embratel::PhoneBill.stub!(:new).and_return(phone_bill)
170
+ Bell::User.stub!(:find).
171
+ with(:name => params[:user][:name]).
172
+ and_return(nil)
173
+ Bell::Message.should_receive(:user_does_not_exist).
174
+ with(params[:user][:name]).
175
+ and_return(user_does_not_exist_message)
176
+ described_class.should_receive(:display).
177
+ with(user_does_not_exist_message)
178
+ described_class.user_report(params)
179
+ end
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,94 @@
1
+ require File.expand_path(File.dirname(__FILE__) << '/../../spec_helper')
2
+
3
+ describe Bell::Handlers::UsersHandler do
4
+ let(:users_handler) { described_class }
5
+ let(:user_created_message) { Bell::Message.user_created(params[:user][:name]) }
6
+ let(:no_created_users_message) { Bell::Message.no_created_users }
7
+ let(:user_already_exists_message) do
8
+ Bell::Message.user_already_exists(params[:user][:name])
9
+ end
10
+
11
+ describe ".create" do
12
+ let(:params) { { :user => { :name => 'bob' } } }
13
+
14
+ context "when there is already a user with the given name" do
15
+ it "shows the 'user already exists' message" do
16
+ Bell::User.stub!(:find).with(:name => params[:user][:name]).and_return(true)
17
+ users_handler.should_receive(:display).with(user_already_exists_message)
18
+ users_handler.create(params)
19
+ end
20
+ end
21
+
22
+ context "when there are no users with the given name" do
23
+ it "creates the user" do
24
+ Bell::User.stub!(:find).and_return(false)
25
+ Bell::User.should_receive(:create).with(:name => params[:user][:name])
26
+ users_handler.create(params)
27
+ end
28
+
29
+ it "shows the 'user created' message" do
30
+ users_handler.should_receive(:display).with(user_created_message)
31
+ users_handler.create(params)
32
+ end
33
+ end
34
+ end
35
+
36
+ describe ".list" do
37
+ let(:params) { {} }
38
+
39
+ context "when there are no created users" do
40
+ it "shows the 'no created users' message" do
41
+ Bell::User.stub!(:empty?).and_return(true)
42
+ users_handler.should_receive(:display).with(no_created_users_message)
43
+ users_handler.list(params)
44
+ end
45
+ end
46
+
47
+ context "when there are created users" do
48
+ let(:bob) { Bell::User.new(:name => 'bob') }
49
+ let(:john) { Bell::User.new(:name => 'john') }
50
+
51
+ it "shows the users' names" do
52
+ Bell::User.stub!(:empty?).and_return(false)
53
+ Bell::User.stub!(:all).and_return([bob, john])
54
+ users_handler.should_receive(:display).with("bob\njohn")
55
+ users_handler.list(params)
56
+ end
57
+ end
58
+ end
59
+
60
+ describe ".remove" do
61
+ let(:params) { { :user => { :name => 'bob' } } }
62
+
63
+ context "when there are no users with the given name" do
64
+ let(:user_does_not_exist_message) do
65
+ Bell::Message.user_does_not_exist(params[:user][:name])
66
+ end
67
+
68
+ it "shows the 'user does not exist' message" do
69
+ Bell::User.stub!(:find).with(:name => params[:user][:name]).and_return(false)
70
+ users_handler.should_receive(:display).with(user_does_not_exist_message)
71
+ users_handler.remove(params)
72
+ end
73
+ end
74
+
75
+ context "when there is a user with the given name" do
76
+ let(:user) { mock(Bell::User, :name => 'bob').as_null_object }
77
+ let(:user_removed_message) { Bell::Message.user_removed(user.name) }
78
+
79
+ before do
80
+ Bell::User.stub!(:find).and_return(user)
81
+ end
82
+
83
+ it "removes the user" do
84
+ user.should_receive(:destroy)
85
+ users_handler.remove(params)
86
+ end
87
+
88
+ it "shows the 'user removed' message" do
89
+ users_handler.should_receive(:display).with(user_removed_message)
90
+ users_handler.remove(params)
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,4 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe Bell::PublicContact do
4
+ end
@@ -0,0 +1,4 @@
1
+ require File.expand_path(File.dirname(__FILE__) << '/../spec_helper')
2
+
3
+ describe Bell::UserContact do
4
+ end
@@ -0,0 +1,4 @@
1
+ require File.expand_path(File.dirname(__FILE__) << '/../spec_helper')
2
+
3
+ describe Bell::UserReport do
4
+ end
@@ -0,0 +1,4 @@
1
+ require File.expand_path(File.dirname(__FILE__) << '/../spec_helper')
2
+
3
+ describe Bell::User do
4
+ end
@@ -0,0 +1,21 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'bell'
3
+ require 'spec'
4
+
5
+ unless defined?(FIXTURES_PATH)
6
+ FIXTURES_PATH = File.join(File.dirname(__FILE__), 'fixtures')
7
+ end
8
+
9
+ Spec::Runner.configure do |config|
10
+ config.suppress_deprecation_warnings!
11
+ end
12
+
13
+ class Spec::Example::ExampleGroup
14
+ def execute(*args, &block)
15
+ DB.transaction do
16
+ super(*args, &block)
17
+ raise Sequel::Error::Rollback
18
+ end
19
+ true
20
+ end
21
+ end