sinatra-admin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +176 -0
  6. data/Rakefile +2 -0
  7. data/dummy/config.ru +12 -0
  8. data/dummy/config/mongoid.yml +6 -0
  9. data/dummy/dummy.rb +19 -0
  10. data/dummy/models/admin.rb +6 -0
  11. data/dummy/models/comment.rb +5 -0
  12. data/dummy/models/user.rb +11 -0
  13. data/dummy/views/admin/customs/index.haml +4 -0
  14. data/dummy/views/admin/users/custom.haml +2 -0
  15. data/features/admin_login.feature +36 -0
  16. data/features/admin_logout.feature +14 -0
  17. data/features/creating_users.feature +44 -0
  18. data/features/custom_pages.feature +34 -0
  19. data/features/default_root.feature +43 -0
  20. data/features/editing_users.feature +46 -0
  21. data/features/listing_users.feature +46 -0
  22. data/features/main_menu_resources.feature +41 -0
  23. data/features/removing_users.feature +34 -0
  24. data/features/step_definitions/common_steps.rb +59 -0
  25. data/features/step_definitions/web_steps.rb +212 -0
  26. data/features/support/database_cleaner.rb +17 -0
  27. data/features/support/env.rb +18 -0
  28. data/features/support/paths.rb +30 -0
  29. data/features/support/sinatra_admin.rb +3 -0
  30. data/features/support/warden.rb +9 -0
  31. data/features/user_details.feature +31 -0
  32. data/lib/sinatra-admin.rb +42 -0
  33. data/lib/sinatra-admin/app.rb +74 -0
  34. data/lib/sinatra-admin/config.rb +45 -0
  35. data/lib/sinatra-admin/helpers/session.rb +24 -0
  36. data/lib/sinatra-admin/helpers/template_lookup.rb +7 -0
  37. data/lib/sinatra-admin/models/admin.rb +40 -0
  38. data/lib/sinatra-admin/register.rb +8 -0
  39. data/lib/sinatra-admin/register/base.rb +29 -0
  40. data/lib/sinatra-admin/register/custom.rb +10 -0
  41. data/lib/sinatra-admin/register/model.rb +75 -0
  42. data/lib/sinatra-admin/version.rb +3 -0
  43. data/lib/sinatra-admin/views/auth/login.haml +16 -0
  44. data/lib/sinatra-admin/views/edit.haml +21 -0
  45. data/lib/sinatra-admin/views/index.haml +34 -0
  46. data/lib/sinatra-admin/views/layout.haml +19 -0
  47. data/lib/sinatra-admin/views/new.haml +19 -0
  48. data/lib/sinatra-admin/views/show.haml +16 -0
  49. data/lib/sinatra-admin/warden_strategies/sinatra_admin.rb +27 -0
  50. data/sinatra-admin.gemspec +36 -0
  51. data/spec/sinatra-admin/app_spec.rb +15 -0
  52. data/spec/sinatra-admin/config_spec.rb +111 -0
  53. data/spec/sinatra-admin/models/admin_spec.rb +33 -0
  54. data/spec/sinatra-admin/register/base_spec.rb +13 -0
  55. data/spec/sinatra-admin/register/custom_spec.rb +40 -0
  56. data/spec/sinatra-admin/register/model_spec.rb +26 -0
  57. data/spec/sinatra-admin/register_spec.rb +15 -0
  58. data/spec/sinatra-admin/version_spec.rb +5 -0
  59. data/spec/sinatra-admin_spec.rb +73 -0
  60. data/spec/spec_helper.rb +81 -0
  61. metadata +343 -0
