date_book 0.0.1

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.
Files changed (203) hide show
  1. checksums.yaml +7 -0
  2. data/.idea/vcs.xml +6 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +23 -0
  5. data/.rubocop_todo.yml +7 -0
  6. data/.ruby-gemset +1 -0
  7. data/.ruby-version +1 -0
  8. data/.travis.yml +3 -0
  9. data/Gemfile +94 -0
  10. data/Gemfile.lock +385 -0
  11. data/LICENSE.txt +20 -0
  12. data/README.md +64 -0
  13. data/Rakefile +30 -0
  14. data/VERSION +1 -0
  15. data/app/assets/images/date_book/.keep +0 -0
  16. data/app/assets/javascripts/date_book.js +21 -0
  17. data/app/assets/javascripts/date_book/calendar_events.js +57 -0
  18. data/app/assets/javascripts/date_book/event_form.js +31 -0
  19. data/app/assets/javascripts/date_book/popovers.js +3 -0
  20. data/app/assets/javascripts/date_book/wysiwyg.js +8 -0
  21. data/app/assets/stylesheets/date_book.css.scss +46 -0
  22. data/app/controllers/date_book/calendars_controller.rb +60 -0
  23. data/app/controllers/date_book/date_book_controller.rb +24 -0
  24. data/app/controllers/date_book/events_controller.rb +105 -0
  25. data/app/controllers/date_book/graphql_controller.rb +35 -0
  26. data/app/graphql/date_book_schema.rb +18 -0
  27. data/app/graphql/types/calendar_type.rb +14 -0
  28. data/app/graphql/types/date_time_type.rb +7 -0
  29. data/app/graphql/types/event_occurrence_type.rb +11 -0
  30. data/app/graphql/types/event_type.rb +19 -0
  31. data/app/graphql/types/mutation_type.rb +5 -0
  32. data/app/graphql/types/profile_type.rb +7 -0
  33. data/app/graphql/types/query_type.rb +57 -0
  34. data/app/helpers/date_book/application_helper.rb +35 -0
  35. data/app/helpers/date_book/calendar_helper.rb +4 -0
  36. data/app/helpers/date_book/events_helper.rb +42 -0
  37. data/app/jobs/date_book/application_job.rb +6 -0
  38. data/app/mailers/date_book/application_mailer.rb +9 -0
  39. data/app/views/date_book/application/_all_day_checkbox.html.haml +1 -0
  40. data/app/views/date_book/application/_date_range.html.haml +8 -0
  41. data/app/views/date_book/application/_wysiwyg.html.haml +65 -0
  42. data/app/views/date_book/calendars/_form.html.haml +6 -0
  43. data/app/views/date_book/calendars/edit.html.haml +5 -0
  44. data/app/views/date_book/calendars/index.html.haml +28 -0
  45. data/app/views/date_book/calendars/new.html.haml +5 -0
  46. data/app/views/date_book/calendars/show.html.haml +28 -0
  47. data/app/views/date_book/events/_event.json.jbuilder +12 -0
  48. data/app/views/date_book/events/_form.html.haml +16 -0
  49. data/app/views/date_book/events/_occurrence_dates.html.haml +11 -0
  50. data/app/views/date_book/events/edit.html.haml +5 -0
  51. data/app/views/date_book/events/fields/_date.html.haml +1 -0
  52. data/app/views/date_book/events/fields/_day.html.haml +1 -0
  53. data/app/views/date_book/events/fields/_day_of_week.html.haml +19 -0
  54. data/app/views/date_book/events/fields/_duration.html.haml +6 -0
  55. data/app/views/date_book/events/fields/_interval.html.haml +1 -0
  56. data/app/views/date_book/events/fields/_time.html.haml +1 -0
  57. data/app/views/date_book/events/index.html.haml +16 -0
  58. data/app/views/date_book/events/new.html.haml +5 -0
  59. data/app/views/date_book/events/popover.html.haml +7 -0
  60. data/app/views/date_book/events/rules/_daily.html.haml +4 -0
  61. data/app/views/date_book/events/rules/_monthly.html.haml +5 -0
  62. data/app/views/date_book/events/rules/_singular.html.haml +4 -0
  63. data/app/views/date_book/events/rules/_weekly.html.haml +5 -0
  64. data/app/views/date_book/events/show.html.haml +16 -0
  65. data/app/views/layouts/_date_book_scripts.html.haml +4 -0
  66. data/app/views/layouts/blank.html.haml +1 -0
  67. data/bin/rails +15 -0
  68. data/config/locales/en.yml +44 -0
  69. data/config/routes.rb +12 -0
  70. data/date_book.gemspec +337 -0
  71. data/db/migrate/20170807133845_create_calendars.rb +11 -0
  72. data/db/migrate/20170807133846_create_events.rb +20 -0
  73. data/db/migrate/20170807133847_create_schedules.rb +25 -0
  74. data/db/migrate/20170807133848_add_fields_to_schedule.rb +6 -0
  75. data/db/migrate/20170807133849_create_event_occurrences.rb +16 -0
  76. data/db/migrate/20170807133850_add_fields_to_event_occurrences.rb +5 -0
  77. data/lib/date_book.rb +40 -0
  78. data/lib/date_book/concerns/ability.rb +27 -0
  79. data/lib/date_book/concerns/acts_as_calendar.rb +29 -0
  80. data/lib/date_book/concerns/acts_as_event.rb +66 -0
  81. data/lib/date_book/concerns/acts_as_event_occurrence.rb +67 -0
  82. data/lib/date_book/concerns/acts_as_ownable.rb +29 -0
  83. data/lib/date_book/concerns/acts_as_owner.rb +18 -0
  84. data/lib/date_book/concerns/acts_as_schedule.rb +44 -0
  85. data/lib/date_book/configuration.rb +43 -0
  86. data/lib/date_book/engine.rb +40 -0
  87. data/lib/date_book/localization.rb +32 -0
  88. data/lib/date_book/version.rb +8 -0
  89. data/lib/generators/date_book/install/install_generator.rb +110 -0
  90. data/lib/generators/date_book/install/templates/app/models/ability.rb +16 -0
  91. data/lib/generators/date_book/install/templates/app/models/calendar.rb +3 -0
  92. data/lib/generators/date_book/install/templates/app/models/event.rb +3 -0
  93. data/lib/generators/date_book/install/templates/app/models/event_occurrence.rb +3 -0
  94. data/lib/generators/date_book/install/templates/app/models/schedule.rb +3 -0
  95. data/lib/generators/date_book/install/templates/config/initializers/date_book.rb +5 -0
  96. data/lib/generators/date_book/utils.rb +25 -0
  97. data/lib/tasks/date_book_tasks.rake +5 -0
  98. data/spec/abilities/calendar_spec.rb +39 -0
  99. data/spec/abilities/event_spec.rb +44 -0
  100. data/spec/controllers/date_book/calendars_controller_spec.rb +259 -0
  101. data/spec/controllers/date_book/events_controller_spec.rb +283 -0
  102. data/spec/dummy/Rakefile +9 -0
  103. data/spec/dummy/app/assets/config/manifest.js +5 -0
  104. data/spec/dummy/app/assets/images/.keep +0 -0
  105. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  106. data/spec/dummy/app/assets/stylesheets/application.css.scss +4 -0
  107. data/spec/dummy/app/assets/stylesheets/bootstrap-everything.scss +54 -0
  108. data/spec/dummy/app/controllers/application_controller.rb +21 -0
  109. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  110. data/spec/dummy/app/helpers/application_helper.rb +4 -0
  111. data/spec/dummy/app/mailers/application_mailer.rb +6 -0
  112. data/spec/dummy/app/models/ability.rb +16 -0
  113. data/spec/dummy/app/models/application_record.rb +5 -0
  114. data/spec/dummy/app/models/calendar.rb +3 -0
  115. data/spec/dummy/app/models/concerns/.keep +0 -0
  116. data/spec/dummy/app/models/event.rb +3 -0
  117. data/spec/dummy/app/models/event_occurrence.rb +3 -0
  118. data/spec/dummy/app/models/role.rb +13 -0
  119. data/spec/dummy/app/models/schedule.rb +3 -0
  120. data/spec/dummy/app/models/user.rb +9 -0
  121. data/spec/dummy/app/views/application/403.html.haml +9 -0
  122. data/spec/dummy/app/views/application/404.html.haml +9 -0
  123. data/spec/dummy/app/views/layouts/application.html.haml +43 -0
  124. data/spec/dummy/app/views/pages/index.html.haml +1 -0
  125. data/spec/dummy/bin/bundle +5 -0
  126. data/spec/dummy/bin/rails +6 -0
  127. data/spec/dummy/bin/rake +6 -0
  128. data/spec/dummy/bin/setup +36 -0
  129. data/spec/dummy/bin/update +31 -0
  130. data/spec/dummy/config.ru +7 -0
  131. data/spec/dummy/config/application.rb +38 -0
  132. data/spec/dummy/config/boot.rb +7 -0
  133. data/spec/dummy/config/cable.yml +9 -0
  134. data/spec/dummy/config/database.yml +25 -0
  135. data/spec/dummy/config/environment.rb +7 -0
  136. data/spec/dummy/config/environments/development.rb +60 -0
  137. data/spec/dummy/config/environments/test.rb +45 -0
  138. data/spec/dummy/config/initializers/application_controller_renderer.rb +7 -0
  139. data/spec/dummy/config/initializers/assets.rb +14 -0
  140. data/spec/dummy/config/initializers/backtrace_silencers.rb +10 -0
  141. data/spec/dummy/config/initializers/bootstrap_leather.rb +9 -0
  142. data/spec/dummy/config/initializers/cookies_serializer.rb +7 -0
  143. data/spec/dummy/config/initializers/date_book.rb +5 -0
  144. data/spec/dummy/config/initializers/devise.rb +277 -0
  145. data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  146. data/spec/dummy/config/initializers/high_voltage.rb +3 -0
  147. data/spec/dummy/config/initializers/inflections.rb +17 -0
  148. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  149. data/spec/dummy/config/initializers/new_framework_defaults.rb +29 -0
  150. data/spec/dummy/config/initializers/rolify.rb +7 -0
  151. data/spec/dummy/config/initializers/session_store.rb +5 -0
  152. data/spec/dummy/config/initializers/wrap_parameters.rb +17 -0
  153. data/spec/dummy/config/locales/devise.en.yml +64 -0
  154. data/spec/dummy/config/locales/en.yml +23 -0
  155. data/spec/dummy/config/puma.rb +49 -0
  156. data/spec/dummy/config/routes.rb +15 -0
  157. data/spec/dummy/config/secrets.yml +22 -0
  158. data/spec/dummy/config/spring.rb +8 -0
  159. data/spec/dummy/db/migrate/20170728171103_create_users_table.rb +7 -0
  160. data/spec/dummy/db/migrate/20170807134122_add_devise_to_users.rb +49 -0
  161. data/spec/dummy/db/migrate/20170807134128_rolify_create_roles.rb +19 -0
  162. data/spec/dummy/db/migrate/20170807134137_create_calendars.date_book.rb +12 -0
  163. data/spec/dummy/db/migrate/20170807134138_create_events.date_book.rb +21 -0
  164. data/spec/dummy/db/migrate/20170807134139_create_schedules.date_book.rb +26 -0
  165. data/spec/dummy/db/migrate/20170807134140_add_fields_to_schedule.date_book.rb +7 -0
  166. data/spec/dummy/db/migrate/20170807134141_create_event_occurrences.date_book.rb +17 -0
  167. data/spec/dummy/db/migrate/20170807134142_add_fields_to_event_occurrences.date_book.rb +6 -0
  168. data/spec/dummy/db/schema.rb +101 -0
  169. data/spec/dummy/db/seeds.rb +0 -0
  170. data/spec/dummy/db/seeds/calendars.seeds.rb +22 -0
  171. data/spec/dummy/db/seeds/events.seeds.rb +89 -0
  172. data/spec/dummy/db/seeds/users.seeds.rb +16 -0
  173. data/spec/dummy/lib/assets/.keep +0 -0
  174. data/spec/dummy/lib/basic_benchmark.rb +9 -0
  175. data/spec/dummy/log/.keep +0 -0
  176. data/spec/factories/calendars.rb +11 -0
  177. data/spec/factories/events.rb +12 -0
  178. data/spec/factories/roles.rb +5 -0
  179. data/spec/factories/users.rb +9 -0
  180. data/spec/features/calendars_spec.rb +185 -0
  181. data/spec/features/events_spec.rb +201 -0
  182. data/spec/helpers/date_book/calendar_helper_spec.rb +17 -0
  183. data/spec/helpers/date_book/events_helper_spec.rb +17 -0
  184. data/spec/models/calendar_spec.rb +26 -0
  185. data/spec/models/event_spec.rb +67 -0
  186. data/spec/models/role_spec.rb +5 -0
  187. data/spec/rails_helper.rb +116 -0
  188. data/spec/requests/date_book/events_spec.rb +56 -0
  189. data/spec/routing/date_book/calendars_routing_spec.rb +49 -0
  190. data/spec/routing/date_book/events_routing_spec.rb +54 -0
  191. data/spec/spec_helper.rb +102 -0
  192. data/spec/support/controller_behaviors.rb +101 -0
  193. data/spec/support/controller_macros.rb +25 -0
  194. data/spec/support/factory_girl.rb +3 -0
  195. data/spec/support/feature_behaviors.rb +150 -0
  196. data/spec/support/loaded_site.rb +5 -0
  197. data/spec/support/loaded_site/calendars.rb +5 -0
  198. data/spec/support/loaded_site/events.rb +6 -0
  199. data/spec/support/loaded_site/users.rb +5 -0
  200. data/spec/support/request_behaviors.rb +89 -0
  201. data/spec/support/shared_connection.rb +14 -0
  202. data/spec/support/utilities.rb +53 -0
  203. metadata +817 -0
