Merge branch 'master' into user-recomendations
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -32,6 +32,3 @@
|
||||
|
||||
public/sitemap.xml
|
||||
public/system/
|
||||
|
||||
#Netbeans projects files
|
||||
/nbproject
|
||||
|
||||
@@ -8,6 +8,7 @@ before_script:
|
||||
- "for i in config/*.example; do cp \"$i\" \"${i/.example}\"; done"
|
||||
- bundle exec rake db:setup
|
||||
script:
|
||||
- "bundle exec rake assets:precompile RAILS_ENV=test"
|
||||
- "bundle exec rake knapsack:rspec"
|
||||
env:
|
||||
global:
|
||||
|
||||
2
Gemfile
2
Gemfile
@@ -24,6 +24,7 @@ gem 'graphql', '~> 1.6.3'
|
||||
gem 'groupdate', '~> 3.2.0'
|
||||
gem 'initialjs-rails', '~> 0.2.0.5'
|
||||
gem 'invisible_captcha', '~> 0.9.2'
|
||||
gem 'jquery-fileupload-rails'
|
||||
gem 'jquery-rails', '~> 4.3.1'
|
||||
gem 'jquery-ui-rails', '~> 6.0.1'
|
||||
gem 'kaminari', '~> 1.0.1'
|
||||
@@ -33,7 +34,6 @@ gem 'omniauth-facebook', '~> 4.0.0'
|
||||
gem 'omniauth-google-oauth2', '~> 0.4.0'
|
||||
gem 'omniauth-twitter', '~> 1.4.0'
|
||||
gem 'paperclip', '~> 5.1.0'
|
||||
gem 'jquery-fileupload-rails'
|
||||
gem 'paranoia', '~> 2.3.1'
|
||||
gem 'pg', '~> 0.21.0'
|
||||
gem 'pg_search', '~> 2.0.1'
|
||||
|
||||
@@ -32,22 +32,30 @@
|
||||
padding: 0;
|
||||
z-index: 4 !important;
|
||||
|
||||
.ui-datepicker-prev {
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
.ui-datepicker-next {
|
||||
right: 12px;
|
||||
}
|
||||
|
||||
.ui-datepicker-prev,
|
||||
.ui-datepicker-next {
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
font-family: "icons" !important;
|
||||
font-size: rem-calc(24);
|
||||
font-weight: normal;
|
||||
font-size: $small-font-size;
|
||||
height: rem-calc(30);
|
||||
line-height: $line-height;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
width: rem-calc(30);
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-datepicker-prev::after {
|
||||
content: '\62';
|
||||
}
|
||||
|
||||
.ui-datepicker-next::after {
|
||||
content: '\63';
|
||||
}
|
||||
|
||||
table {
|
||||
|
||||
@@ -395,8 +395,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.tags,
|
||||
&.geozone {
|
||||
.tags,
|
||||
.geozone {
|
||||
|
||||
li {
|
||||
margin-bottom: 0;
|
||||
@@ -478,6 +478,7 @@
|
||||
|
||||
.tags {
|
||||
display: block;
|
||||
margin-bottom: 0;
|
||||
|
||||
a {
|
||||
margin-right: rem-calc(6);
|
||||
@@ -610,6 +611,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.show-actions-menu {
|
||||
|
||||
[class^="icon-"] {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
// 04. List participation
|
||||
// ----------------------
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Admin::Poll::ShiftsController < Admin::BaseController
|
||||
|
||||
|
||||
before_action :load_booth
|
||||
before_action :load_polls
|
||||
before_action :load_officer
|
||||
|
||||
@@ -7,7 +7,7 @@ class CommunitiesController < ApplicationController
|
||||
skip_authorization_check
|
||||
|
||||
def show
|
||||
redirect_to root_path unless Setting['feature.community'].present?
|
||||
redirect_to root_path if Setting['feature.community'].blank?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
class DocumentsController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
before_filter :find_documentable, except: :destroy
|
||||
before_filter :prepare_new_document, only: [:new, :new_nested]
|
||||
before_filter :prepare_document_for_creation, only: :create
|
||||
before_action :find_documentable, except: :destroy
|
||||
before_action :prepare_new_document, only: [:new, :new_nested]
|
||||
before_action :prepare_document_for_creation, only: :create
|
||||
|
||||
load_and_authorize_resource except: :upload
|
||||
skip_authorization_check only: :upload
|
||||
@@ -48,6 +48,7 @@ class DocumentsController < ApplicationController
|
||||
def destroy_upload
|
||||
@document = Document.new(cached_attachment: params[:path])
|
||||
@document.set_attachment_from_cached_attachment
|
||||
@document.cached_attachment = nil
|
||||
@document.documentable = @documentable
|
||||
|
||||
if @document.attachment.destroy
|
||||
|
||||
@@ -7,7 +7,7 @@ class Officing::PollsController < Officing::BaseController
|
||||
|
||||
def final
|
||||
@polls = if current_user.poll_officer?
|
||||
current_user.poll_officer.final_days_assigned_polls.select {|poll| poll.ends_at > 1.week.ago && poll.expired?}
|
||||
current_user.poll_officer.final_days_assigned_polls.select {|poll| poll.ends_at > 2.week.ago && poll.expired?}
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
@@ -78,7 +78,7 @@ class ProposalsController < ApplicationController
|
||||
def proposal_params
|
||||
params.require(:proposal).permit(:title, :question, :summary, :description, :external_url, :video_url,
|
||||
:responsible_name, :tag_list, :terms_of_service, :geozone_id,
|
||||
documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id] )
|
||||
documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id])
|
||||
end
|
||||
|
||||
def retired_params
|
||||
|
||||
@@ -36,6 +36,10 @@ module AdminHelper
|
||||
["banners"].include? controller_name
|
||||
end
|
||||
|
||||
def menu_customization?
|
||||
["pages", "images", "content_blocks"].include? controller_name
|
||||
end
|
||||
|
||||
def official_level_options
|
||||
options = [["", 0]]
|
||||
(1..5).each do |i|
|
||||
|
||||
@@ -12,7 +12,7 @@ module CommunitiesHelper
|
||||
community.from_proposal? ? t("community.show.description.proposal") : t("community.show.description.investment")
|
||||
end
|
||||
|
||||
def is_author?(community, participant)
|
||||
def author?(community, participant)
|
||||
if community.from_proposal?
|
||||
community.proposal.author_id == participant.id
|
||||
else
|
||||
|
||||
@@ -9,7 +9,7 @@ module DocumentablesHelper
|
||||
end
|
||||
|
||||
def max_file_size(documentable)
|
||||
bytesToMeg(documentable.class.max_file_size)
|
||||
bytes_to_mega(documentable.class.max_file_size)
|
||||
end
|
||||
|
||||
def accepted_content_types(documentable)
|
||||
@@ -18,8 +18,8 @@ module DocumentablesHelper
|
||||
|
||||
def accepted_content_types_extensions(documentable_class)
|
||||
documentable_class.accepted_content_types
|
||||
.collect{ |content_type| ".#{content_type.split("/").last}" }
|
||||
.join(",")
|
||||
.collect{ |content_type| ".#{content_type.split('/').last}" }
|
||||
.join(",")
|
||||
end
|
||||
|
||||
def humanized_accepted_content_types(documentable)
|
||||
@@ -38,4 +38,4 @@ module DocumentablesHelper
|
||||
documentable.documents.count >= documentable.class.max_documents_allowed
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ module DocumentsHelper
|
||||
document.errors[:attachment].join(', ') if document.errors.key?(:attachment)
|
||||
end
|
||||
|
||||
def bytesToMeg(bytes)
|
||||
def bytes_to_mega(bytes)
|
||||
bytes / Numeric::MEGABYTE
|
||||
end
|
||||
|
||||
@@ -80,10 +80,10 @@ module DocumentsHelper
|
||||
|
||||
def document_direct_upload_url(document)
|
||||
upload_documents_url(
|
||||
documentable_type: document.documentable_type,
|
||||
documentable_id: document.documentable_id,
|
||||
format: :js
|
||||
)
|
||||
documentable_type: document.documentable_type,
|
||||
documentable_id: document.documentable_id,
|
||||
format: :js
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -40,4 +40,17 @@ module ProposalsHelper
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def can_create_document?(document, proposal)
|
||||
can?(:create, document) && proposal.documents.size < Proposal.max_documents_allowed
|
||||
end
|
||||
|
||||
def author_of_proposal?(proposal)
|
||||
author_of?(proposal, current_user)
|
||||
end
|
||||
|
||||
def current_editable?(proposal)
|
||||
current_user && proposal.editable_by?(current_user)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@ class Community < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def from_proposal?
|
||||
self.proposal.present?
|
||||
proposal.present?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -10,7 +10,7 @@ module Documentable
|
||||
|
||||
private
|
||||
|
||||
def documentable(options= {})
|
||||
def documentable(options = {})
|
||||
@max_documents_allowed = options[:max_documents_allowed]
|
||||
@max_file_size = options[:max_file_size]
|
||||
@accepted_content_types = options[:accepted_content_types]
|
||||
|
||||
@@ -40,7 +40,7 @@ class Document < ActiveRecord::Base
|
||||
attachment.instance.prefix(attachment, style)
|
||||
end
|
||||
|
||||
def prefix(attachment, style)
|
||||
def prefix(attachment, _style)
|
||||
if !attachment.instance.persisted?
|
||||
"cached_attachments/user/#{attachment.instance.user_id}"
|
||||
else
|
||||
@@ -75,7 +75,7 @@ class Document < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def remove_cached_document
|
||||
File.delete(cached_attachment) if File.exists?(cached_attachment)
|
||||
File.delete(cached_attachment) if File.exist?(cached_attachment)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ class Poll
|
||||
has_many :shifts
|
||||
|
||||
validates :name, presence: true, uniqueness: true
|
||||
|
||||
|
||||
def self.search(terms)
|
||||
return Booth.none if terms.blank?
|
||||
Booth.where("name ILIKE ? OR location ILIKE ?", "%#{terms}%", "%#{terms}%")
|
||||
|
||||
@@ -20,6 +20,7 @@ class Poll::Question < ActiveRecord::Base
|
||||
|
||||
validates :title, presence: true
|
||||
validates :author, presence: true
|
||||
validates :poll_id, presence: true
|
||||
|
||||
validates :title, length: { minimum: 4 }
|
||||
validates :description, length: { maximum: Poll::Question.description_max_length }
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
class Poll
|
||||
class Shift < ActiveRecord::Base
|
||||
belongs_to :booth
|
||||
belongs_to :officer
|
||||
belongs_to :booth
|
||||
belongs_to :officer
|
||||
|
||||
validates :booth_id, presence: true
|
||||
validates :officer_id, presence: true
|
||||
validates :date, presence: true
|
||||
validates :date, uniqueness: { scope: [:officer_id, :booth_id] }
|
||||
|
||||
|
||||
before_create :persist_data
|
||||
after_create :create_officer_assignments
|
||||
|
||||
@@ -20,10 +20,10 @@ class Poll
|
||||
end
|
||||
end
|
||||
|
||||
def persist_data
|
||||
def persist_data
|
||||
self.officer_name = officer.name
|
||||
self.officer_email = officer.email
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,6 +13,6 @@ class Topic < ActiveRecord::Base
|
||||
|
||||
scope :sort_by_newest, -> { order(created_at: :desc) }
|
||||
scope :sort_by_oldest, -> { order(created_at: :asc) }
|
||||
scope :sort_by_most_commented, -> { reorder(comments_count: :desc) }
|
||||
scope :sort_by_most_commented, -> { reorder(comments_count: :desc) }
|
||||
|
||||
end
|
||||
|
||||
@@ -57,13 +57,13 @@ class User < ActiveRecord::Base
|
||||
scope :officials, -> { where("official_level > 0") }
|
||||
scope :newsletter, -> { where(newsletter: true) }
|
||||
scope :for_render, -> { includes(:organization) }
|
||||
scope :by_document, -> (document_type, document_number) { where(document_type: document_type, document_number: document_number) }
|
||||
scope :by_document, ->(document_type, document_number) { where(document_type: document_type, document_number: document_number) }
|
||||
scope :email_digest, -> { where(email_digest: true) }
|
||||
scope :active, -> { where(erased_at: nil) }
|
||||
scope :erased, -> { where.not(erased_at: nil) }
|
||||
scope :public_for_api, -> { all }
|
||||
scope :by_comments, -> (query, topics_ids) { joins(:comments).where(query, topics_ids).uniq }
|
||||
scope :by_authors, -> (author_ids) { where("users.id IN (?)", author_ids) }
|
||||
scope :by_comments, ->(query, topics_ids) { joins(:comments).where(query, topics_ids).uniq }
|
||||
scope :by_authors, ->(author_ids) { where("users.id IN (?)", author_ids) }
|
||||
|
||||
before_validation :clean_document_number
|
||||
|
||||
|
||||
@@ -60,12 +60,12 @@
|
||||
<span class="icon-checkmark-circle"></span>
|
||||
<strong><%= t("admin.menu.title_polls") %></strong>
|
||||
</a>
|
||||
<ul id="polls_menu" <%= "class=is-active" if menu_polls? %>>
|
||||
<li <%= "class=active" if ["polls", "officer_assignments", "booth_assignments", "recounts", "results"].include? controller_name %>>
|
||||
<ul id="polls_menu" <%= "class=is-active" if menu_polls? && controller.class.parent == Admin::Poll::QuestionsController %>>
|
||||
<li <%= "class=active" if ["polls", "officer_assignments", "booth_assignments", "recounts", "results"].include? controller_name %>>
|
||||
<%= link_to t('admin.menu.polls'), admin_polls_path %>
|
||||
</li>
|
||||
|
||||
<li <%= "class=active" if controller_name == "questions" %>>
|
||||
<li <%= "class=active" if controller_name == "questions" && controller.class.parent == Admin::Poll::QuestionsController %>>
|
||||
<%= link_to t("admin.menu.poll_questions"), admin_questions_path %>
|
||||
</li>
|
||||
|
||||
@@ -73,13 +73,13 @@
|
||||
<%= link_to t('admin.menu.poll_officers'), admin_officers_path %>
|
||||
</li>
|
||||
|
||||
<li <%= "class=active" if controller_name == "booths" &&
|
||||
<li <%= "class=active" if controller_name == "booths" &&
|
||||
action_name != "available" %>>
|
||||
<%= link_to t('admin.menu.poll_booths'), admin_booths_path %>
|
||||
</li>
|
||||
|
||||
<li <%= "class=active" if controller_name == "shifts" ||
|
||||
controller_name == "booths" &&
|
||||
<li <%= "class=active" if controller_name == "shifts" ||
|
||||
controller_name == "booths" &&
|
||||
action_name == "available" %>>
|
||||
<%= link_to t('admin.menu.poll_shifts'), available_admin_booths_path %>
|
||||
</li>
|
||||
@@ -158,7 +158,7 @@
|
||||
<span class="icon-settings"></span>
|
||||
<strong><%= t("admin.menu.title_site_customization") %></strong>
|
||||
</a>
|
||||
<ul <%= "class=is-active" if menu_profiles? %>>
|
||||
<ul <%= "class=is-active" if menu_customization? %>>
|
||||
<li <%= "class=active" if controller_name == "pages" %>>
|
||||
<%= link_to t("admin.menu.site_customization.pages"), admin_site_customization_pages_path %>
|
||||
</li>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<%= link_to participant.name, user_path(participant)%>
|
||||
</span>
|
||||
|
||||
<% if is_author?(@community, participant) %>
|
||||
<% if author?(@community, participant) %>
|
||||
•
|
||||
<span class="label round is-author">
|
||||
<%= t("comments.comment.author") %>
|
||||
|
||||
@@ -16,24 +16,6 @@
|
||||
<div class="small-12 medium-9 column">
|
||||
<%= back_link_to %>
|
||||
|
||||
<% if can?(:create, @document) && @proposal.documents.size < Proposal.max_documents_allowed %>
|
||||
<%= link_to t("documents.upload_document"),
|
||||
new_document_path(documentable_id: @proposal, documentable_type: @proposal.class.name, from: request.url),
|
||||
class: 'button hollow float-right' %>
|
||||
<% end %>
|
||||
|
||||
<% if author_of?(@proposal, current_user) %>
|
||||
<%= link_to t("proposals.show.send_notification"),
|
||||
new_proposal_notification_path(proposal_id: @proposal.id),
|
||||
class: 'button hollow float-right' %>
|
||||
<% end %>
|
||||
|
||||
<% if current_user && @proposal.editable_by?(current_user) %>
|
||||
<%= link_to edit_proposal_path(@proposal), class: 'edit-proposal button hollow float-right' do %>
|
||||
<%= t("proposals.show.edit_proposal_link") %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<h1><%= @proposal.title %></h1>
|
||||
<% if @proposal.retired? %>
|
||||
<div data-alert class="callout alert margin-top proposal-retired">
|
||||
@@ -122,6 +104,35 @@
|
||||
</div>
|
||||
|
||||
<aside class="small-12 medium-3 column">
|
||||
<% if can_create_document?(@document, @proposal) || author_of_proposal?(@proposal) || current_editable?(@proposal) %>
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("proposals.show.author") %></h2>
|
||||
<div class="show-actions-menu">
|
||||
<% if can_create_document?(@document, @proposal) %>
|
||||
<%= link_to new_document_path(documentable_id: @proposal, documentable_type: @proposal.class.name, from: request.url),
|
||||
class: 'button hollow expanded' do %>
|
||||
<span class="icon-document"></span>
|
||||
<%= t("documents.upload_document") %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if author_of_proposal?(@proposal) %>
|
||||
<%= link_to new_proposal_notification_path(proposal_id: @proposal.id),
|
||||
class: 'button hollow expanded' do %>
|
||||
<span class="icon-no-notification"></span>
|
||||
<%= t("proposals.show.send_notification") %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if current_editable?(@proposal) %>
|
||||
<%= link_to edit_proposal_path(@proposal), class: 'edit-proposal button hollow expanded' do %>
|
||||
<span class="icon-edit"></span>
|
||||
<%= t("proposals.show.edit_proposal_link") %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("votes.supports") %></h2>
|
||||
<div id="<%= dom_id(@proposal) %>_votes">
|
||||
|
||||
@@ -21,7 +21,7 @@ data:
|
||||
# - config/locales/**/*.%{locale}.yml
|
||||
## Another gem (replace %#= with %=):
|
||||
# - "<%#= %x[bundle show vagrant].chomp %>/templates/locales/%{locale}.yml"
|
||||
- config/locales/custom/%{locale}/custom.yml
|
||||
- config/locales/custom/%{locale}/*.yml
|
||||
- config/locales/%{locale}/general.yml
|
||||
- config/locales/%{locale}/activerecord.yml
|
||||
- config/locales/%{locale}/activemodel.yml
|
||||
|
||||
@@ -441,6 +441,7 @@ en:
|
||||
embed_video_title: "Video on %{proposal}"
|
||||
title_external_url: "Additional documentation"
|
||||
title_video_url: "External video"
|
||||
author: Author
|
||||
update:
|
||||
form:
|
||||
submit_button: Save changes
|
||||
|
||||
@@ -441,6 +441,7 @@ es:
|
||||
embed_video_title: "Vídeo en %{proposal}"
|
||||
title_external_url: "Documentación adicional"
|
||||
title_video_url: "Vídeo externo"
|
||||
author: Autor
|
||||
update:
|
||||
form:
|
||||
submit_button: Guardar cambios
|
||||
|
||||
@@ -390,13 +390,10 @@ feature 'Admin budget investments' do
|
||||
|
||||
budget_investment2 = create(:budget_investment)
|
||||
|
||||
visit admin_budget_budget_investment_path(budget_investment2.budget, budget_investment2)
|
||||
click_link 'Edit classification'
|
||||
visit edit_admin_budget_budget_investment_path(budget_investment2.budget, budget_investment2)
|
||||
|
||||
find('.js-add-tag-link', text: 'Education').click
|
||||
|
||||
fill_in 'budget_investment_title', with: 'Updated title'
|
||||
|
||||
click_button 'Update'
|
||||
|
||||
expect(page).to have_content 'Investment project updated succesfully.'
|
||||
|
||||
@@ -9,8 +9,15 @@ feature 'Admin legislation questions' do
|
||||
|
||||
context "Feature flag" do
|
||||
|
||||
scenario 'Disabled with a feature flag' do
|
||||
background do
|
||||
Setting['feature.legislation'] = nil
|
||||
end
|
||||
|
||||
after do
|
||||
Setting['feature.legislation'] = true
|
||||
end
|
||||
|
||||
scenario 'Disabled with a feature flag' do
|
||||
process = create(:legislation_process)
|
||||
expect{ visit admin_legislation_process_questions_path(process) }.to raise_exception(FeatureFlags::FeatureDisabled)
|
||||
end
|
||||
|
||||
@@ -44,13 +44,13 @@ feature 'Admin booths' do
|
||||
current_poll = create(:poll, :current)
|
||||
incoming_poll = create(:poll, :incoming)
|
||||
expired_poll = create(:poll, :expired)
|
||||
|
||||
|
||||
create(:poll_booth_assignment, poll: current_poll, booth: booth_for_current_poll)
|
||||
create(:poll_booth_assignment, poll: incoming_poll, booth: booth_for_incoming_poll)
|
||||
create(:poll_booth_assignment, poll: expired_poll, booth: booth_for_expired_poll)
|
||||
|
||||
|
||||
visit admin_root_path
|
||||
|
||||
|
||||
within('#side_menu') do
|
||||
click_link "Manage shifts"
|
||||
end
|
||||
|
||||
@@ -183,7 +183,7 @@ feature 'Admin polls' do
|
||||
|
||||
scenario 'Add question to poll', :js do
|
||||
poll = create(:poll)
|
||||
question = create(:poll_question, poll: nil, title: 'Should we rebuild the city?')
|
||||
question = create(:poll_question, title: 'Should we rebuild the city?')
|
||||
|
||||
visit admin_poll_path(poll)
|
||||
|
||||
|
||||
@@ -8,25 +8,25 @@ feature 'Admin shifts' do
|
||||
end
|
||||
|
||||
scenario "Show" do
|
||||
poll = create(:poll)
|
||||
poll = create(:poll)
|
||||
officer = create(:poll_officer)
|
||||
|
||||
booth1 = create(:poll_booth)
|
||||
booth2 = create(:poll_booth)
|
||||
|
||||
shift1 = create(:poll_shift, officer: officer, booth: booth1, date: Date.today)
|
||||
shift2 = create(:poll_shift, officer: officer, booth: booth2, date: Date.tomorrow)
|
||||
|
||||
shift1 = create(:poll_shift, officer: officer, booth: booth1, date: Time.zone.today)
|
||||
shift2 = create(:poll_shift, officer: officer, booth: booth2, date: Time.zone.tomorrow)
|
||||
|
||||
visit new_admin_booth_shift_path(booth1)
|
||||
|
||||
expect(page).to have_css(".shift", count: 1)
|
||||
expect(page).to have_content I18n.l(Date.today, format: :long)
|
||||
expect(page).to have_content I18n.l(Time.zone.today, format: :long)
|
||||
expect(page).to have_content officer.name
|
||||
|
||||
visit new_admin_booth_shift_path(booth2)
|
||||
|
||||
expect(page).to have_css(".shift", count: 1)
|
||||
expect(page).to have_content I18n.l(Date.tomorrow, format: :long)
|
||||
expect(page).to have_content I18n.l(Time.zone.tomorrow, format: :long)
|
||||
expect(page).to have_content officer.name
|
||||
end
|
||||
|
||||
@@ -36,7 +36,7 @@ feature 'Admin shifts' do
|
||||
officer = create(:poll_officer)
|
||||
|
||||
visit admin_booths_path
|
||||
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
click_link "Manage shifts"
|
||||
end
|
||||
@@ -47,7 +47,7 @@ feature 'Admin shifts' do
|
||||
|
||||
select I18n.l(poll.starts_at.to_date, format: :long), from: 'shift_date'
|
||||
click_button "Add shift"
|
||||
|
||||
|
||||
expect(page).to have_content "Shift added"
|
||||
|
||||
within("#shifts") do
|
||||
@@ -63,7 +63,7 @@ feature 'Admin shifts' do
|
||||
officer = create(:poll_officer)
|
||||
|
||||
visit admin_booths_path
|
||||
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
click_link "Manage shifts"
|
||||
end
|
||||
@@ -84,7 +84,7 @@ feature 'Admin shifts' do
|
||||
shift = create(:poll_shift, officer: officer, booth: booth)
|
||||
|
||||
visit admin_booths_path
|
||||
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
click_link "Manage shifts"
|
||||
end
|
||||
|
||||
@@ -341,7 +341,7 @@ feature 'Budget Investments' do
|
||||
|
||||
scenario 'Can not access the community' do
|
||||
Setting['feature.community'] = false
|
||||
|
||||
|
||||
investment = create(:budget_investment, heading: heading)
|
||||
visit budget_investment_path(budget_id: budget.id, id: investment.id)
|
||||
expect(page).not_to have_content "Access the community"
|
||||
|
||||
@@ -33,7 +33,7 @@ feature 'Commenting debates' do
|
||||
expect(page).to have_content second_child.body
|
||||
|
||||
expect(page).to have_link "Go back to #{debate.title}", href: debate_path(debate)
|
||||
|
||||
|
||||
expect(page).to have_selector("ul#comment_#{parent_comment.id}>li", count: 2)
|
||||
expect(page).to have_selector("ul#comment_#{first_child.id}>li", count: 1)
|
||||
expect(page).to have_selector("ul#comment_#{second_child.id}>li", count: 1)
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Legacy Legislation' do
|
||||
|
||||
scenario 'Show' do
|
||||
legacy_legislation = create(:legacy_legislation, title: 'Change the world', body: 'To achieve this...')
|
||||
|
||||
visit legacy_legislation_path(legacy_legislation)
|
||||
|
||||
expect(page).to have_content 'Change the world'
|
||||
expect(page).to have_content 'To achieve this...'
|
||||
end
|
||||
|
||||
context 'Annotations', :js do
|
||||
|
||||
let(:user) { create(:user) }
|
||||
background { login_as user }
|
||||
|
||||
scenario 'Create' do
|
||||
legacy_legislation = create(:legacy_legislation)
|
||||
|
||||
visit legacy_legislation_path(legacy_legislation)
|
||||
|
||||
page.find(:css, "#legacy_legislation_body").double_click
|
||||
page.find(:css, ".annotator-adder button").click
|
||||
fill_in 'annotator-field-0', with: 'this is my annotation'
|
||||
page.find(:css, ".annotator-controls a[href='#save']").click
|
||||
|
||||
expect(page).to have_css ".annotator-hl"
|
||||
first(:css, ".annotator-hl").click
|
||||
expect(page).to have_content "this is my annotation"
|
||||
|
||||
visit legacy_legislation_path(legacy_legislation)
|
||||
|
||||
expect(page).to have_css ".annotator-hl"
|
||||
first(:css, ".annotator-hl").click
|
||||
expect(page).to have_content "this is my annotation"
|
||||
end
|
||||
|
||||
scenario 'Update' do
|
||||
legacy_legislation = create(:legacy_legislation)
|
||||
annotation = create(:annotation, legacy_legislation: legacy_legislation, user: user, text: "my annotation")
|
||||
|
||||
visit legacy_legislation_path(legacy_legislation)
|
||||
|
||||
expect(page).to have_css ".annotator-hl"
|
||||
page.find(:css, ".annotator-hl").click
|
||||
page.find(:css, ".annotator-edit").click
|
||||
|
||||
fill_in 'annotator-field-0', with: 'edited annotation'
|
||||
page.find(:css, ".annotator-controls a[href='#save']").click
|
||||
|
||||
expect(page).to_not have_css('span', text: 'my annotation')
|
||||
|
||||
page.find(:css, ".annotator-hl").click
|
||||
expect(page).to have_content "edited annotation"
|
||||
|
||||
visit legacy_legislation_path(legacy_legislation)
|
||||
|
||||
page.find(:css, ".annotator-hl").click
|
||||
expect(page).to have_content "edited annotation"
|
||||
end
|
||||
|
||||
scenario 'Destroy' do
|
||||
legacy_legislation = create(:legacy_legislation)
|
||||
annotation = create(:annotation, legacy_legislation: legacy_legislation, user: user)
|
||||
|
||||
visit legacy_legislation_path(legacy_legislation)
|
||||
|
||||
expect(page).to have_css ".annotator-hl"
|
||||
|
||||
page.find(:css, ".annotator-hl").click
|
||||
page.find(:css, ".annotator-delete").click
|
||||
|
||||
expect(page).to_not have_css ".annotator-hl"
|
||||
end
|
||||
|
||||
scenario 'Search' do
|
||||
legacy_legislation = create(:legacy_legislation)
|
||||
annotation1 = create(:annotation, legacy_legislation: legacy_legislation, text: "my annotation",
|
||||
ranges: [{"start" => "/div[1]", "startOffset" => 5, "end" => "/div[1]", "endOffset" => 10}])
|
||||
annotation2 = create(:annotation, legacy_legislation: legacy_legislation, text: "my other annotation",
|
||||
ranges: [{"start" => "/div[1]", "startOffset" => 12, "end" => "/div[1]", "endOffset" => 19}])
|
||||
|
||||
visit legacy_legislation_path(legacy_legislation)
|
||||
|
||||
expect(page).to have_css ".annotator-hl"
|
||||
first(:css, ".annotator-hl").click
|
||||
expect(page).to have_content "my annotation"
|
||||
|
||||
all(".annotator-hl")[1].click
|
||||
expect(page).to have_content "my other annotation"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
## Notes logged in and not logged in users
|
||||
@@ -303,7 +303,7 @@ feature 'Votes' do
|
||||
debate = create(:debate)
|
||||
comment = create(:comment, commentable: debate)
|
||||
|
||||
visit comment_path(debate)
|
||||
visit comment_path(comment)
|
||||
within("#comment_#{comment.id}") do
|
||||
find("div.votes").hover
|
||||
expect_message_you_need_to_sign_in_to_vote_comments
|
||||
|
||||
@@ -41,7 +41,7 @@ describe 'Communities Rake' do
|
||||
|
||||
expect(investment.community).to be_present
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Geozone, type: :model do
|
||||
describe Geozone do
|
||||
let(:geozone) { build(:geozone) }
|
||||
|
||||
it "should be valid" do
|
||||
@@ -13,6 +13,8 @@ RSpec.describe Geozone, type: :model do
|
||||
end
|
||||
|
||||
describe "#safe_to_destroy?" do
|
||||
let(:geozone) { create(:geozone) }
|
||||
|
||||
it "is true when not linked to other models" do
|
||||
expect(geozone.safe_to_destroy?).to be_truthy
|
||||
end
|
||||
|
||||
@@ -25,20 +25,20 @@ describe :booth do
|
||||
end
|
||||
|
||||
describe "#available" do
|
||||
|
||||
|
||||
it "returns booths associated to current or incoming polls" do
|
||||
booth_for_current_poll = create(:poll_booth)
|
||||
booth_for_incoming_poll = create(:poll_booth)
|
||||
booth_for_expired_poll = create(:poll_booth)
|
||||
|
||||
|
||||
current_poll = create(:poll, :current)
|
||||
incoming_poll = create(:poll, :incoming)
|
||||
expired_poll = create(:poll, :expired)
|
||||
|
||||
|
||||
create(:poll_booth_assignment, poll: current_poll, booth: booth_for_current_poll)
|
||||
create(:poll_booth_assignment, poll: incoming_poll, booth: booth_for_incoming_poll)
|
||||
create(:poll_booth_assignment, poll: expired_poll, booth: booth_for_expired_poll)
|
||||
|
||||
|
||||
expect(Poll::Booth.available).to include(booth_for_current_poll)
|
||||
expect(Poll::Booth.available).to include(booth_for_incoming_poll)
|
||||
expect(Poll::Booth.available).to_not include(booth_for_expired_poll)
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Poll::Question, type: :model do
|
||||
let(:poll_question) { build(:poll_question) }
|
||||
|
||||
describe "#valid_answers" do
|
||||
it "gets a comma-separated string, but returns an array" do
|
||||
q = create(:poll_question, valid_answers: "Yes, No")
|
||||
expect(q.valid_answers).to eq(["Yes", "No"])
|
||||
poll_question.valid_answers = "Yes, No"
|
||||
expect(poll_question.valid_answers).to eq(["Yes", "No"])
|
||||
end
|
||||
end
|
||||
|
||||
describe "#poll_question_id" do
|
||||
it "should be invalid if a poll is not selected" do
|
||||
poll_question.poll_id = nil
|
||||
expect(poll_question).to_not be_valid
|
||||
end
|
||||
|
||||
it "should be valid if a poll is selected" do
|
||||
poll_question.poll_id = 1
|
||||
expect(poll_question).to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,13 +26,12 @@ RSpec.describe Poll::Question, type: :model do
|
||||
it "copies the attributes from the proposal" do
|
||||
create_list(:geozone, 3)
|
||||
p = create(:proposal)
|
||||
q = create(:poll_question)
|
||||
q.copy_attributes_from_proposal(p)
|
||||
expect(q.valid_answers).to eq(['Yes', 'No'])
|
||||
expect(q.author).to eq(p.author)
|
||||
expect(q.author_visible_name).to eq(p.author.name)
|
||||
expect(q.proposal_id).to eq(p.id)
|
||||
expect(q.title).to eq(p.title)
|
||||
poll_question.copy_attributes_from_proposal(p)
|
||||
expect(poll_question.valid_answers).to eq(['Yes', 'No'])
|
||||
expect(poll_question.author).to eq(p.author)
|
||||
expect(poll_question.author_visible_name).to eq(p.author.name)
|
||||
expect(poll_question.proposal_id).to eq(p.id)
|
||||
expect(poll_question.title).to eq(p.title)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ describe :shift do
|
||||
|
||||
officer_assignments = Poll::OfficerAssignment.all
|
||||
expect(officer_assignments.count).to eq(2)
|
||||
|
||||
|
||||
oa1 = officer_assignments.first
|
||||
oa2 = officer_assignments.second
|
||||
|
||||
@@ -59,10 +59,10 @@ describe :shift do
|
||||
end
|
||||
|
||||
describe "#persist_data" do
|
||||
|
||||
let(:user) { create(:user, username: "Ana", email: "ana@example.com") }
|
||||
let(:officer) { create(:poll_officer, user: user) }
|
||||
let(:shift) { create(:poll_shift, officer: officer) }
|
||||
|
||||
let(:user) { create(:user, username: "Ana", email: "ana@example.com") }
|
||||
let(:officer) { create(:poll_officer, user: user) }
|
||||
let(:shift) { create(:poll_shift, officer: officer) }
|
||||
|
||||
it "should maintain officer data after destroying associated user" do
|
||||
shift.officer.user.destroy
|
||||
@@ -79,5 +79,5 @@ describe :shift do
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -71,5 +71,4 @@ describe Topic do
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -60,7 +60,7 @@ shared_examples "documentable" do |documentable_factory_name, documentable_path,
|
||||
login_as(user)
|
||||
|
||||
visit send(documentable_path, arguments)
|
||||
click_link "Upload document"
|
||||
click_link "Upload document"
|
||||
|
||||
expect(page).to have_selector("h1", text: "Upload document")
|
||||
end
|
||||
@@ -251,6 +251,41 @@ shared_examples "documentable" do |documentable_factory_name, documentable_path,
|
||||
expect(find("input[name='document[cached_attachment]']", visible: false).value).to include("empty.pdf")
|
||||
end
|
||||
|
||||
scenario "Should not show 'Choose document' button after valid upload", :js do
|
||||
login_as documentable.author
|
||||
visit new_document_path(documentable_type: documentable.class.name,
|
||||
documentable_id: documentable.id)
|
||||
|
||||
attach_file :document_attachment, "spec/fixtures/files/empty.pdf", make_visible: true
|
||||
sleep 1
|
||||
|
||||
expect(page).not_to have_content "Choose document"
|
||||
end
|
||||
|
||||
scenario "Should show 'Remove document' button after valid upload", :js do
|
||||
login_as documentable.author
|
||||
visit new_document_path(documentable_type: documentable.class.name,
|
||||
documentable_id: documentable.id)
|
||||
|
||||
attach_file :document_attachment, "spec/fixtures/files/empty.pdf", make_visible: true
|
||||
sleep 1
|
||||
|
||||
expect(page).to have_link("Remove document")
|
||||
end
|
||||
|
||||
scenario "Should show 'Choose document' button after remove valid upload", :js do
|
||||
login_as documentable.author
|
||||
visit new_document_path(documentable_type: documentable.class.name,
|
||||
documentable_id: documentable.id)
|
||||
|
||||
attach_file :document_attachment, "spec/fixtures/files/empty.pdf", make_visible: true
|
||||
sleep 1
|
||||
click_link "Remove document"
|
||||
sleep 1
|
||||
|
||||
expect(page).to have_content "Choose document"
|
||||
end
|
||||
|
||||
scenario "Should not update document cached_attachment field after unvalid file upload", :js do
|
||||
login_as documentable.author
|
||||
visit new_document_path(documentable_type: documentable.class.name,
|
||||
|
||||
@@ -11,10 +11,8 @@ shared_examples "nested documentable" do |documentable_factory_name, path, docum
|
||||
before do
|
||||
create(:administrator, user: administrator)
|
||||
|
||||
if documentable_path_arguments
|
||||
documentable_path_arguments.each do |argument_name, path_to_value|
|
||||
documentable_path_arguments&.each do |argument_name, path_to_value|
|
||||
arguments.merge!("#{argument_name}": documentable.send(path_to_value))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -222,7 +220,7 @@ shared_examples "nested documentable" do |documentable_factory_name, path, docum
|
||||
send(fill_resource_method_name) if fill_resource_method_name
|
||||
|
||||
documentable.class.max_documents_allowed.times.each do |index|
|
||||
attach_new_file(documentable_factory_name, index , "spec/fixtures/files/empty.pdf")
|
||||
attach_new_file(documentable_factory_name, index, "spec/fixtures/files/empty.pdf")
|
||||
end
|
||||
|
||||
click_on submit_button
|
||||
@@ -250,7 +248,7 @@ def attach_new_file(documentable_factory_name, index, path)
|
||||
end
|
||||
|
||||
def fill_new_valid_proposal
|
||||
fill_in :proposal_title, with: "Proposal title"
|
||||
fill_in :proposal_title, with: "Proposal title #{rand(9999)}"
|
||||
fill_in :proposal_summary, with: "Proposal summary"
|
||||
fill_in :proposal_question, with: "Proposal question?"
|
||||
check :proposal_terms_of_service
|
||||
|
||||
Reference in New Issue
Block a user