@@ -0,0 +1,43 @@
1
+ Feature: Default root
2
+ In order to use SinatraAdmin
3
+ As an Admin
4
+ I want to either define a root resource or allow SinatraAdmin to use the first registered
5
+
6
+ Scenario: Admin tries to visit root without login
7
+ Given I add SinatraAdmin as middleware
8
+ And I register "User" resource
9
+ And I register "Comment" resource
10
+ And I am an Admin
11
+ And I define "User" as root resource
12
+ When I go to the home page
13
+ Then I should see "Login - SinatraAdmin"
14
+ And I should see "You must log in"
15
+
16
+ Scenario: Admin is redirected to defined root resource when it's defined
17
+ Given I add SinatraAdmin as middleware
18
+ And I register "User" resource
19
+ And I register "Comment" resource
20
+ And I am an Admin
21
+ And I am logged in as admin
22
+ And I define "User" as root resource
23
+ When I go to the home page
24
+ Then I should see "Users - Index"
25
+ And I should see "_id"
26
+ And I should see "first_name"
27
+ And I should see "last_name"
28
+ And I should see "email"
29
+ And I should see "There are not records in the database"
30
+
31
+ Scenario: Admin is redirected to first registered route when root resource is not defined
32
+ Given I add SinatraAdmin as middleware
33
+ And I register "Comment" resource
34
+ And I register "User" resource
35
+ And I am an Admin
36
+ And I am logged in as admin
37
+ When I go to the home page
38
+ Then I should see "Users - Index"
39
+ And I should see "_id"
40
+ And I should see "first_name"
41
+ And I should see "last_name"
42
+ And I should see "email"
43
+ And I should see "There are not records in the database"
@@ -0,0 +1,46 @@
1
+ Feature: Users edit
2
+ In order to use SinatraAdmin
3
+ As an Admin
4
+ I want to edit users records when I register the "User" resource
5
+
6
+ Scenario: Admin tries to edit a record without login
7
+ Given I add SinatraAdmin as middleware
8
+ And I register "User" resource
9
+ And I am an Admin
10
+ And There are users
11
+ When I go to users listing
12
+ Then I should see "Login - SinatraAdmin"
13
+ And I should see "You must log in"
14
+
15
+ Scenario: Admin edits a record without errors
16
+ Given I add SinatraAdmin as middleware
17
+ And I register "User" resource
18
+ And I am an Admin
19
+ And I am logged in as admin
20
+ And There are users
21
+ And I am on users listing
22
+ And I click on Carlo id
23
+ When I follow "Edit"
24
+ And I fill in "email" with "carlo.edit@herbalife.com"
25
+ And I press "Update"
26
+ Then I should see "User - Show"
27
+ And I should see "_id"
28
+ And I should see "first_name"
29
+ And I should see "last_name"
30
+ And I should see "email"
31
+ And I should see "Carlo"
32
+ And I should see "Cajucom"
33
+ And I should see "carlo.edit@herbalife.com"
34
+
35
+ Scenario: Admin edits a record with errors
36
+ Given I add SinatraAdmin as middleware
37
+ And I register "User" resource
38
+ And I am an Admin
39
+ And I am logged in as admin
40
+ And There are users
41
+ And I am on users listing
42
+ And I click on Carlo id
43
+ When I follow "Edit"
44
+ And I fill in "email" with ""
45
+ And I press "Update"
46
+ Then I should see "email ["can't be blank"]"
@@ -0,0 +1,46 @@
1
+ Feature: Users listing
2
+ In order to use SinatraAdmin
3
+ As an Admin
4
+ I want to see the all users when I register the "User" resource
5
+
6
+ Scenario: Admin tries to see user listing without login
7
+ Given I add SinatraAdmin as middleware
8
+ And I register "User" resource
9
+ And I am an Admin
10
+ And There are users
11
+ When I go to users listing
12
+ Then I should see "Login - SinatraAdmin"
13
+ And I should see "You must log in"
14
+
15
+ Scenario: Admin sees user listing when there are records
16
+ Given I add SinatraAdmin as middleware
17
+ And I register "User" resource
18
+ And I am an Admin
19
+ And I am logged in as admin
20
+ And There are users
21
+ When I go to users listing
22
+ Then I should see "Users - Index"
23
+ And I should see "_id"
24
+ And I should see "first_name"
25
+ And I should see "last_name"
26
+ And I should see "email"
27
+ And I should see "Carlo"
28
+ And I should see "Cajucom"
29
+ And I should see "carlo@herbalife.com"
30
+ And I should see "Francisco"
31
+ And I should see "Delgado"
32
+ And I should see "francisco@herbalife.com"
33
+
34
+ Scenario: Admin sees "No records" message when there are not users
35
+ Given I add SinatraAdmin as middleware
36
+ And I register "User" resource
37
+ And I am an Admin
38
+ And I am logged in as admin
39
+ And There are not users
40
+ When I go to users listing
41
+ Then I should see "Users - Index"
42
+ And I should see "_id"
43
+ And I should see "first_name"
44
+ And I should see "last_name"
45
+ And I should see "email"
46
+ And I should see "There are not records in the database"
@@ -0,0 +1,41 @@
1
+ Feature: Main Menu resources
2
+ In order to use SinatraAdmin
3
+ As an Admin
4
+ I want to see all registered routes links in the main menu
5
+
6
+ Scenario: Admin does not see main menu when he/she is not logged in
7
+ Given I add SinatraAdmin as middleware
8
+ And I register "User" resource
9
+ And I register "Comment" resource
10
+ And I am an Admin
11
+ When I go to the login page
12
+ Then I should not see "Users"
13
+ Then I should not see "Comments"
14
+
15
+ Scenario: Admin sees main menu when he/she is logged in
16
+ Given I add SinatraAdmin as middleware
17
+ And I register "User" resource
18
+ And I register "Comment" resource
19
+ And I am an Admin
20
+ And I am logged in as admin
21
+ When I go to the home page
22
+ Then I should see "Users"
23
+ Then I should see "Comments"
24
+
25
+ Scenario: Admin navigates through main menu when he/she is logged in
26
+ Given I add SinatraAdmin as middleware
27
+ And I register "User" resource
28
+ And I am an Admin
29
+ And I am logged in as admin
30
+ When I go to the home page
31
+ And I follow "Users"
32
+ Then I should see "Users - Index"
33
+
34
+ Scenario: Admin navigates through main menu when he/she is logged in
35
+ Given I add SinatraAdmin as middleware
36
+ And I register "Comment" resource
37
+ And I am an Admin
38
+ And I am logged in as admin
39
+ When I go to the home page
40
+ And I follow "Comments"
41
+ Then I should see "Comments - Index"
@@ -0,0 +1,34 @@
1
+ Feature: User show
2
+ In order to use SinatraAdmin
3
+ As an Admin
4
+ I want to remove user records when I register the "User" resource
5
+ And I click on remove button
6
+
7
+ Scenario: Admin tries to remove a user without login
8
+ Given I add SinatraAdmin as middleware
9
+ And I register "User" resource
10
+ And I am an Admin
11
+ And There are users
12
+ When I go to users listing
13
+ Then I should see "Login - SinatraAdmin"
14
+ And I should see "You must log in"
15
+
16
+ Scenario: Admin removes user from list
17
+ Given I add SinatraAdmin as middleware
18
+ And I register "User" resource
19
+ And I am an Admin
20
+ And I am logged in as admin
21
+ And There are users
22
+ And I am on users listing
23
+ When I click on Carlo remove button
24
+ Then I should see "Users - Index"
25
+ And I should see "_id"
26
+ And I should see "first_name"
27
+ And I should see "last_name"
28
+ And I should see "email"
29
+ And I should see "Francisco"
30
+ And I should see "Delgado"
31
+ And I should see "francisco@herbalife.com"
32
+ And I should not see "Carlo"
33
+ And I should not see "Cajucom"
34
+ And I should not see "carlo@herbalife.com"
@@ -0,0 +1,59 @@
1
+ Given /^I am an Admin$/ do
2
+ @admin = SinatraAdmin.config.admin_model.create(email: "admin@mail.com", password: "admin")
3
+ end
4
+
5
+ Given /^I am logged in as admin$/ do
6
+ login_as @admin, scope: :sinatra_admin
7
+ end
8
+
9
+ Given /^There are users$/ do
10
+ @carlo = User.create(first_name: "Carlo", last_name: "Cajucom", email: "carlo@herbalife.com")
11
+ @fco = User.create(first_name: "Francisco", last_name: "Delgado", email: "francisco@herbalife.com")
12
+ end
13
+
14
+ Given /^There are not users$/ do
15
+ User.destroy_all
16
+ end
17
+
18
+ Given /^I add SinatraAdmin as middleware$/ do
19
+ Dummy::Admin.use SinatraAdmin::App
20
+ end
21
+
22
+ Given /^I register "(\w+)" resource$/ do |resource|
23
+ SinatraAdmin.register resource
24
+ end
25
+
26
+ Given /^I register "(\w+)" resource with custom route$/ do |resource|
27
+ SinatraAdmin.register resource do
28
+ get '/custom/?' do
29
+ @message = "Welcome to Resource model custom page"
30
+ haml "users/custom".to_sym
31
+ end
32
+ end
33
+ end
34
+
35
+ Given /^I register my custom page$/ do
36
+ SinatraAdmin.register 'Custom' do
37
+ get '/?' do
38
+ @welcome_msg = 'Welcome to SinatraAdmin custom pages!'
39
+ @admin_count = SinatraAdmin::Admin.count
40
+ haml 'customs/index'.to_sym
41
+ end
42
+ end
43
+ end
44
+
45
+ Given /^I add main app views to SinatraAdmin views$/ do
46
+ SinatraAdmin.extend_views_from(Dummy::API)
47
+ end
48
+
49
+ Given /^I define "(\w+)" as root resource$/ do |resource|
50
+ SinatraAdmin.root resource
51
+ end
52
+
53
+ When /^I click on Carlo id$/ do
54
+ click_link(@carlo.id.to_s)
55
+ end
56
+
57
+ When /^I click on Carlo remove button$/ do
58
+ click_button("delete_#{@carlo.id.to_s}")
59
+ end
@@ -0,0 +1,212 @@
1
+ require 'uri'
2
+ require 'cgi'
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths"))
4
+
5
+ module WithinHelpers
6
+ def with_scope(locator)
7
+ locator ? within(locator) { yield } : yield
8
+ end
9
+ end
10
+ World(WithinHelpers)
11
+
12
+ Given /^(?:|I )am on (.+)$/ do |page_name|
13
+ visit path_to(page_name)
14
+ end
15
+
16
+ When /^(?:|I )go to (.+)$/ do |page_name|
17
+ visit path_to(page_name)
18
+ end
19
+
20
+ When /^(?:|I )press "([^\"]*)"(?: within "([^\"]*)")?$/ do |button, selector|
21
+ with_scope(selector) do
22
+ click_button(button)
23
+ end
24
+ end
25
+
26
+ When /^(?:|I )follow "([^\"]*)"(?: within "([^\"]*)")?$/ do |link, selector|
27
+ with_scope(selector) do
28
+ click_link(link)
29
+ end
30
+ end
31
+
32
+ When /^(?:|I )fill in "([^\"]*)" with "([^\"]*)"(?: within "([^\"]*)")?$/ do |field, value, selector|
33
+ with_scope(selector) do
34
+ fill_in(field, :with => value)
35
+ end
36
+ end
37
+
38
+ When /^(?:|I )fill in "([^\"]*)" for "([^\"]*)"(?: within "([^\"]*)")?$/ do |value, field, selector|
39
+ with_scope(selector) do
40
+ fill_in(field, :with => value)
41
+ end
42
+ end
43
+
44
+ # Use this to fill in an entire form with data from a table. Example:
45
+ #
46
+ # When I fill in the following:
47
+ # | Account Number | 5002 |
48
+ # | Expiry date | 2009-11-01 |
49
+ # | Note | Nice guy |
50
+ # | Wants Email? | |
51
+ #
52
+ # TODO: Add support for checkbox, select og option
53
+ # based on naming conventions.
54
+ #
55
+ When /^(?:|I )fill in the following(?: within "([^\"]*)")?:$/ do |selector, fields|
56
+ with_scope(selector) do
57
+ fields.rows_hash.each do |name, value|
58
+ When %{I fill in "#{name}" with "#{value}"}
59
+ end
60
+ end
61
+ end
62
+
63
+ When /^(?:|I )select "([^\"]*)" from "([^\"]*)"(?: within "([^\"]*)")?$/ do |value, field, selector|
64
+ with_scope(selector) do
65
+ select(value, :from => field)
66
+ end
67
+ end
68
+
69
+ When /^(?:|I )check "([^\"]*)"(?: within "([^\"]*)")?$/ do |field, selector|
70
+ with_scope(selector) do
71
+ check(field)
72
+ end
73
+ end
74
+
75
+ When /^(?:|I )uncheck "([^\"]*)"(?: within "([^\"]*)")?$/ do |field, selector|
76
+ with_scope(selector) do
77
+ uncheck(field)
78
+ end
79
+ end
80
+
81
+ When /^(?:|I )choose "([^\"]*)"(?: within "([^\"]*)")?$/ do |field, selector|
82
+ with_scope(selector) do
83
+ choose(field)
84
+ end
85
+ end
86
+
87
+ When /^(?:|I )attach the file "([^\"]*)" to "([^\"]*)"(?: within "([^\"]*)")?$/ do |path, field, selector|
88
+ with_scope(selector) do
89
+ attach_file(field, path)
90
+ end
91
+ end
92
+
93
+ Then /^(?:|I )should see JSON:$/ do |expected_json|
94
+ require 'json'
95
+ expected = JSON.pretty_generate(JSON.parse(expected_json))
96
+ actual = JSON.pretty_generate(JSON.parse(response.body))
97
+ expected.should == actual
98
+ end
99
+
100
+ Then /^(?:|I )should see "(.*)"(?: within "([^\"]*)")?$/ do |text, selector|
101
+ with_scope(selector) do
102
+ if page.respond_to? :should
103
+ page.should have_content(text)
104
+ else
105
+ assert page.has_content?(text)
106
+ end
107
+ end
108
+ end
109
+
110
+ Then /^(?:|I )should see \/([^\/]*)\/(?: within "([^\"]*)")?$/ do |regexp, selector|
111
+ regexp = Regexp.new(regexp)
112
+ with_scope(selector) do
113
+ if page.respond_to? :should
114
+ page.should have_xpath('//*', :text => regexp)
115
+ else
116
+ assert page.has_xpath?('//*', :text => regexp)
117
+ end
118
+ end
119
+ end
120
+
121
+ Then /^(?:|I )should not see "([^\"]*)"(?: within "([^\"]*)")?$/ do |text, selector|
122
+ with_scope(selector) do
123
+ if page.respond_to? :should
124
+ page.should have_no_content(text)
125
+ else
126
+ assert page.has_no_content?(text)
127
+ end
128
+ end
129
+ end
130
+
131
+ Then /^(?:|I )should not see \/([^\/]*)\/(?: within "([^\"]*)")?$/ do |regexp, selector|
132
+ regexp = Regexp.new(regexp)
133
+ with_scope(selector) do
134
+ if page.respond_to? :should
135
+ page.should have_no_xpath('//*', :text => regexp)
136
+ else
137
+ assert page.has_no_xpath?('//*', :text => regexp)
138
+ end
139
+ end
140
+ end
141
+
142
+ Then /^the "([^\"]*)" field(?: within "([^\"]*)")? should contain "([^\"]*)"$/ do |field, selector, value|
143
+ with_scope(selector) do
144
+ field = find_field(field)
145
+ field_value = (field.tag_name == 'textarea') ? field.text : field.value
146
+ if field_value.respond_to? :should
147
+ field_value.should =~ /#{value}/
148
+ else
149
+ assert_match(/#{value}/, field_value)
150
+ end
151
+ end
152
+ end
153
+
154
+ Then /^the "([^\"]*)" field(?: within "([^\"]*)")? should not contain "([^\"]*)"$/ do |field, selector, value|
155
+ with_scope(selector) do
156
+ field = find_field(field)
157
+ field_value = (field.tag_name == 'textarea') ? field.text : field.value
158
+ if field_value.respond_to? :should_not
159
+ field_value.should_not =~ /#{value}/
160
+ else
161
+ assert_no_match(/#{value}/, field_value)
162
+ end
163
+ end
164
+ end
165
+
166
+ Then /^the "([^\"]*)" checkbox(?: within "([^\"]*)")? should be checked$/ do |label, selector|
167
+ with_scope(selector) do
168
+ field_checked = find_field(label)['checked']
169
+ if field_checked.respond_to? :should
170
+ field_checked.should == 'checked'
171
+ else
172
+ assert_equal 'checked', field_checked
173
+ end
174
+ end
175
+ end
176
+
177
+ Then /^the "([^\"]*)" checkbox(?: within "([^\"]*)")? should not be checked$/ do |label, selector|
178
+ with_scope(selector) do
179
+ field_checked = find_field(label)['checked']
180
+ if field_checked.respond_to? :should_not
181
+ field_checked.should_not == 'checked'
182
+ else
183
+ assert_not_equal 'checked', field_checked
184
+ end
185
+ end
186
+ end
187
+
188
+ Then /^(?:|I )should be on (.+)$/ do |page_name|
189
+ current_path = URI.parse(current_url).path
190
+ if current_path.respond_to? :should
191
+ current_path.should == path_to(page_name)
192
+ else
193
+ assert_equal path_to(page_name), current_path
194
+ end
195
+ end
196
+
197
+ Then /^(?:|I )should have the following query string:$/ do |expected_pairs|
198
+ query = URI.parse(current_url).query
199
+ actual_params = query ? CGI.parse(query) : {}
200
+ expected_params = {}
201
+ expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')}
202
+
203
+ if actual_params.respond_to? :should
204
+ actual_params.should == expected_params
205
+ else
206
+ assert_equal expected_params, actual_params
207
+ end
208
+ end
209
+
210
+ Then /^show me the page$/ do
211
+ save_and_open_page
212
+ end