@@ -0,0 +1,101 @@
1
+ shared_examples_for 'a successful page' do |options = {}|
2
+ describe 'responds successfully' do
3
+ subject { response }
4
+ it { should be_success }
5
+ end
6
+ if options[:which_renders].present?
7
+ it_behaves_like 'a page rendering a template', options[:which_renders]
8
+ end
9
+ if options[:with_layout].present?
10
+ it_behaves_like 'a page rendering with a layout', options[:with_layout]
11
+ end
12
+ end
13
+ shared_examples_for 'a page rendering a template' do |template|
14
+ describe "renders the #{template} template" do
15
+ subject { response }
16
+ it { should render_template(template) }
17
+ end
18
+ end
19
+ shared_examples_for 'a page rendering with a layout' do |layout|
20
+ describe "renders the #{layout} layout" do
21
+ subject { response }
22
+ it { should render_template("layouts/#{layout}") }
23
+ end
24
+ end
25
+ shared_examples_for 'an error response' do |http_status|
26
+ describe "issues error response code #{http_status}" do
27
+ subject { response }
28
+ it { should have_http_status(http_status) }
29
+ end
30
+ end
31
+ shared_examples_for 'a redirect to' do |path|
32
+ describe "redirects to #{path}" do
33
+ subject { response }
34
+ it { should redirect_to path_to_url(path) }
35
+ end
36
+ end
37
+ shared_examples_for 'a redirect matching' do |path_expression|
38
+ describe "redirects matching #{path_expression}" do
39
+ subject { response.location }
40
+ it { should match path_expression }
41
+ end
42
+ end
43
+ shared_examples_for 'a redirect to the home page' do
44
+ it_behaves_like 'a redirect to', '/'
45
+ end
46
+ shared_examples_for 'an error response with message' do |status, message|
47
+ it_behaves_like 'an error response', status
48
+ it_behaves_like 'a page with message', :error, message
49
+ end
50
+ shared_examples_for 'a page with message' do |flash_key, error|
51
+ describe 'sets message' do
52
+ subject { flash[flash_key] }
53
+ it { should eq error }
54
+ end
55
+ end
56
+ shared_examples_for 'a page without error' do
57
+ describe 'sets no error message' do
58
+ subject { flash[:error] }
59
+ it { should be nil }
60
+ end
61
+ end
62
+ shared_examples_for 'a 403 Forbidden error' do
63
+ it_should_behave_like(
64
+ 'an error response with message',
65
+ :forbidden,
66
+ 'You are not authorized to access this page.'
67
+ )
68
+ end
69
+ shared_examples_for 'a 404 Not Found error' do
70
+ it_should_behave_like(
71
+ 'an error response with message',
72
+ :not_found,
73
+ 'The page you requested does not exist.'
74
+ )
75
+ end
76
+ shared_examples_for 'a redirect with notice' do |path, message|
77
+ it_behaves_like 'a redirect to', path
78
+ describe 'sets notice' do
79
+ subject { flash[:notice] }
80
+ it { should eq message }
81
+ end
82
+ end
83
+ shared_examples_for 'a redirect with alert' do |path, message|
84
+ it_behaves_like 'a redirect to', path
85
+ describe 'sets alert' do
86
+ subject { flash[:alert] }
87
+ it { should eq message }
88
+ end
89
+ end
90
+ shared_examples_for 'a download' do
91
+ subject { response.headers['Content-Disposition'] }
92
+ it { should include 'attachment' }
93
+ end
94
+ shared_examples_for 'a variable assignment' do |options = {}|
95
+ options.each do |key, value|
96
+ describe "@#{key}" do
97
+ subject { assigns(key) }
98
+ it { should eq value }
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,25 @@
1
+ module ControllerMacros
2
+ def login_user(user)
3
+ @request.env['devise.mapping'] = Devise.mappings[:user]
4
+ sign_in user
5
+ end
6
+ end
7
+
8
+ shared_context 'authentication for routes' do
9
+ let(:warden) do
10
+ instance_double('Warden::Proxy').tap do |warden|
11
+ allow(warden).to receive(:authenticate?).with(scope: :user)
12
+ .and_return(authenticated?)
13
+ allow(warden).to receive(:user).with(:user).and_return(user)
14
+ end
15
+ end
16
+ let(:user) { instance_double(User) }
17
+ let(:authenticated?) { true }
18
+ end
19
+
20
+ def simulate_running_with_devise
21
+ stub_const(
22
+ 'Rack::MockRequest::DEFAULT_ENV',
23
+ Rack::MockRequest::DEFAULT_ENV.merge('warden' => warden)
24
+ )
25
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure do |config|
2
+ config.include FactoryGirl::Syntax::Methods
3
+ end
@@ -0,0 +1,150 @@
1
+ shared_examples_for 'a restricted page' do
2
+ describe 'redirects to the home page' do
3
+ subject { current_path }
4
+ it { should eq '/users/sign_in' }
5
+ end
6
+ it_behaves_like(
7
+ 'a bootstrap page with an alert',
8
+ 'danger',
9
+ 'You must sign in or sign up to access this content.'
10
+ )
11
+ end
12
+
13
+ shared_examples_for 'an authentication error' do
14
+ describe 'redirects to the home page' do
15
+ subject { current_path }
16
+ it { should eq '/' }
17
+ end
18
+ it_behaves_like(
19
+ 'a bootstrap page with an alert',
20
+ 'danger',
21
+ 'You must sign in or sign up to access this content.'
22
+ )
23
+ end
24
+
25
+ shared_examples_for 'an authorization error' do
26
+ it_behaves_like(
27
+ 'a bootstrap page with an alert',
28
+ 'danger',
29
+ 'You are not authorized to access this page.'
30
+ )
31
+ end
32
+
33
+ shared_examples_for 'an admin page' do
34
+ subject { page }
35
+ it { should have_css 'body.rails_admin' }
36
+ end
37
+
38
+ shared_examples_for 'a bootstrap page' do |options = {}|
39
+ include ERB::Util
40
+ describe 'displays a page with bootstrap elements' do
41
+ subject { page }
42
+ if options[:title].present?
43
+ it { should have_title options[:title] }
44
+ it { should have_xpath '//h1', text: options[:title] }
45
+ end
46
+ it do
47
+ should have_selector(
48
+ '.navbar .navbar-header .navbar-brand',
49
+ text: BootstrapLeather.configuration.application_title
50
+ )
51
+ end
52
+ end
53
+ end
54
+
55
+ shared_examples_for 'a bootstrap page '\
56
+ 'with a dropdown navigation list' do |options|
57
+ if options[:text]
58
+ context "has a #{options[:text]} link" do
59
+ before do
60
+ click_button 'Menu'
61
+ end
62
+ it do
63
+ should(
64
+ have_selector('li.dropdown a.dropdown-toggle', text: options[:text])
65
+ )
66
+ end
67
+ end
68
+ if options[:links]
69
+ options[:links].each do |link_text|
70
+ it "has a #{link_text} link" do
71
+ click_link_or_button 'Menu'
72
+ within find('.navbar', text: options[:text]) do
73
+ click_link_or_button options[:text]
74
+ within first('li.dropdown', text: options[:text]) do
75
+ expect(page).to have_link(link_text)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ else
82
+ it { should have_selector 'li.dropdown a.dropdown-toggle' }
83
+ end
84
+ end
85
+
86
+ shared_examples_for 'a bootstrap page with an alert' do |type, text|
87
+ before do
88
+ wait_until { page.has_css? '.alert' }
89
+ end
90
+ subject { page }
91
+ it { should have_selector ".alert.alert-#{type}", text: text }
92
+ end
93
+
94
+ shared_examples_for 'a bootstrap page '\
95
+ 'listing a collection of items' do |object, options = {}|
96
+ options[:minimum] ||= 1
97
+ options[:plural_title] ||= object.model_name.human.pluralize(2).titlecase
98
+ options[:plural_name] ||= object.table_name
99
+ collection_css_class = options[:plural_name]
100
+ member_css_class = options[:plural_name].singularize
101
+ it_behaves_like 'a bootstrap page', title: options[:plural_title]
102
+ describe "displays a list of .#{collection_css_class} in "\
103
+ ".#{member_css_class}" do
104
+ subject { page }
105
+ it do
106
+ should have_css(
107
+ ".#{collection_css_class} .#{member_css_class}",
108
+ minimum: options[:minimum]
109
+ )
110
+ end
111
+ end
112
+ end
113
+
114
+ shared_examples_for 'a bootstrap page '\
115
+ 'showing an item' do |object, title, options = {}|
116
+ options[:css_class] ||= object.table_name.singularize
117
+ it_behaves_like 'a bootstrap page', title: title
118
+ describe "displays an item at .#{options[:css_class]}" do
119
+ subject { page }
120
+ it { should have_css(".#{options[:css_class]}") }
121
+ end
122
+ end
123
+
124
+ shared_examples_for 'a bootstrap page with a gallery' do |options = {}|
125
+ css = ''
126
+ test_name = 'displays a gallery'
127
+ if options[:inside]
128
+ test_name += " inside #{options[:inside]}"
129
+ css += "#{options[:inside]} "
130
+ end
131
+ css += '.gallery'
132
+ describe test_name do
133
+ subject { page }
134
+ it { should have_css(css) }
135
+ end
136
+ end
137
+
138
+ shared_examples_for 'a bootstrap form with errors' do |error_fields|
139
+ subject { page }
140
+ error_fields.each do |field|
141
+ it_behaves_like(
142
+ 'a bootstrap page with an alert',
143
+ 'danger',
144
+ "#{field.to_s.humanize} can't be blank"
145
+ )
146
+ it "shows errors on #{field}" do
147
+ expect(page.has_css?("[id$=#{field}]")).to be true
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,5 @@
1
+ shared_context 'loaded site' do
2
+ include_context 'calendars'
3
+ include_context 'events'
4
+ include_context 'users'
5
+ end
@@ -0,0 +1,5 @@
1
+ shared_context 'calendars' do
2
+ let(:regular_calendar) { Calendar.friendly.find('regular-calendar') }
3
+ let(:other_calendar) { Calendar.friendly.find('other-calendar') }
4
+ let(:admin_calendar) { Calendar.friendly.find('admin-calendar') }
5
+ end
@@ -0,0 +1,6 @@
1
+ shared_context 'events' do
2
+ let(:monday_event) { Event.friendly.find('monday') }
3
+ let(:science_fiction_club_event) { Event.friendly.find('science-fiction-club') }
4
+ let(:yesterdays_event) { Event.friendly.find('yesterday-s-event') }
5
+ let(:tomorrows_event) { Event.friendly.find('tomorrow-s-event') }
6
+ end
@@ -0,0 +1,5 @@
1
+ shared_context 'users' do
2
+ let(:admin_user) { User.find_by_name('Admin User') }
3
+ let(:regular_user) { User.find_by_name('Regular User') }
4
+ let(:other_user) { User.find_by_name('Other User') }
5
+ end
@@ -0,0 +1,89 @@
1
+ shared_examples_for 'a Json authentication error' do
2
+ it_behaves_like(
3
+ 'a json object with an error',
4
+ 'You need to sign in or sign up before continuing.'
5
+ )
6
+ end
7
+
8
+ shared_examples_for 'a Json authorization error' do
9
+ it_behaves_like(
10
+ 'a json object with an error',
11
+ 'You are not authorized to access this page.'
12
+ )
13
+ end
14
+
15
+ shared_examples_for 'a blank response' do
16
+ describe 'displays nothing' do
17
+ subject { response.body }
18
+ it { should eq '' }
19
+ end
20
+ end
21
+
22
+ shared_examples_for 'a json array' do |options = {}|
23
+ describe 'displays an array in Json' do
24
+ subject { JSON.parse(response.body) }
25
+ it { should be_an Array }
26
+ end
27
+ end
28
+
29
+ shared_examples_for 'a json object' do |options = {}|
30
+ describe 'displays an object with information about itself' do
31
+ subject { JSON.parse(response.body) }
32
+ its(['title']) { should eq options[:title] }
33
+ end
34
+ end
35
+
36
+ shared_examples_for 'a json object with a message' do |key, text|
37
+ subject { JSON.parse(response.body) }
38
+ its([key.to_s]) { should match(/#{text}/) }
39
+ end
40
+
41
+ shared_examples_for 'a json object without a message' do |key|
42
+ subject { JSON.parse(response.body) }
43
+ its([key.to_s]) { should be nil }
44
+ end
45
+
46
+ shared_examples_for 'a json object with an error' do |text|
47
+ it_behaves_like 'a json object with a message', :error, text
48
+ it_behaves_like 'a json object without a message', :info
49
+ it_behaves_like 'a json object without a message', :notice
50
+ end
51
+
52
+ shared_examples_for 'a json object with a notice' do |text|
53
+ it_behaves_like 'a json object with a message', :notice, text
54
+ it_behaves_like 'a json object without a message', :error
55
+ it_behaves_like 'a json object without a message', :info
56
+ end
57
+
58
+ shared_examples_for 'a json object with info' do |text|
59
+ it_behaves_like 'a json object with a message', :info, text
60
+ it_behaves_like 'a json object without a message', :error
61
+ it_behaves_like 'a json object without a message', :notice
62
+ end
63
+
64
+ shared_examples_for 'a json object '\
65
+ 'listing a collection of items' do |object, options = {}|
66
+ options[:minimum] ||= 1
67
+ options[:plural_name] ||= object.table_name.to_s
68
+ objects_key = options[:plural_name].to_sym
69
+ it_behaves_like 'a json array'
70
+ describe "displays a list of #{objects_key}" do
71
+ subject { JSON.parse(response.body) }
72
+ its(:count) { should >= options[:minimum] }
73
+ end
74
+ end
75
+
76
+ shared_examples_for 'a json object '\
77
+ 'showing an item' do |object, title, options = {}|
78
+ describe "displays an item" do
79
+ subject { JSON.parse(response.body) }
80
+ its(['title']) { should eq title }
81
+ end
82
+ end
83
+
84
+ shared_examples_for 'a json object with errors' do |error_fields|
85
+ subject { JSON.parse(response.body)[:errors] }
86
+ error_fields.each do |field|
87
+ its([field.to_s]) { should eq "#{field.to_s.humanize} can't be blank" }
88
+ end
89
+ end
@@ -0,0 +1,14 @@
1
+ module ActiveRecord
2
+ class Base
3
+ mattr_accessor :shared_connection
4
+ @@shared_connection = nil
5
+
6
+ def self.connection
7
+ @@shared_connection || retrieve_connection
8
+ end
9
+ end
10
+ end
11
+
12
+ # Forces all threads to share the same connection. This works on
13
+ # Capybara because it starts the web server in a thread.
14
+ ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
@@ -0,0 +1,53 @@
1
+ def path_to_url(path)
2
+ protocol = request.protocol
3
+ host = request.host_with_port.sub(/:80$/, '')
4
+ stripped_path = path.sub(%r{^/}, '')
5
+ "#{protocol}#{host}/#{stripped_path}"
6
+ end
7
+
8
+ def show_page
9
+ save_page Rails.root.join('public', 'capybara.html')
10
+ # This runs launchy as a system command
11
+ `launchy http://localhost:3000/capybara.html`
12
+ end
13
+
14
+ def wait_until(delay = 1)
15
+ seconds_waited = 0
16
+ while !yield && seconds_waited < Capybara.default_max_wait_time
17
+ sleep delay
18
+ seconds_waited += 1
19
+ end
20
+ unless yield
21
+ puts "Waited for #{Capybara.default_max_wait_time} seconds."
22
+ puts "{#{yield}} did not become true, continuing."
23
+ end
24
+ end
25
+
26
+ def submit_via_execute(form_selector)
27
+ page.execute_script("$('#{form_selector}').submit();")
28
+ end
29
+
30
+ def click_on_body
31
+ page.execute_script("$('body').click();")
32
+ end
33
+
34
+ # Used to fill wysiwig fields
35
+ # @param [String] locator label text for the textarea or textarea id
36
+ def fill_in_wysiwyg(locator, text)
37
+ include ActionView::Helpers::JavaScriptHelper
38
+ locator = find_field_by_label(locator)
39
+ text = text.gsub("'", "\'").gsub("\n", '\\\n')
40
+
41
+ # Fill the editor content
42
+ page.execute_script <<-SCRIPT
43
+ $('##{locator}').data('wysihtml5').editor.setValue('#{text}');
44
+ SCRIPT
45
+ end
46
+
47
+ def find_field_by_label(locator)
48
+ if page.has_css?('label', text: locator)
49
+ find('label', text: locator)[:for]
50
+ else
51
+ locator
52
+ end
53
+ end