decidim-dev 0.0.6

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 (52) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +24 -0
  3. data/Rakefile +2 -0
  4. data/app/views/decidim/dummy_resource/_linked_dummys.html.erb +5 -0
  5. data/config/i18n-tasks.yml +4 -0
  6. data/config/locales/ca.yml +5 -0
  7. data/config/locales/en.yml +5 -0
  8. data/config/locales/es.yml +5 -0
  9. data/config/locales/eu.yml +5 -0
  10. data/config/locales/fi.yml +5 -0
  11. data/lib/decidim/dev.rb +22 -0
  12. data/lib/decidim/dev/assets/Exampledocument.docx +0 -0
  13. data/lib/decidim/dev/assets/Exampledocument.odt +0 -0
  14. data/lib/decidim/dev/assets/Exampledocument.pdf +0 -0
  15. data/lib/decidim/dev/assets/avatar.jpg +0 -0
  16. data/lib/decidim/dev/assets/city.jpeg +0 -0
  17. data/lib/decidim/dev/assets/city2.jpeg +0 -0
  18. data/lib/decidim/dev/assets/city3.jpeg +0 -0
  19. data/lib/decidim/dev/assets/icon.png +0 -0
  20. data/lib/decidim/dev/assets/malicious.jpg +0 -0
  21. data/lib/decidim/dev/common_rake.rb +28 -0
  22. data/lib/decidim/dev/dummy_authorization_handler.rb +26 -0
  23. data/lib/decidim/dev/test/authorization_shared_examples.rb +23 -0
  24. data/lib/decidim/dev/test/base_spec_helper.rb +48 -0
  25. data/lib/decidim/dev/test/i18n_spec.rb +34 -0
  26. data/lib/decidim/dev/test/rspec_support/action_mailer.rb +72 -0
  27. data/lib/decidim/dev/test/rspec_support/active_job.rb +11 -0
  28. data/lib/decidim/dev/test/rspec_support/authenticated_controller_context.rb +9 -0
  29. data/lib/decidim/dev/test/rspec_support/authorization_handlers.rb +7 -0
  30. data/lib/decidim/dev/test/rspec_support/capybara.rb +73 -0
  31. data/lib/decidim/dev/test/rspec_support/database_cleaner.rb +13 -0
  32. data/lib/decidim/dev/test/rspec_support/engine_routes.rb +34 -0
  33. data/lib/decidim/dev/test/rspec_support/factory_girl.rb +4 -0
  34. data/lib/decidim/dev/test/rspec_support/feature.rb +91 -0
  35. data/lib/decidim/dev/test/rspec_support/feature_context.rb +44 -0
  36. data/lib/decidim/dev/test/rspec_support/geocoder.rb +11 -0
  37. data/lib/decidim/dev/test/rspec_support/helpers.rb +46 -0
  38. data/lib/decidim/dev/test/rspec_support/html_matchers.rb +6 -0
  39. data/lib/decidim/dev/test/rspec_support/i18n.rb +15 -0
  40. data/lib/decidim/dev/test/rspec_support/phantomjs_polyfills/bind-polyfill.js +18 -0
  41. data/lib/decidim/dev/test/rspec_support/phantomjs_polyfills/object-assign-polyfill.js +24 -0
  42. data/lib/decidim/dev/test/rspec_support/phantomjs_polyfills/promise.js +233 -0
  43. data/lib/decidim/dev/test/rspec_support/translation_helpers.rb +75 -0
  44. data/lib/decidim/dev/test/rspec_support/warden.rb +9 -0
  45. data/lib/decidim/dev/test/rspec_support/webmock.rb +2 -0
  46. data/lib/decidim/dev/test/rspec_support/wisper.rb +6 -0
  47. data/lib/decidim/dev/test/spec_helper.rb +37 -0
  48. data/lib/generators/decidim/dummy_generator.rb +80 -0
  49. data/lib/generators/decidim/templates/autoprefixer.yml +8 -0
  50. data/lib/generators/decidim/templates/autoprefixer_initializer.rb +16 -0
  51. data/lib/generators/decidim/templates/decidim_dev.rb +2 -0
  52. metadata +406 -0
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ RSpec.configure do |config|
3
+ config.before(:suite) do
4
+ DatabaseCleaner.strategy = :truncation
5
+ DatabaseCleaner.clean_with :truncation
6
+ end
7
+
8
+ config.around(:each) do |example|
9
+ DatabaseCleaner.cleaning do
10
+ example.run
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ # This is a quick hack so all controller specs have their engine's routes
4
+ # included as well as our Devise mapping.
5
+ module ControllerRequests
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ begin
10
+ engine = (ENV["ENGINE_NAME"].to_s.split("-").map(&:capitalize).join("::") + "::Engine").constantize
11
+
12
+ load_routes engine if engine.respond_to?(:routes)
13
+ rescue NameError => _exception
14
+ puts "Failed to automatically inject routes for engine #{ENV["ENGINE_NAME"]}"
15
+ end
16
+ end
17
+
18
+ class_methods do
19
+ def load_routes(klass)
20
+ routes do
21
+ klass.routes
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ RSpec.configure do |config|
29
+ config.include Decidim::ControllerRequests, type: :controller
30
+
31
+ config.before :each, type: :controller do
32
+ @request.env["devise.mapping"] = Devise.mappings[:user]
33
+ end
34
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ RSpec.configure do |config|
3
+ config.include FactoryGirl::Syntax::Methods
4
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/feature_validator"
4
+ require "decidim/comments"
5
+
6
+ module Decidim
7
+ # Dummy engine to be able to test components.
8
+ class DummyEngine < Rails::Engine
9
+ engine_name "dummy"
10
+
11
+ routes do
12
+ root to: proc { [200, {}, ["DUMMY ENGINE"]] }
13
+ resources :dummy_resources, controller: "decidim/dummy_resources"
14
+ end
15
+ end
16
+
17
+ class DummyResource < ActiveRecord::Base
18
+ include HasFeature
19
+ include Resourceable
20
+ include Reportable
21
+ include Authorable
22
+ include Decidim::Comments::Commentable
23
+
24
+ feature_manifest_name "dummy"
25
+
26
+ def reported_content
27
+ title
28
+ end
29
+ end
30
+
31
+ class DummyResourcesController < ActionController::Base
32
+ helper Decidim::Comments::CommentsHelper
33
+ skip_authorization_check
34
+
35
+ def show
36
+ @commentable = DummyResource.find(params[:id])
37
+ render inline: %{
38
+ <%= display_flash_messages %>
39
+ <div class="reveal" id="loginModal" data-reveal></div>
40
+ <%= javascript_include_tag 'application' %>
41
+ <%= inline_comments_for(@commentable) %>
42
+ }
43
+ end
44
+ end
45
+ end
46
+
47
+ Decidim.register_feature(:dummy) do |feature|
48
+ feature.engine = Decidim::DummyEngine
49
+
50
+ feature.actions = %w(foo bar)
51
+
52
+ feature.settings(:global) do |settings|
53
+ settings.attribute :comments_enabled, type: :boolean, default: true
54
+ settings.attribute :dummy_global_attribute_1, type: :boolean
55
+ settings.attribute :dummy_global_attribute_2, type: :boolean
56
+ end
57
+
58
+ feature.settings(:step) do |settings|
59
+ settings.attribute :comments_blocked, type: :boolean, default: false
60
+ settings.attribute :dummy_step_attribute_1, type: :boolean
61
+ settings.attribute :dummy_step_attribute_2, type: :boolean
62
+ end
63
+
64
+ feature.register_resource do |resource|
65
+ resource.name = :dummy
66
+ resource.model_class_name = "Decidim::DummyResource"
67
+ resource.template = "decidim/dummy_resource/linked_dummys"
68
+ end
69
+ end
70
+
71
+ RSpec.configure do |config|
72
+ config.before(:suite) do
73
+ unless ActiveRecord::Base.connection.data_source_exists?("decidim_dummy_resources")
74
+ ActiveRecord::Migration.create_table :decidim_dummy_resources do |t|
75
+ t.string :title
76
+ t.text :address
77
+ t.float :latitude
78
+ t.float :longitude
79
+
80
+ t.references :decidim_feature, index: true
81
+ t.references :decidim_author, index: true
82
+
83
+ t.timestamps
84
+ end
85
+ end
86
+ end
87
+
88
+ config.before(:each) do
89
+ Decidim.find_feature_manifest(:dummy).reset_hooks!
90
+ end
91
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+ RSpec.shared_context "feature" do
3
+ let!(:manifest_name) { raise NotImplementedError }
4
+ let(:manifest) { Decidim.find_feature_manifest(manifest_name) }
5
+
6
+ let!(:organization) { create(:organization) }
7
+
8
+ let(:participatory_process) do
9
+ create(:participatory_process, :with_steps, organization: organization)
10
+ end
11
+
12
+ let!(:feature) do
13
+ create(:feature,
14
+ manifest: manifest,
15
+ participatory_process: participatory_process)
16
+ end
17
+
18
+ before do
19
+ switch_to_host(organization.host)
20
+ end
21
+
22
+ def visit_feature
23
+ page.visit decidim.feature_path(participatory_process, feature)
24
+ end
25
+ end
26
+
27
+ RSpec.shared_context "feature admin" do
28
+ include_context "feature"
29
+ let(:user) { create(:user, :confirmed, organization: organization) }
30
+
31
+ before do
32
+ Decidim::Admin::ParticipatoryProcessUserRole.create!(
33
+ role: :admin,
34
+ user: user,
35
+ participatory_process: participatory_process
36
+ )
37
+
38
+ login_as user, scope: :user
39
+ end
40
+
41
+ def visit_feature_admin
42
+ visit decidim_admin.manage_feature_path(participatory_process, feature)
43
+ end
44
+ end
@@ -0,0 +1,11 @@
1
+ RSpec.configure do |config|
2
+ config.before(:each) do
3
+ # Set geocoder configuration in test mode
4
+ Decidim.geocoder = {
5
+ static_map_url: "http://www.example.org",
6
+ here_app_id: '1234',
7
+ here_app_code: '5678'
8
+ }
9
+ Geocoder.configure(lookup: :test)
10
+ end
11
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Helpers that get automatically included in feature specs.
4
+ module Decidim::FeatureTestHelpers
5
+ def within_user_menu
6
+ within ".topbar__user__logged" do
7
+ find("a", text: user.name).hover
8
+ yield
9
+ end
10
+ end
11
+
12
+ def within_language_menu
13
+ within ".topbar__dropmenu.language-choose" do
14
+ find("ul.dropdown.menu").hover
15
+ yield
16
+ end
17
+ end
18
+
19
+ def click_icon(name = nil)
20
+ classes = ["icon"]
21
+ classes << ["icon--#{name}"] if name
22
+ find(".#{classes.join(".")}").click
23
+ end
24
+
25
+ def stripped(text)
26
+ Nokogiri::HTML(text).text
27
+ end
28
+
29
+ def within_flash_messages
30
+ within ".flash.callout" do
31
+ yield
32
+ end
33
+ end
34
+
35
+ def expect_user_logged
36
+ expect(page).to have_css(".topbar__user__logged")
37
+ end
38
+ end
39
+
40
+ def stripped(text)
41
+ Nokogiri::HTML(text).text
42
+ end
43
+
44
+ RSpec.configure do |config|
45
+ config.include Decidim::FeatureTestHelpers, type: :feature
46
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ require "rspec-html-matchers"
3
+
4
+ RSpec.configure do |config|
5
+ config.include RSpecHtmlMatchers
6
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ RSpec.configure do |config|
3
+ config.before(:suite) do
4
+ I18n.config.enforce_available_locales = false
5
+ end
6
+
7
+ config.around(:each) do |example|
8
+ I18n.available_locales = %w{en ca es}
9
+ Decidim.available_locales = %w{en ca es}
10
+
11
+ previous_locale = I18n.locale
12
+ example.run
13
+ I18n.locale = previous_locale
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ if (typeof Function.prototype.bind != 'function') {
2
+ Function.prototype.bind = function bind(obj) {
3
+ var args = Array.prototype.slice.call(arguments, 1),
4
+ self = this,
5
+ nop = function() {
6
+ },
7
+ bound = function() {
8
+ return self.apply(
9
+ this instanceof nop ? this : (obj || {}), args.concat(
10
+ Array.prototype.slice.call(arguments)
11
+ )
12
+ );
13
+ };
14
+ nop.prototype = this.prototype || {};
15
+ bound.prototype = new nop();
16
+ return bound;
17
+ };
18
+ }
@@ -0,0 +1,24 @@
1
+ //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill
2
+ if (typeof Object.assign != 'function') {
3
+ (function () {
4
+ Object.assign = function (target) {
5
+ 'use strict';
6
+ if (target === undefined || target === null) {
7
+ throw new TypeError('Cannot convert undefined or null to object');
8
+ }
9
+
10
+ var output = Object(target);
11
+ for (var index = 1; index < arguments.length; index++) {
12
+ var source = arguments[index];
13
+ if (source !== undefined && source !== null) {
14
+ for (var nextKey in source) {
15
+ if (source.hasOwnProperty(nextKey)) {
16
+ output[nextKey] = source[nextKey];
17
+ }
18
+ }
19
+ }
20
+ }
21
+ return output;
22
+ };
23
+ })();
24
+ }
@@ -0,0 +1,233 @@
1
+ (function (root) {
2
+
3
+ // Store setTimeout reference so promise-polyfill will be unaffected by
4
+ // other code modifying setTimeout (like sinon.useFakeTimers())
5
+ var setTimeoutFunc = setTimeout;
6
+
7
+ function noop() {}
8
+
9
+ // Polyfill for Function.prototype.bind
10
+ function bind(fn, thisArg) {
11
+ return function () {
12
+ fn.apply(thisArg, arguments);
13
+ };
14
+ }
15
+
16
+ function Promise(fn) {
17
+ if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
18
+ if (typeof fn !== 'function') throw new TypeError('not a function');
19
+ this._state = 0;
20
+ this._handled = false;
21
+ this._value = undefined;
22
+ this._deferreds = [];
23
+
24
+ doResolve(fn, this);
25
+ }
26
+
27
+ function handle(self, deferred) {
28
+ while (self._state === 3) {
29
+ self = self._value;
30
+ }
31
+ if (self._state === 0) {
32
+ self._deferreds.push(deferred);
33
+ return;
34
+ }
35
+ self._handled = true;
36
+ Promise._immediateFn(function () {
37
+ var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
38
+ if (cb === null) {
39
+ (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
40
+ return;
41
+ }
42
+ var ret;
43
+ try {
44
+ ret = cb(self._value);
45
+ } catch (e) {
46
+ reject(deferred.promise, e);
47
+ return;
48
+ }
49
+ resolve(deferred.promise, ret);
50
+ });
51
+ }
52
+
53
+ function resolve(self, newValue) {
54
+ try {
55
+ // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
56
+ if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.');
57
+ if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
58
+ var then = newValue.then;
59
+ if (newValue instanceof Promise) {
60
+ self._state = 3;
61
+ self._value = newValue;
62
+ finale(self);
63
+ return;
64
+ } else if (typeof then === 'function') {
65
+ doResolve(bind(then, newValue), self);
66
+ return;
67
+ }
68
+ }
69
+ self._state = 1;
70
+ self._value = newValue;
71
+ finale(self);
72
+ } catch (e) {
73
+ reject(self, e);
74
+ }
75
+ }
76
+
77
+ function reject(self, newValue) {
78
+ self._state = 2;
79
+ self._value = newValue;
80
+ finale(self);
81
+ }
82
+
83
+ function finale(self) {
84
+ if (self._state === 2 && self._deferreds.length === 0) {
85
+ Promise._immediateFn(function() {
86
+ if (!self._handled) {
87
+ Promise._unhandledRejectionFn(self._value);
88
+ }
89
+ });
90
+ }
91
+
92
+ for (var i = 0, len = self._deferreds.length; i < len; i++) {
93
+ handle(self, self._deferreds[i]);
94
+ }
95
+ self._deferreds = null;
96
+ }
97
+
98
+ function Handler(onFulfilled, onRejected, promise) {
99
+ this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
100
+ this.onRejected = typeof onRejected === 'function' ? onRejected : null;
101
+ this.promise = promise;
102
+ }
103
+
104
+ /**
105
+ * Take a potentially misbehaving resolver function and make sure
106
+ * onFulfilled and onRejected are only called once.
107
+ *
108
+ * Makes no guarantees about asynchrony.
109
+ */
110
+ function doResolve(fn, self) {
111
+ var done = false;
112
+ try {
113
+ fn(function (value) {
114
+ if (done) return;
115
+ done = true;
116
+ resolve(self, value);
117
+ }, function (reason) {
118
+ if (done) return;
119
+ done = true;
120
+ reject(self, reason);
121
+ });
122
+ } catch (ex) {
123
+ if (done) return;
124
+ done = true;
125
+ reject(self, ex);
126
+ }
127
+ }
128
+
129
+ Promise.prototype['catch'] = function (onRejected) {
130
+ return this.then(null, onRejected);
131
+ };
132
+
133
+ Promise.prototype.then = function (onFulfilled, onRejected) {
134
+ var prom = new (this.constructor)(noop);
135
+
136
+ handle(this, new Handler(onFulfilled, onRejected, prom));
137
+ return prom;
138
+ };
139
+
140
+ Promise.all = function (arr) {
141
+ var args = Array.prototype.slice.call(arr);
142
+
143
+ return new Promise(function (resolve, reject) {
144
+ if (args.length === 0) return resolve([]);
145
+ var remaining = args.length;
146
+
147
+ function res(i, val) {
148
+ try {
149
+ if (val && (typeof val === 'object' || typeof val === 'function')) {
150
+ var then = val.then;
151
+ if (typeof then === 'function') {
152
+ then.call(val, function (val) {
153
+ res(i, val);
154
+ }, reject);
155
+ return;
156
+ }
157
+ }
158
+ args[i] = val;
159
+ if (--remaining === 0) {
160
+ resolve(args);
161
+ }
162
+ } catch (ex) {
163
+ reject(ex);
164
+ }
165
+ }
166
+
167
+ for (var i = 0; i < args.length; i++) {
168
+ res(i, args[i]);
169
+ }
170
+ });
171
+ };
172
+
173
+ Promise.resolve = function (value) {
174
+ if (value && typeof value === 'object' && value.constructor === Promise) {
175
+ return value;
176
+ }
177
+
178
+ return new Promise(function (resolve) {
179
+ resolve(value);
180
+ });
181
+ };
182
+
183
+ Promise.reject = function (value) {
184
+ return new Promise(function (resolve, reject) {
185
+ reject(value);
186
+ });
187
+ };
188
+
189
+ Promise.race = function (values) {
190
+ return new Promise(function (resolve, reject) {
191
+ for (var i = 0, len = values.length; i < len; i++) {
192
+ values[i].then(resolve, reject);
193
+ }
194
+ });
195
+ };
196
+
197
+ // Use polyfill for setImmediate for performance gains
198
+ Promise._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) ||
199
+ function (fn) {
200
+ setTimeoutFunc(fn, 0);
201
+ };
202
+
203
+ Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
204
+ if (typeof console !== 'undefined' && console) {
205
+ console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
206
+ }
207
+ };
208
+
209
+ /**
210
+ * Set the immediate function to execute callbacks
211
+ * @param fn {function} Function to execute
212
+ * @deprecated
213
+ */
214
+ Promise._setImmediateFn = function _setImmediateFn(fn) {
215
+ Promise._immediateFn = fn;
216
+ };
217
+
218
+ /**
219
+ * Change the function to execute on unhandled rejection
220
+ * @param {function} fn Function to execute on unhandled rejection
221
+ * @deprecated
222
+ */
223
+ Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
224
+ Promise._unhandledRejectionFn = fn;
225
+ };
226
+
227
+ if (typeof module !== 'undefined' && module.exports) {
228
+ module.exports = Promise;
229
+ } else if (!root.Promise) {
230
+ root.Promise = Promise;
231
+ }
232
+
233
+ })(this);