diff options
79 files changed, 911 insertions, 351 deletions
| diff --git a/app/assets/stylesheets/base/_config.sass b/app/assets/stylesheets/base/_config.sass index 65444479f..ec1c43e7f 100644 --- a/app/assets/stylesheets/base/_config.sass +++ b/app/assets/stylesheets/base/_config.sass @@ -16,6 +16,7 @@ $blue: #007fbb  $darkgrey: #4b4b4b  $grey: #a4a4a4 +$lightgrey: rgba($grey, 0.15)  $green: #70b12b  $red: #da2f36 diff --git a/app/assets/stylesheets/components/_forms.sass b/app/assets/stylesheets/components/_forms.sass index 9a363ab97..47faf19b1 100644 --- a/app/assets/stylesheets/components/_forms.sass +++ b/app/assets/stylesheets/components/_forms.sass @@ -229,6 +229,13 @@ $cbx-size-xs: 15px      &[type='checkbox']:checked + label:before        background-color: $blue +    &[type='checkbox']:disabled + label +      &:before +        border-color: $grey +        background-color: $lightgrey +        cursor: not-allowed +      &:after +        display: none  // Table adjustments  table, .table    .td, td, .th, th diff --git a/app/assets/stylesheets/components/_panels.sass b/app/assets/stylesheets/components/_panels.sass index e9f615081..ab25d8184 100644 --- a/app/assets/stylesheets/components/_panels.sass +++ b/app/assets/stylesheets/components/_panels.sass @@ -34,6 +34,7 @@          a            text-decoration: none            color: $blue +          text-transform: capitalize            &:hover, &:focus              color: $darkblue diff --git a/app/controllers/autocomplete_stop_areas_controller.rb b/app/controllers/autocomplete_stop_areas_controller.rb index 233012028..be1badff0 100644 --- a/app/controllers/autocomplete_stop_areas_controller.rb +++ b/app/controllers/autocomplete_stop_areas_controller.rb @@ -18,7 +18,7 @@ class AutocompleteStopAreasController < ChouetteController        scope = scope.possible_parents if relation_children?      end      args = [].tap{|arg| 4.times{arg << "%#{params[:q]}%"}} -    @stop_areas = scope.where("name ILIKE ? OR city_name ILIKE ? OR registration_number ILIKE ? OR objectid ILIKE ?", *args).limit(50) +    @stop_areas = scope.where("unaccent(name) ILIKE unaccent(?) OR unaccent(city_name) ILIKE unaccent(?) OR registration_number ILIKE ? OR objectid ILIKE ?", *args).limit(50)      @stop_areas    end diff --git a/app/controllers/line_referentials_controller.rb b/app/controllers/line_referentials_controller.rb index 39c2cdb89..03dab3f8f 100644 --- a/app/controllers/line_referentials_controller.rb +++ b/app/controllers/line_referentials_controller.rb @@ -3,6 +3,7 @@ class LineReferentialsController < ChouetteController    defaults :resource_class => LineReferential    def sync +    authorize resource, :synchronize?      @sync = resource.line_referential_syncs.build      if @sync.save        flash[:notice] = t('notice.line_referential_sync.created') diff --git a/app/controllers/referentials_controller.rb b/app/controllers/referentials_controller.rb index ee1236912..40e8264ce 100644 --- a/app/controllers/referentials_controller.rb +++ b/app/controllers/referentials_controller.rb @@ -17,6 +17,8 @@ class ReferentialsController < ChouetteController        build_referenial        if !!@referential.created_from_id +        flash[:notice] = t('notice.referentials.duplicate') +          format.html { redirect_to workbench_path(@referential.workbench) }        end      end @@ -60,7 +62,7 @@ class ReferentialsController < ChouetteController    def validate      ComplianceControlSetCopyWorker.perform_async(params[:compliance_control_set], params[:id]) -    flash[:notice] = I18n.t("referentials.operation_in_progress") +    flash[:notice] = t('notice.referentials.validate')      redirect_to(referential_path)    end diff --git a/app/controllers/stop_area_referentials_controller.rb b/app/controllers/stop_area_referentials_controller.rb index 85541230d..f2d375e49 100644 --- a/app/controllers/stop_area_referentials_controller.rb +++ b/app/controllers/stop_area_referentials_controller.rb @@ -2,6 +2,7 @@ class StopAreaReferentialsController < ChouetteController    defaults :resource_class => StopAreaReferential    def sync +    authorize resource, :synchronize?      @sync = resource.stop_area_referential_syncs.build      if @sync.save        flash[:notice] = t('notice.stop_area_referential_sync.created') diff --git a/app/controllers/stop_areas_controller.rb b/app/controllers/stop_areas_controller.rb index 133518324..d4d996adb 100644 --- a/app/controllers/stop_areas_controller.rb +++ b/app/controllers/stop_areas_controller.rb @@ -171,7 +171,7 @@ class StopAreasController < ChouetteController    helper_method :current_referential    def stop_area_params -    params.require(:stop_area).permit( :routing_stop_ids, :routing_line_ids, :children_ids, :stop_area_type, :parent_id, :objectid, :object_version, :name, :comment, :area_type, :registration_number, :nearest_topic_name, :fare_code, :longitude, :latitude, :long_lat_type, :country_code, :street_name, :zip_code, :city_name, :mobility_restricted_suitability, :stairs_availability, :lift_availability, :int_user_needs, :coordinates, :url, :time_zone ) +    params.require(:stop_area).permit( :routing_stop_ids, :routing_line_ids, :children_ids, :parent_id, :objectid, :object_version, :name, :comment, :area_type, :registration_number, :nearest_topic_name, :fare_code, :longitude, :latitude, :long_lat_type, :country_code, :street_name, :zip_code, :city_name, :mobility_restricted_suitability, :stairs_availability, :lift_availability, :int_user_needs, :coordinates, :url, :time_zone )    end  end diff --git a/app/decorators/company_decorator.rb b/app/decorators/company_decorator.rb index 9416c73ae..50b82d276 100644 --- a/app/decorators/company_decorator.rb +++ b/app/decorators/company_decorator.rb @@ -18,13 +18,6 @@ class CompanyDecorator < Draper::Decorator    def action_links      links = [] -    if h.policy(Chouette::Company).create? -      links << Link.new( -        content: h.t('companies.actions.new'), -        href: h.new_line_referential_company_path(context[:referential]) -      ) -    end -      if h.policy(object).update?        links << Link.new(          content: h.t('companies.actions.edit'), @@ -37,7 +30,7 @@ class CompanyDecorator < Draper::Decorator      if h.policy(object).destroy?        links << Link.new( -        content: t('companies.actions.destroy'), +        content: h.destroy_link_content('companies.actions.destroy'),          href: h.line_referential_company_path(            context[:referential],            object diff --git a/app/decorators/compliance_check_set_decorator.rb b/app/decorators/compliance_check_set_decorator.rb index 096596b19..c58e14d88 100644 --- a/app/decorators/compliance_check_set_decorator.rb +++ b/app/decorators/compliance_check_set_decorator.rb @@ -3,15 +3,6 @@ class ComplianceCheckSetDecorator < Draper::Decorator    def action_links      links = [] - -    links << Link.new( -      content: h.destroy_link_content, -      href: h.workbench_compliance_check_sets_path(object.id), -      method: :delete, -      data: {confirm: h.t('imports.actions.destroy_confirm')} -    ) - -    links    end    def lines_status diff --git a/app/decorators/referential_line_decorator.rb b/app/decorators/referential_line_decorator.rb index 55acf7ed9..654f68bf5 100644 --- a/app/decorators/referential_line_decorator.rb +++ b/app/decorators/referential_line_decorator.rb @@ -24,21 +24,6 @@ class ReferentialLineDecorator < Draper::Decorator        )      ) -    if h.policy(Chouette::Line).create? && -        context[:referential].organisation == context[:current_organisation] -      links << Link.new( -        content: h.t('actions.new'), -        href: h.new_referential_line_path(context[:referential]) -      ) -    end - -    if h.policy(object).update? -      links << Link.new( -        content: h.t('actions.edit'), -        href: h.edit_referential_line_path(context[:referential], object) -      ) -    end -      if h.policy(object).destroy?        links << Link.new(          content: h.destroy_link_content('actions.destroy'), diff --git a/app/decorators/stop_area_decorator.rb b/app/decorators/stop_area_decorator.rb index 4e777292d..8b2ebf490 100644 --- a/app/decorators/stop_area_decorator.rb +++ b/app/decorators/stop_area_decorator.rb @@ -7,15 +7,6 @@ class StopAreaDecorator < Draper::Decorator      links = []      stop_area ||= object -    if h.policy(Chouette::StopArea).new? -      links << Link.new( -        content: h.t('stop_areas.actions.new'), -        href: h.new_stop_area_referential_stop_area_path( -          stop_area.stop_area_referential -        ) -      ) -    end -      if h.policy(stop_area).update?        links << Link.new(          content: h.t('stop_areas.actions.edit'), diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 124604cd9..713542ff4 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -23,12 +23,18 @@ module ApplicationHelper    end    def page_header_meta(object) -    info = t('last_update', time: l(object.updated_at, format: :short)) -    if object.try(:versions) -      author = object.versions.try(:last).try(:whodunnit) || t('default_whodunnit') -      info   = "#{info} <br/> #{t('whodunnit', author: author)}" +    out = "" +    display = true +    display = policy(object).synchronize? if policy(object).respond_to?(:synchronize?) rescue false +    if display +      info = t('last_update', time: l(object.updated_at, format: :short)) +      if object.try(:versions) +        author = object.versions.try(:last).try(:whodunnit) || t('default_whodunnit') +        info   = "#{info} <br/> #{t('whodunnit', author: author)}" +      end +      out += content_tag :div, info.html_safe, class: 'small last-update'      end -    content_tag :div, info.html_safe, class: 'small' +    out.html_safe    end    def page_header_content_for(object) diff --git a/app/helpers/table_builder_helper.rb b/app/helpers/table_builder_helper.rb index 37f01ce0d..de78e903d 100644 --- a/app/helpers/table_builder_helper.rb +++ b/app/helpers/table_builder_helper.rb @@ -95,6 +95,18 @@ module TableBuilderHelper        class: cls    end +  def self.item_row_class_name collection +    if collection.respond_to?(:model) +      model_name = collection.model.name +    elsif collection.respond_to?(:first) +      model_name = collection.first.class.name +    else +      model_name = "item" +    end + +    model_name.split("::").last.parameterize +  end +    private    def thead(collection, columns, sortable, selectable, has_links, overhead, model ) @@ -187,86 +199,92 @@ module TableBuilderHelper      end    end -  def tbody(collection, columns, selectable, links, overhead) -    content_tag :tbody do -      collection.map do |item| - -        content_tag :tr do -          bcont = [] - -          if selectable -            bcont << content_tag( -              :td, -              checkbox(id_name: item.try(:id), value: item.try(:id)) -            ) -          end - -          columns.each do |column| -            value = column.value(item) +  def tr item, columns, selectable, links, overhead, model_name +    klass = "#{model_name}-#{item.id}" +    content_tag :tr, class: klass do +      bcont = [] +      if selectable +        disabled = selectable.respond_to?(:call) && !selectable.call(item) +        bcont << content_tag( +          :td, +          checkbox(id_name: item.try(:id), value: item.try(:id), disabled: disabled) +        ) +      end -            if column.linkable? -              path = column.link_to(item) -              link = link_to(value, path) +      columns.each do |column| +        value = column.value(item) -              if overhead.empty? -                bcont << content_tag(:td, link, title: 'Voir') +        if column.linkable? +          path = column.link_to(item) +          link = link_to(value, path) -              else -                i = columns.index(column) - -                if overhead[i].blank? -                  if (i > 0) && (overhead[i - 1][:width] > 1) -                    clsArrayAlt = overhead[i - 1][:cls].split +          if overhead.empty? +            bcont << content_tag(:td, link, title: 'Voir') -                    bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArrayAlt)) +          else +            i = columns.index(column) -                  else -                    bcont << content_tag(:td, link, title: 'Voir') -                  end +            if overhead[i].blank? +              if (i > 0) && (overhead[i - 1][:width] > 1) +                clsArrayAlt = overhead[i - 1][:cls].split -                else -                  clsArray = overhead[columns.index(column)][:cls].split +                bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArrayAlt)) -                  bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArray)) -                end +              else +                bcont << content_tag(:td, link, title: 'Voir')                end              else -              if overhead.empty? -                bcont << content_tag(:td, value) +              clsArray = overhead[columns.index(column)][:cls].split -              else -                i = columns.index(column) +              bcont << content_tag(:td, link, title: 'Voir', class: td_cls(clsArray)) +            end +          end -                if overhead[i].blank? -                  if (i > 0) && (overhead[i - 1][:width] > 1) -                    clsArrayAlt = overhead[i - 1][:cls].split +        else +          if overhead.empty? +            bcont << content_tag(:td, value) -                    bcont << content_tag(:td, value, class: td_cls(clsArrayAlt)) +          else +            i = columns.index(column) -                  else -                    bcont << content_tag(:td, value) -                  end +            if overhead[i].blank? +              if (i > 0) && (overhead[i - 1][:width] > 1) +                clsArrayAlt = overhead[i - 1][:cls].split -                else -                  clsArray = overhead[i][:cls].split +                bcont << content_tag(:td, value, class: td_cls(clsArrayAlt)) -                  bcont << content_tag(:td, value, class: td_cls(clsArray)) -                end +              else +                bcont << content_tag(:td, value)                end + +            else +              clsArray = overhead[i][:cls].split + +              bcont << content_tag(:td, value, class: td_cls(clsArray))              end            end +        end +      end -          if links.any? || item.try(:action_links).try(:any?) -            bcont << content_tag( -              :td, -              build_links(item, links), -              class: 'actions' -            ) -          end +      if links.any? || item.try(:action_links).try(:any?) +        bcont << content_tag( +          :td, +          build_links(item, links), +          class: 'actions' +        ) +      end -          bcont.join.html_safe -        end +      bcont.join.html_safe +    end +  end + +  def tbody(collection, columns, selectable, links, overhead) +    model_name = TableBuilderHelper.item_row_class_name collection + +    content_tag :tbody do +      collection.map do |item| +        tr item, columns, selectable, links, overhead, model_name        end.join.html_safe      end    end @@ -341,13 +359,14 @@ module TableBuilderHelper      end    end -  def checkbox(id_name:, value:) +  def checkbox(id_name:, value:, disabled: false)      content_tag :div, '', class: 'checkbox' do -      check_box_tag(id_name, value).concat( +      check_box_tag(id_name, value, nil, disabled: disabled).concat(          content_tag(:label, '', for: id_name)        )      end    end +    def gear_menu_link(link)      content_tag(        :li, diff --git a/app/models/chouette/area_type.rb b/app/models/chouette/area_type.rb new file mode 100644 index 000000000..f295fe7ae --- /dev/null +++ b/app/models/chouette/area_type.rb @@ -0,0 +1,37 @@ +class Chouette::AreaType + +  ALL = %i(zdep zder zdlp zdlr lda).freeze + +  @@all = ALL +  mattr_accessor :all + +  def self.all=(values) +    @@all = ALL & values +    reset_caches! +  end + +  @@instances = {} +  def self.find(code) +    code = code.to_sym +    @@instances[code] ||= new(code) if ALL.include? code +  end + +  def self.reset_caches! +    @@instances = {} +    @@options = nil +  end + +  def self.options +    @@options ||= all.map { |c| find(c) }.map { |t| [ t.label, t.code ] } +  end + +  attr_reader :code +  def initialize(code) +    @code = code +  end + +  def label +    I18n.translate code, scope: 'area_types.label' +  end + +end diff --git a/app/models/chouette/stop_area.rb b/app/models/chouette/stop_area.rb index cc7170728..f216ce449 100644 --- a/app/models/chouette/stop_area.rb +++ b/app/models/chouette/stop_area.rb @@ -9,7 +9,7 @@ module Chouette      include ObjectidSupport      extend Enumerize -    enumerize :area_type, in: %i(zdep zder zdlp zdlr lda) +    enumerize :area_type, in: Chouette::AreaType::ALL      with_options dependent: :destroy do |assoc|        assoc.has_many :stop_points @@ -196,10 +196,12 @@ module Chouette        GeoRuby::SimpleFeatures::Envelope.from_coordinates coordinates      end +    # DEPRECATED use StopArea#area_type      def stop_area_type        area_type ? area_type : " "      end +    # DEPRECATED use StopArea#area_type      def stop_area_type=(stop_area_type)        self.area_type = (stop_area_type ? stop_area_type.camelcase : nil)      end diff --git a/app/models/referential_cloning.rb b/app/models/referential_cloning.rb index 5bf283814..24117e6c8 100644 --- a/app/models/referential_cloning.rb +++ b/app/models/referential_cloning.rb @@ -2,14 +2,27 @@ class ReferentialCloning < ActiveRecord::Base    include AASM    belongs_to :source_referential, class_name: 'Referential'    belongs_to :target_referential, class_name: 'Referential' -  after_commit :perform_clone, :on => :create +  after_commit :clone, on: :create -  private -  def perform_clone +  def clone      ReferentialCloningWorker.perform_async(id) -    # ReferentialCloningWorker.new.perform(id)    end +  def clone! +    run! + +    AF83::SchemaCloner +      .new(source_referential.slug, target_referential.slug) +      .clone_schema + +    successful! +  rescue Exception => e +    Rails.logger.error "Clone failed : #{e}" +    failed! +  end + +  private +    aasm column: :status do      state :new, :initial => true      state :pending diff --git a/app/models/user.rb b/app/models/user.rb index 37d35209a..1342f60ed 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -36,7 +36,7 @@ class User < ActiveRecord::Base      self.name         = extra[:full_name]      self.email        = extra[:email]      self.organisation = Organisation.sync_update extra[:organisation_code], extra[:organisation_name], extra[:functional_scope] -    self.permissions  = Stif::PermissionTranslator.translate(extra[:permissions]) +    self.permissions  = Stif::PermissionTranslator.translate(extra[:permissions], self.organisation)    end    def self.portail_api_request diff --git a/app/policies/calendar_policy.rb b/app/policies/calendar_policy.rb index 074c41d8d..c2da8c924 100644 --- a/app/policies/calendar_policy.rb +++ b/app/policies/calendar_policy.rb @@ -5,18 +5,15 @@ class CalendarPolicy < ApplicationPolicy      end    end -  def create?  -    !archived? && user.has_permission?('calendars.create') -  end -  def destroy? -    !archived? & organisation_match? && user.has_permission?('calendars.destroy') -  end -  def update? -    !archived? && organisation_match? && user.has_permission?('calendars.update') +  def create? +    user.has_permission?('calendars.create')    end +  def destroy?; instance_permission("destroy") end +  def update?; instance_permission("update") end +  def share?; instance_permission("share") end -  def share? -    user.organisation.name == 'STIF' # FIXME +  private +  def instance_permission permission +    organisation_match? && user.has_permission?("calendars.#{permission}")    end -  end diff --git a/app/policies/line_referential_policy.rb b/app/policies/line_referential_policy.rb new file mode 100644 index 000000000..ee742a083 --- /dev/null +++ b/app/policies/line_referential_policy.rb @@ -0,0 +1,14 @@ +class LineReferentialPolicy < ApplicationPolicy +  class Scope < Scope +    def resolve +      scope +    end +  end + +  def synchronize?; instance_permission("synchronize") end + +  private +  def instance_permission permission +    user.has_permission?("line_referentials.#{permission}") +  end +end diff --git a/app/policies/stop_area_referential_policy.rb b/app/policies/stop_area_referential_policy.rb new file mode 100644 index 000000000..e370babf8 --- /dev/null +++ b/app/policies/stop_area_referential_policy.rb @@ -0,0 +1,14 @@ +class StopAreaReferentialPolicy < ApplicationPolicy +  class Scope < Scope +    def resolve +      scope +    end +  end + +  def synchronize?; instance_permission("synchronize") end + +  private +  def instance_permission permission +    user.has_permission?("stop_area_referentials.#{permission}") +  end +end diff --git a/app/views/companies/index.html.slim b/app/views/companies/index.html.slim index 5d746642f..e031f3776 100644 --- a/app/views/companies/index.html.slim +++ b/app/views/companies/index.html.slim @@ -34,7 +34,7 @@                  end \                ) \              ], -            links: [:show, :edit], +            links: [:show],              cls: 'table has-search'            = new_pagination @companies, 'pull-right' diff --git a/app/views/compliance_check_sets/index.html.slim b/app/views/compliance_check_sets/index.html.slim index f5d1bd777..f109845b4 100644 --- a/app/views/compliance_check_sets/index.html.slim +++ b/app/views/compliance_check_sets/index.html.slim @@ -12,7 +12,7 @@                [ \                  TableBuilderHelper::Column.new( \                    key: :ref, \ -                  attribute: 'compliance_check_set_id' \ +                  attribute: 'id' \                  ), \                  TableBuilderHelper::Column.new( \                    key: :creation_date, \ @@ -41,5 +41,3 @@        .row.mt-xs          .col-lg-12            = replacement_msg t('compliance_check_sets.search_no_results') - - diff --git a/app/views/dashboards/_dashboard.html.slim b/app/views/dashboards/_dashboard.html.slim index f03301e23..7d547bf4c 100644 --- a/app/views/dashboards/_dashboard.html.slim +++ b/app/views/dashboards/_dashboard.html.slim @@ -5,7 +5,7 @@          .panel-heading            h3.panel-title.with_actions              div -              = workbench.name +              = link_to workbench.name, workbench_path(workbench)                span.badge.ml-xs = workbench.referentials.count if workbench.referentials.present?              div @@ -22,7 +22,7 @@      .panel.panel-default        .panel-heading          h3.panel-title.with_actions -          = "Modèles de calendrier" +          = link_to I18n.t("activerecord.models.calendar", count: @dashboard.current_organisation.calendars.size), calendars_path            div              = link_to '', calendars_path, class: ' fa fa-chevron-right pull-right'        - if @dashboard.current_organisation.calendars.present? diff --git a/app/views/devise/invitations/edit.html.slim b/app/views/devise/invitations/edit.html.slim index 6c9a6f436..7a22146c0 100644 --- a/app/views/devise/invitations/edit.html.slim +++ b/app/views/devise/invitations/edit.html.slim @@ -1,14 +1,19 @@ -.col-md-offset-2.col-md-8 -  .panel.panel-default -    .panel-heading = t('devise.invitations.edit.header') -     -    .panel-body -      = simple_form_for resource, as: resource_name, :url => invitation_path(resource_name), :html => { :method => :put, class: "form-horizontal" } do |form| -        = form.hidden_field :invitation_token - -        = form.input :name -        = form.input :password, as: :password -        = form.input :password_confirmation, as: :password - -        .submit -          = form.button :submit, value: t('devise.invitations.edit.submit_button'), class: 'btn-info'
\ No newline at end of file +/ PageHeader + +- content_for :page_header_title, t('.title') + +/ PageContent +.page_content +  .container-fluid +    .row +      .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-10.col-sm-offset-1 +        = simple_form_for resource, as: resource_name, :url => invitation_path(resource_name), :html => { :method => :put, class: "form-horizontal", id: 'invitation_form' } do |form| +            .row +              .col-lg-12 +                = form.hidden_field :invitation_token + +                = form.input :name +                = form.input :password, as: :password +                = form.input :password_confirmation, as: :password + +            = form.button :submit, value: t('devise.invitations.edit.submit_button'), class: 'btn-info btn-default formSubmitr', form: 'invitation_form' diff --git a/app/views/devise/passwords/edit.html.slim b/app/views/devise/passwords/edit.html.slim index 864a44499..0d18f657c 100644 --- a/app/views/devise/passwords/edit.html.slim +++ b/app/views/devise/passwords/edit.html.slim @@ -1,13 +1,17 @@ -.col-md-offset-2.col-md-8 -  .panel.panel-default -    .panel-heading = t('.title') -    .panel-body -      = simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put, class: "form-horizontal" }) do |f| +/ PageHeader -        = f.input :reset_password_token, as: :hidden -        = f.input :password, as: :password -        = f.input :password_confirmation, as: :password -         -        .form-actions -          = link_to t("cancel"), unauthenticated_root_path, class: 'btn btn-default' -          = f.button :submit, :value => t("devise.passwords.edit.commit"), class: 'btn-info'
\ No newline at end of file +- content_for :page_header_title, t('.title') + +/ PageContent +.page_content +  .container-fluid +    .row +      .col-lg-8.col-lg-offset-2.col-md-8.col-md-offset-2.col-sm-10.col-sm-offset-1 +        = simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put, class: "form-horizontal", id: 'password_form' }) do |f| +          .row +            .col-lg-12 +              = f.input :reset_password_token, as: :hidden +              = f.input :password, as: :password +              = f.input :password_confirmation, as: :password + +          = f.button :submit, :value => t("devise.passwords.edit.commit"), class: 'btn btn-default formSubmitr', form: 'password_form' diff --git a/app/views/devise/passwords/new.html.slim b/app/views/devise/passwords/new.html.slim index 6e03595fc..303f78f0e 100644 --- a/app/views/devise/passwords/new.html.slim +++ b/app/views/devise/passwords/new.html.slim @@ -1,6 +1,6 @@  / PageHeader -= pageheader '', t('.title') +- content_for :page_header_title, t('.title')  / PageContent  .page_content @@ -12,4 +12,4 @@              .col-lg-12                = form.input :email, :as => :email, placeholder: 'user@domain.com' -          = form.button :submit, :value => t("devise.passwords.new.commit"), class: 'btn btn-default formSubmitr', form: 'invitation_form' +          = form.button :submit, :value => t("devise.passwords.new.commit"), class: 'btn btn-default formSubmitr', form: 'password_form' diff --git a/app/views/devise/sessions/new.html.slim b/app/views/devise/sessions/new.html.slim index 0ed17e24a..a812726e5 100644 --- a/app/views/devise/sessions/new.html.slim +++ b/app/views/devise/sessions/new.html.slim @@ -1,3 +1,5 @@ +- content_for :page_header_title, t('.title') +  .page_content#devise    .container-fluid      #sessions_new.row diff --git a/app/views/layouts/navigation/_main_nav_top.html.slim b/app/views/layouts/navigation/_main_nav_top.html.slim index d6c849d3f..363a89b48 100644 --- a/app/views/layouts/navigation/_main_nav_top.html.slim +++ b/app/views/layouts/navigation/_main_nav_top.html.slim @@ -11,7 +11,7 @@            span.fa.fa-lg.fa-tasks          = link_to '#', class: 'menu-item', data: { panel: 'toggle', target: '#profile_panel' }, title: 'Profil' do -          span = current_user.username +          span = current_user.name            span.fa.fa-lg.fa-user diff --git a/app/views/line_referentials/show.html.slim b/app/views/line_referentials/show.html.slim index b4b32bc52..763eb076e 100644 --- a/app/views/line_referentials/show.html.slim +++ b/app/views/line_referentials/show.html.slim @@ -1,7 +1,8 @@  - breadcrumb :line_referential, @line_referential  - page_header_content_for @line_referential -- content_for :page_header_actions do -  = link_to(t('actions.sync'), sync_line_referential_path(@line_referential), method: :post, class: 'btn btn-default') +- if policy(@line_referential).synchronize? +  - content_for :page_header_actions do +    = link_to(t('actions.sync'), sync_line_referential_path(@line_referential), method: :post, class: 'btn btn-default')  - content_for :page_header_content do    .row.mb-md diff --git a/app/views/referential_companies/index.html.slim b/app/views/referential_companies/index.html.slim index de0f7de69..07de2bc9d 100644 --- a/app/views/referential_companies/index.html.slim +++ b/app/views/referential_companies/index.html.slim @@ -46,7 +46,7 @@                  attribute: 'url' \                ) \              ], -            links: [:show, :edit], +            links: [:show],              cls: 'table has-search'            = new_pagination @companies, 'pull-right' diff --git a/app/views/stop_area_referentials/show.html.slim b/app/views/stop_area_referentials/show.html.slim index d43333fd9..911006c39 100644 --- a/app/views/stop_area_referentials/show.html.slim +++ b/app/views/stop_area_referentials/show.html.slim @@ -1,13 +1,14 @@  - breadcrumb :stop_area_referential, @stop_area_referential -- content_for :page_header_actions do -  = link_to(t('actions.sync'), sync_stop_area_referential_path(@stop_area_referential), method: :post, class: 'btn btn-default') +- if policy(@stop_area_referential).synchronize? +  - content_for :page_header_actions do +    = link_to(t('actions.sync'), sync_stop_area_referential_path(@stop_area_referential), method: :post, class: 'btn btn-default')  - content_for :page_header_content do    .row.mb-md      .col-lg-12.text-right        = link_to stop_area_referential_stop_areas_path(@stop_area_referential), class: 'btn btn-primary' do          = Referential.human_attribute_name(:stop_areas) -        em.small = " (#{@stop_area_referential.stop_areas.size})" +        em.small = " (#{@stop_area_referential.stop_areas.count})"  - page_header_content_for @stop_area_referential  .page_content diff --git a/app/views/stop_areas/_filters.html.slim b/app/views/stop_areas/_filters.html.slim index 3b99f377c..90368dff4 100644 --- a/app/views/stop_areas/_filters.html.slim +++ b/app/views/stop_areas/_filters.html.slim @@ -12,7 +12,7 @@      .form-group.togglable        = f.label Chouette::StopArea.human_attribute_name(:area_type), required: false, class: 'control-label' -      = f.input :area_type_eq_any, collection: Chouette::StopArea.area_type.options.sort, as: :check_boxes, label: false, label_method: lambda{|w| ("<span>" + t("enumerize.stop_area.area_type.#{w[1]}") + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' } +      = f.input :area_type_eq_any, collection: Chouette::AreaType.options, as: :check_boxes, label: false, label_method: lambda{|w| ("<span>" + w[0] + "</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' }    .actions      = link_to 'Effacer', @workbench, class: 'btn btn-link' diff --git a/app/views/stop_areas/_form.html.slim b/app/views/stop_areas/_form.html.slim index 20c7c0468..ac2cb4e87 100644 --- a/app/views/stop_areas/_form.html.slim +++ b/app/views/stop_areas/_form.html.slim @@ -6,7 +6,7 @@          /= @map.to_html          = f.input :id, as: :hidden          = f.input :name, :input_html => {:title => t("formtastic.titles#{format_restriction_for_locales(@referential)}.stop_area.name")} -        = f.input :area_type, as: :select, :input_html => {:disabled => !@stop_area.new_record?}, :collection => Chouette::StopArea.area_type.options, :include_blank => false +        = f.input :area_type, as: :select, :input_html => {:disabled => !@stop_area.new_record?}, :collection => Chouette::AreaType.options, :include_blank => false          .location_info            h3 = t("stop_areas.stop_area.localisation") diff --git a/app/views/stop_areas/index.html.slim b/app/views/stop_areas/index.html.slim index c4d880081..63e99fd75 100644 --- a/app/views/stop_areas/index.html.slim +++ b/app/views/stop_areas/index.html.slim @@ -24,7 +24,7 @@                  key: :name, \                  attribute: 'name', \                  link_to: lambda do |stop_area| \ -                  referential_stop_area_path( \ +                  stop_area_referential_stop_area_path( \                      @stop_area_referential, \                      stop_area \                    ) \ @@ -48,10 +48,10 @@                ), \                TableBuilderHelper::Column.new( \                  key: :area_type, \ -                attribute: Proc.new { |s| (s.area_type.nil? ? '-' : t("enumerize.stop_area.area_type.#{s.try(:area_type)}")) } \ +                attribute: Proc.new { |s| Chouette::AreaType.find(s.area_type).try :label } \                ), \              ], -            links: [:show, :edit, :delete], +            links: [:show],              cls: 'table has-filter has-search'            = new_pagination @stop_areas, 'pull-right' diff --git a/app/views/stop_areas/show.html.slim b/app/views/stop_areas/show.html.slim index af673bb25..1b1209a68 100644 --- a/app/views/stop_areas/show.html.slim +++ b/app/views/stop_areas/show.html.slim @@ -17,7 +17,7 @@        .col-lg-6.col-md-6.col-sm-12.col-xs-12          = definition_list t('metadatas'),            { t('id_reflex') => @stop_area.get_objectid.short_id, -            @stop_area.human_attribute_name(:stop_area_type) => t("area_types.label.#{@stop_area.stop_area_type}"), +            @stop_area.human_attribute_name(:stop_area_type) => Chouette::AreaType.find(@stop_area.area_type).try(:label),              @stop_area.human_attribute_name(:registration_number) => @stop_area.registration_number,              'Coordonnées' => geo_data(@stop_area, @stop_area_referential),              @stop_area.human_attribute_name(:zip_code) => @stop_area.zip_code, diff --git a/app/views/stop_points/_stop_point.html.slim b/app/views/stop_points/_stop_point.html.slim index ca86e339a..e54158cef 100644 --- a/app/views/stop_points/_stop_point.html.slim +++ b/app/views/stop_points/_stop_point.html.slim @@ -5,7 +5,7 @@          = link_to [@referential, stop_point.stop_area], class: "preview", title: "#{Chouette::StopArea.model_name.human.capitalize} #{stop_point.stop_area.name}" do            span.name              span.label.label-primary = stop_point.position + 1 -            = image_tag "map/" + stop_point.stop_area.stop_area_type + ".png" +            = image_tag "map/" + stop_point.stop_area.area_type + ".png"              = truncate(stop_point.stop_area.name, length: 20)    .panel-body @@ -27,4 +27,4 @@          = t(".no_object")        - else          - stop_point.stop_area.lines.each do |line| -          span.label.label-default.line = line.number || truncate( line.name, length: 4 )
\ No newline at end of file +          span.label.label-default.line = line.number || truncate( line.name, length: 4 ) diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim index af312fc08..1c82c34b7 100644 --- a/app/views/workbenches/show.html.slim +++ b/app/views/workbenches/show.html.slim @@ -57,7 +57,7 @@                    attribute: '' \                  ) \                ], -              selectable: true, +              selectable: ->(ref){ @workbench.referentials.include?(ref) },                links: [:show, :edit],                cls: 'table has-filter has-search' diff --git a/app/workers/referential_cloning_worker.rb b/app/workers/referential_cloning_worker.rb index 6592160ec..e20148055 100644 --- a/app/workers/referential_cloning_worker.rb +++ b/app/workers/referential_cloning_worker.rb @@ -1,32 +1,7 @@  class ReferentialCloningWorker    include Sidekiq::Worker -  # Replace default apartment created schema with clone schema from source referential    def perform(id) -    ref_cloning = ReferentialCloning.find id - -    source_schema = ref_cloning.source_referential.slug -    target_schema = ref_cloning.target_referential.slug - -    clone_schema ref_cloning, source_schema, target_schema -  end - -  private - -  def clone_schema ref_cloning, source_schema, target_schema -    ref_cloning.run! - -    AF83::SchemaCloner -      .new(source_schema, target_schema)  -      .clone_schema - -    ref_cloning.successful! -  rescue Exception => e -    Rails.logger.error "ReferentialCloningWorker : #{e}" -    ref_cloning.failed! -  end - -  def execute_sql sql -    ActiveRecord::Base.connection.execute sql +    ReferentialCloning.find(id).clone!    end  end diff --git a/config/deploy.rb b/config/deploy.rb index a8d44d3e5..33771507f 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -90,6 +90,6 @@ namespace :deploy do    desc "Run db:seed"    task :seed do -    run "cd #{current_path} && #{bundle_cmd} exec /var/lib/gems/2.2.0/bin/rake db:seed RAILS_ENV=#{rails_env}" +    run "cd #{current_path} && #{rake} db:seed RAILS_ENV=#{rails_env}"    end  end diff --git a/config/locales/calendars.en.yml b/config/locales/calendars.en.yml index 0076e5207..d3cc57677 100644 --- a/config/locales/calendars.en.yml +++ b/config/locales/calendars.en.yml @@ -56,8 +56,9 @@ en:            end: End    activerecord:      models: -      one: calendar -      other: calendars +      calendar: +        one: calendar +        other: calendars      attributes:        calendar:          name: Name diff --git a/config/locales/calendars.fr.yml b/config/locales/calendars.fr.yml index fddb47d64..fc895bf89 100644 --- a/config/locales/calendars.fr.yml +++ b/config/locales/calendars.fr.yml @@ -56,8 +56,9 @@ fr:            end: Fin    activerecord:      models: -      one: "calendrier" -      other: "calendriers" +      calendar: +        one: "calendrier" +        other: "calendriers"      attributes:        calendar:          name: Nom diff --git a/config/locales/compliance_check_sets.fr.yml b/config/locales/compliance_check_sets.fr.yml index 8f1c066e7..8c4561ae9 100644 --- a/config/locales/compliance_check_sets.fr.yml +++ b/config/locales/compliance_check_sets.fr.yml @@ -10,7 +10,7 @@ fr:            name_compliance_control_set: Indiquez le nom d'un jeu de contrôle            error_period_filter: La date de fin doit être supérieure ou égale à la date de début0      index: -      title: "Liste des jeux de contrôles"       +      title: "Liste des rapports de contrôles"      search_no_results: Aucun rapport de contrôle ne correspond à votre recherche      executed:        title: Jeu de contrôles exécutés %{name} @@ -24,7 +24,7 @@ fr:    activerecord:      attributes:        compliance_check_set: -        ref: réf +        ref: Ref          creation_date: Date et heure de création          associated_object: Objet associé          assigned_to: Affectation diff --git a/config/locales/imports.en.yml b/config/locales/imports.en.yml index 0bb54d90d..462b17196 100644 --- a/config/locales/imports.en.yml +++ b/config/locales/imports.en.yml @@ -74,3 +74,7 @@ en:          max_distance_for_connection_link: "Max distance for connection link"          ignore_last_word: "ignore last word"          ignore_end_chars: "ignore last chars" +  flash: +    imports: +      create: +        notice: "The import is in progress. Please wait and refresh the page in a few moments." diff --git a/config/locales/imports.fr.yml b/config/locales/imports.fr.yml index 207f5cc31..b545f90df 100644 --- a/config/locales/imports.fr.yml +++ b/config/locales/imports.fr.yml @@ -74,3 +74,7 @@ fr:          max_distance_for_connection_link: "Distance max pour créer les correspondances"          ignore_last_word: "ignorer le dernier mot"          ignore_end_chars: "ignorer les n derniers caractères" +  flash: +    imports: +      create: +        notice: "L'import est en cours, veuillez patienter. Actualiser votre page si vous voulez voir l'avancement de votre traitement." diff --git a/config/locales/lines.fr.yml b/config/locales/lines.fr.yml index 35f8792f4..36254d754 100644 --- a/config/locales/lines.fr.yml +++ b/config/locales/lines.fr.yml @@ -74,7 +74,7 @@ fr:          deactivated: "Activé"          name: "Nom de la ligne"          published_name: "Nom public" -        number: "Nom court" +        number: "Numéro"          transport_mode: "Mode de transport"          transport_submode: "Sous mode de transport"          seasonal: "Saisonnière" diff --git a/config/locales/referentials.en.yml b/config/locales/referentials.en.yml index 8420e9539..f41e35446 100644 --- a/config/locales/referentials.en.yml +++ b/config/locales/referentials.en.yml @@ -5,7 +5,6 @@ en:        name: 'Search by name'        line: 'Seach by associated lines'      search_no_results: 'No data space matching your query' -    operation_in_progress: The validation process is in progress      error_period_filter: "The period filter must have valid bounding dates"      index:        title: 'Data spaces' @@ -126,6 +125,8 @@ en:    notice:      referentials:        deleted: "Datasets has been successfully destroyed" +      duplicate: "The duplication is in progress. Please wait and refresh the page in a few moments." +      validate: "The validation is in progress. Please wait and refresh the page in a few moments."      referential:        archived: "The data space has been successfully archived"        unarchived: "The data space has been successfully unarchived" diff --git a/config/locales/referentials.fr.yml b/config/locales/referentials.fr.yml index ec7ed776d..9250a033c 100644 --- a/config/locales/referentials.fr.yml +++ b/config/locales/referentials.fr.yml @@ -5,7 +5,6 @@ fr:        name: 'Indiquez un nom de jeu de données...'        line: 'Indiquez une ligne...'      search_no_results: 'Aucun jeu de données ne correspond à votre recherche' -    operation_in_progress: L'opération de validation est en cours      error_period_filter: "Le filtre par période doit contenir une date de début et de fin valides"      index:        title: 'Jeux de données' @@ -124,6 +123,8 @@ fr:    notice:      referentials:        deleted: "Les jeux de données on été supprimés" +      duplicate: "La duplication est en cours, veuillez patienter. Actualiser votre page si vous voulez voir l'avancement de votre traitement." +      validate: "La validation est en cours, veuillez patienter. Actualiser votre page si vous voulez voir l'avancement de votre traitement."      referential:        archived: "Le jeu de données a été correctement conservé"        unarchived: "Le jeu de données a été correctement déconservé" diff --git a/config/locales/stop_areas.en.yml b/config/locales/stop_areas.en.yml index 324294892..54a5ebae5 100644 --- a/config/locales/stop_areas.en.yml +++ b/config/locales/stop_areas.en.yml @@ -15,7 +15,7 @@ en:      actions:        new: "Add a new stop"        edit: "Edit this stop" -      destroy: "Remove this stop" +      destroy: "Remove"        deleted_at: "Activated"        destroy_confirm: "Are you sure you want destroy this stop and all of his children ?"        select_parent: "Create or modify the relation child -> parent" diff --git a/config/locales/stop_areas.fr.yml b/config/locales/stop_areas.fr.yml index bf4dd832f..f96a2e564 100644 --- a/config/locales/stop_areas.fr.yml +++ b/config/locales/stop_areas.fr.yml @@ -15,7 +15,7 @@ fr:      actions:        new: "Ajouter un arrêt"        edit: "Editer cet arrêt" -      destroy: "Supprimer cet arrêt" +      destroy: "Supprimer"        deleted_at: "Activé"        destroy_confirm: "Etes vous sûr de supprimer cet arrêt ainsi que tous ses fils?"        select_parent: "Créer ou éditer la relation enfant -> parent" diff --git a/db/migrate/20171214130636_enable_unaccent_extension.rb b/db/migrate/20171214130636_enable_unaccent_extension.rb new file mode 100644 index 000000000..f7411b1f4 --- /dev/null +++ b/db/migrate/20171214130636_enable_unaccent_extension.rb @@ -0,0 +1,9 @@ +class EnableUnaccentExtension < ActiveRecord::Migration +  def up +    execute 'CREATE EXTENSION IF NOT EXISTS unaccent SCHEMA shared_extensions;' +  end + +  def down +    execute 'DROP EXTENSION IF EXISTS unaccent SCHEMA shared_extensions;' +  end +end diff --git a/db/schema.rb b/db/schema.rb index 4a04dac26..f2642f8fc 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,12 +11,13 @@  #  # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20171130180144) do +ActiveRecord::Schema.define(version: 20171214130636) do    # These are extensions that must be enabled in order to support this database    enable_extension "plpgsql"    enable_extension "postgis"    enable_extension "hstore" +  enable_extension "unaccent"    create_table "access_links", id: :bigserial, force: :cascade do |t|      t.integer  "access_point_id",                        limit: 8 diff --git a/lib/stif/permission_translator.rb b/lib/stif/permission_translator.rb index 2d267bc7b..4acf42884 100644 --- a/lib/stif/permission_translator.rb +++ b/lib/stif/permission_translator.rb @@ -1,11 +1,11 @@  module Stif    module PermissionTranslator extend self -    def translate(sso_extra_permissions) -      sso_extra_permissions -        .sort +    def translate(sso_extra_permissions, organisation=nil) +      permissions = sso_extra_permissions.sort          .flat_map(&method(:extra_permission_translation)) -        .uniq +      permissions += extra_organisation_permissions(organisation) +      permissions.uniq      end      private @@ -49,5 +49,12 @@ module Stif          "boiv:edit-offer" => all_destructive_permissions + %w{sessions.create},        }      end + +    def extra_organisation_permissions organisation +      if organisation&.name&.downcase == "stif" +        return %w{calendars.share stop_area_referentials.synchronize line_referentials.synchronize} +      end +      [] +    end    end  end diff --git a/spec/controllers/autocomplete_stop_areas_controller_spec.rb b/spec/controllers/autocomplete_stop_areas_controller_spec.rb new file mode 100644 index 000000000..50fc877dd --- /dev/null +++ b/spec/controllers/autocomplete_stop_areas_controller_spec.rb @@ -0,0 +1,29 @@ +require 'rails_helper' + +RSpec.describe AutocompleteStopAreasController, type: :controller do +  login_user + +  let(:referential) { Referential.first } +  let!(:stop_area) { create :stop_area, name: 'écolà militaire' } + +  describe 'GET #index' do +    it 'should be successful' do +      get :index, referential_id: referential.id +      expect(response).to be_success +    end + +    context 'search by name' do +      it 'should be successful' do +        get :index, referential_id: referential.id, q: 'écolà', :format => :json +        expect(response).to be_success +        expect(assigns(:stop_areas)).to eq([stop_area]) +      end + +      it 'should be accent insensitive' do +        get :index, referential_id: referential.id, q: 'ecola', :format => :json +        expect(response).to be_success +        expect(assigns(:stop_areas)).to eq([stop_area]) +      end +    end +  end +end diff --git a/spec/controllers/imports_controller_spec.rb b/spec/controllers/imports_controller_spec.rb index 22be9f6ed..08495ff47 100644 --- a/spec/controllers/imports_controller_spec.rb +++ b/spec/controllers/imports_controller_spec.rb @@ -17,6 +17,20 @@ RSpec.describe ImportsController, :type => :controller do      end    end +  describe "POST #create" do +    it "displays a flash message" do +      post :create, workbench_id: workbench.id, +        import: { +          name: 'Offre', +          file: fixture_file_upload('nozip.zip') +        } + +      expect(controller).to set_flash[:notice].to( +        I18n.t('flash.imports.create.notice') +      ) +    end +  end +    describe 'GET #download' do      it 'should be successful' do        get :download, workbench_id: workbench.id, id: import.id, token: import.token_download diff --git a/spec/controllers/line_referentials_controller_spec.rb b/spec/controllers/line_referentials_controller_spec.rb index aee24b0fa..17ffb670d 100644 --- a/spec/controllers/line_referentials_controller_spec.rb +++ b/spec/controllers/line_referentials_controller_spec.rb @@ -1,3 +1,19 @@  RSpec.describe LineReferentialsController, :type => :controller do +  login_user +  let(:line_referential) { create :line_referential } + +  describe 'PUT sync' do +    let(:request){ put :sync, id: line_referential.id } + +    it 'should redirect to 403' do +       expect(request).to redirect_to "/403" +    end + +    with_permission "line_referentials.synchronize" do +      it 'returns HTTP success' do +        expect(request).to redirect_to [line_referential] +      end +    end +  end  end diff --git a/spec/controllers/referentials_controller_spec.rb b/spec/controllers/referentials_controller_spec.rb index fba063085..4050a8812 100644 --- a/spec/controllers/referentials_controller_spec.rb +++ b/spec/controllers/referentials_controller_spec.rb @@ -30,4 +30,33 @@ describe ReferentialsController, :type => :controller do        expect(assigns[:compliance_control_sets]).to eq([compliance_control_set])      end    end + +  describe "POST #validate" do +    it "displays a flash message" do +      post :validate, id: referential.id, params: { +        compliance_control_set: create(:compliance_control_set).id +      } + +      expect(controller).to set_flash[:notice].to( +        I18n.t('notice.referentials.validate') +      ) +    end +  end + +  describe "POST #create" do +    context "when duplicating" do +      it "displays a flash message" do +        post :create, +          from: referential.id, +          current_workbench_id: referential.workbench_id, +          referential: { +            name: 'Duplicated' +          } + +        expect(controller).to set_flash[:notice].to( +          I18n.t('notice.referentials.duplicate') +        ) +      end +    end +  end  end diff --git a/spec/controllers/stop_area_referentials_controller_spec.rb b/spec/controllers/stop_area_referentials_controller_spec.rb new file mode 100644 index 000000000..c8d7e1736 --- /dev/null +++ b/spec/controllers/stop_area_referentials_controller_spec.rb @@ -0,0 +1,17 @@ +RSpec.describe StopAreaReferentialsController, :type => :controller do +  login_user + +  let(:stop_area_referential) { create :stop_area_referential } + +  describe 'PUT sync' do +    let(:request){ put :sync, id: stop_area_referential.id } + +    it { request.should redirect_to "/403" } + +    with_permission "stop_area_referentials.synchronize" do +      it 'returns HTTP success' do +        expect(request).to redirect_to [stop_area_referential] +      end +    end +  end +end diff --git a/spec/factories/chouette_stop_areas.rb b/spec/factories/chouette_stop_areas.rb index 8b64c227b..7f937e361 100644 --- a/spec/factories/chouette_stop_areas.rb +++ b/spec/factories/chouette_stop_areas.rb @@ -3,7 +3,7 @@ FactoryGirl.define do      sequence(:objectid) { |n| "FR:#{n}:ZDE:#{n}:STIF" }      sequence(:name) { |n| "stop_area_#{n}" }      sequence(:registration_number) { |n| "test-#{n}" } -    area_type { Chouette::StopArea.area_type.values.sample } +    area_type { Chouette::AreaType.all.sample }      latitude {10.0 * rand}      longitude {10.0 * rand} diff --git a/spec/features/compliance_check_sets_spec.rb b/spec/features/compliance_check_sets_spec.rb index 7ba64b6b8..6b7d7a4f8 100644 --- a/spec/features/compliance_check_sets_spec.rb +++ b/spec/features/compliance_check_sets_spec.rb @@ -29,7 +29,7 @@ RSpec.describe "ComplianceCheckSets", type: :feature do      it 'we can see the expected content' do        # Breadcrumbs -      expect_breadcrumb_links "Accueil", "Gestion de l'offre", "Liste des jeux de contrôles" +      expect_breadcrumb_links "Accueil", "Gestion de l'offre", "Liste des rapports de contrôles"        # Headline        expect( page ).to have_content("Jeu de contrôles exécutés #{compliance_check_set.name}") @@ -49,10 +49,10 @@ RSpec.describe "ComplianceCheckSets", type: :feature do        # Direct Children        within(:xpath, xpath_for_div_of_block) do          direct_checks.each do | direct_check | -          expect( page ).to have_content( direct_check.code )  -          expect( page ).to have_content( direct_check.name )  -          expect( page ).to have_content( direct_check.criticity )  -          expect( page ).to have_content( direct_check.comment )  +          expect( page ).to have_content( direct_check.code ) +          expect( page ).to have_content( direct_check.name ) +          expect( page ).to have_content( direct_check.criticity ) +          expect( page ).to have_content( direct_check.comment )          end        end @@ -60,10 +60,10 @@ RSpec.describe "ComplianceCheckSets", type: :feature do        compliance_check_set.compliance_check_blocks.each do | block |          within(:xpath, xpath_for_div_of_block(block)) do            block.compliance_checks.each do | check | -            expect( page ).to have_content( check.code )  -            expect( page ).to have_content( check.name )  -            expect( page ).to have_content( check.criticity )  -            expect( page ).to have_content( check.comment )  +            expect( page ).to have_content( check.code ) +            expect( page ).to have_content( check.name ) +            expect( page ).to have_content( check.criticity ) +            expect( page ).to have_content( check.comment )            end          end        end @@ -86,7 +86,7 @@ RSpec.describe "ComplianceCheckSets", type: :feature do        all_checks.each do | check |          expect( page ).to have_content(check.code)        end -       +      end    end diff --git a/spec/helpers/table_builder_helper_spec.rb b/spec/helpers/table_builder_helper_spec.rb index 3b0a18379..83b746d4b 100644 --- a/spec/helpers/table_builder_helper_spec.rb +++ b/spec/helpers/table_builder_helper_spec.rb @@ -59,7 +59,7 @@ describe TableBuilderHelper, type: :helper do          </tr>      </thead>      <tbody> -        <tr> +        <tr class="referential-#{referential.id}">              <td>                  <div class="checkbox"><input type="checkbox" name="#{referential.id}" id="#{referential.id}" value="#{referential.id}" /><label for="#{referential.id}"></label></div>              </td> @@ -213,7 +213,7 @@ describe TableBuilderHelper, type: :helper do          </tr>      </thead>      <tbody> -        <tr> +        <tr class="company-#{company.id}">              <td>#{company.get_objectid.local_id}</td>              <td title="Voir"><a href="/referentials/#{referential.id}/companies/#{company.id}">#{company.name}</a></td>              <td></td> @@ -326,7 +326,7 @@ describe TableBuilderHelper, type: :helper do          </tr>      </thead>      <tbody> -        <tr> +        <tr class="company-#{company.id}">              <td>#{company.get_objectid.local_id}</td>              <td title="Voir"><a href="/referentials/#{referential.id}/companies/#{company.id}">#{company.name}</a></td>              <td></td> @@ -381,5 +381,86 @@ describe TableBuilderHelper, type: :helper do        expect(beautified_html).to eq(expected.chomp)      end + +    context "on a single row" do +      let(:referential){ build_stubbed :referential } +      let(:other_referential){ build_stubbed :referential } +      let(:user_context){ +        UserContext.new( +          build_stubbed( +            :user, +            organisation: referential.organisation, +            permissions: [ +              'referentials.create', +              'referentials.update', +              'referentials.destroy', +            ] +          ), +          referential: referential +        ) +      } +      let(:columns){ +        [ +          TableBuilderHelper::Column.new( +            key: :name, +            attribute: 'name' +          ), +        ] +      } +      let(:item){ referential.decorate } +      let(:other_item){ other_referential.decorate } +      let(:selectable){ false } +      let(:links){ [:show] } +      let(:overhead){ [] } +      let(:model_name){ "referential" } +      let(:other_tr){ helper.send(:tr, other_item, columns, selectable, links, overhead, model_name) } +      let(:items){ [item, other_item] } + +      before(:each){ +        allow(helper).to receive(:current_user).and_return(user_context) +      } + +      context "with all rows non-selectable" do +        let(:selectable){ false } +        it "sets all rows as non selectable" do +          items.each do |i| +            tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name) +            klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}" +            selector = "tr.#{klass} [type=checkbox]" +            expect(tr).to_not have_selector selector +          end +        end +      end + +      context "with all rows selectable" do +        let(:selectable){ true } +        it "adds a checkbox in all rows" do +          items.each do |i| +            tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name) +            klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}" +            selector = "tr.#{klass} [type=checkbox]" +            expect(tr).to have_selector selector +          end +        end +      end + +      context "with THIS row non selectable" do +        let(:selectable){ ->(i){ i.id != item.id } } +        it "adds a checkbox in all rows" do +          items.each do |i| +            tr = helper.send(:tr, i, columns, selectable, links, overhead, model_name) +            klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{i.id}" +            selector = "tr.#{klass} [type=checkbox]" +            expect(tr).to have_selector selector +          end +        end +        it "disables this rows checkbox" do +          tr = helper.send(:tr, item, columns, selectable, links, overhead, model_name) +          klass = "#{TableBuilderHelper.item_row_class_name([referential])}-#{item.id}" +          selector = "tr.#{klass} [type=checkbox][disabled]" +          expect(tr).to have_selector selector +        end +      end +    end    end  end diff --git a/spec/lib/stif/permission_translator_spec.rb b/spec/lib/stif/permission_translator_spec.rb index ae1a2d1d5..9771af187 100644 --- a/spec/lib/stif/permission_translator_spec.rb +++ b/spec/lib/stif/permission_translator_spec.rb @@ -1,3 +1,4 @@ +# coding: utf-8  RSpec.describe Stif::PermissionTranslator do    context "No SSO Permissions" do @@ -42,4 +43,19 @@ RSpec.describe Stif::PermissionTranslator do        ).to match_array(Support::Permissions.all_permissions)      end    end + +  context "For the STIF organisation" do +    let(:organisation){ build_stubbed :organisation, name: "STIF" } +    let(:permissions){ %w{calendars.share stop_area_referentials.synchronize line_referentials.synchronize}.sort } +    it "adds the STIF permission" do +      expect(described_class.translate([], organisation).sort).to eq permissions +    end + +    context "with the case changed" do +      let(:organisation){ build_stubbed :organisation, name: "StiF" } +      it "adds the STIF permission" do +        expect(described_class.translate([], organisation).sort).to eq permissions +      end +    end +  end  end diff --git a/spec/models/chouette/area_type_spec.rb b/spec/models/chouette/area_type_spec.rb new file mode 100644 index 000000000..470e3a066 --- /dev/null +++ b/spec/models/chouette/area_type_spec.rb @@ -0,0 +1,32 @@ +require "rails_helper" + +RSpec.describe Chouette::AreaType do + +  describe "::ALL" do +    it "includes all supported types" do +      expect(Chouette::AreaType::ALL).to match_array( %i(zdep zder zdlp zdlr lda) ) +    end +  end + +  describe ".find" do +    it "returns nil if the given code is unknown" do +      expect(Chouette::AreaType.find('dummy')).to be_nil +    end + +    it "returns an AreaType associated to the code" do +      expect(Chouette::AreaType.find('zdep').code).to eq :zdep +    end +  end + +  describe ".options" do +    before do +      Chouette::AreaType.reset_caches! +    end + +    it "returns an array with label and code for each type" do +      allow(Chouette::AreaType).to receive(:all).and_return(%i{zdep lda}) +      expect(Chouette::AreaType.options).to eq([["ZDEp", :zdep], ["LDA", :lda]]) +    end +  end + +end diff --git a/spec/models/referential_cloning_spec.rb b/spec/models/referential_cloning_spec.rb index 5acd433ec..4327c98aa 100644 --- a/spec/models/referential_cloning_spec.rb +++ b/spec/models/referential_cloning_spec.rb @@ -1,6 +1,7 @@  require 'spec_helper'  RSpec.describe ReferentialCloning, :type => :model do +    it 'should have a valid factory' do      expect(FactoryGirl.build(:referential_cloning)).to be_valid    end @@ -8,11 +9,69 @@ RSpec.describe ReferentialCloning, :type => :model do    it { should belong_to :source_referential }    it { should belong_to :target_referential } -  describe "ReferentialCloningWorker" do +  describe 'after commit' do +    let(:referential_cloning) { FactoryGirl.create(:referential_cloning) } + +    it 'invoke clone method' do +    expect(referential_cloning).to receive(:clone) +    referential_cloning.run_callbacks(:commit) +    end +  end + +  describe '#clone' do      let(:referential_cloning) { FactoryGirl.create(:referential_cloning) }      it "should schedule a job in worker" do -      expect{referential_cloning.run_callbacks(:commit)}.to change {ReferentialCloningWorker.jobs.count}.by(1) +      expect{referential_cloning.clone}.to change {ReferentialCloningWorker.jobs.count}.by(1) +    end +  end + +  describe '#clone!' do +    let(:source_referential) { Referential.new slug: "source"} +    let(:target_referential) { Referential.new slug: "target"} +    let(:referential_cloning) do +      ReferentialCloning.new source_referential: source_referential, +                             target_referential: target_referential +    end + +    let(:cloner) { double } + +    before do +      allow(AF83::SchemaCloner).to receive(:new).and_return cloner +      allow(cloner).to receive(:clone_schema)      end + +    it 'creates a schema cloner with source and target schemas and clone schema' do +      expect(AF83::SchemaCloner).to receive(:new).with(source_referential.slug, target_referential.slug).and_return(cloner) +      expect(cloner).to receive(:clone_schema) + +      referential_cloning.clone! +    end + +    context 'when clone_schema is performed without error' do +      it "should have successful status" do +        referential_cloning.clone! +        expect(referential_cloning.status).to eq("successful") +      end +    end + +    context 'when clone_schema raises an error' do +      it "should have failed status" do +        expect(cloner).to receive(:clone_schema).and_raise("#fail") +        referential_cloning.clone! +        expect(referential_cloning.status).to eq("failed") +      end +    end + +    it "defines started_at" do +      referential_cloning.clone! +      expect(referential_cloning.started_at).not_to be_nil +    end + +    it "defines ended_at" do +      referential_cloning.clone! +      expect(referential_cloning.ended_at).not_to be_nil +    end +    end  end diff --git a/spec/policies/calendar_policy_spec.rb b/spec/policies/calendar_policy_spec.rb index 294be8198..144a1c6bb 100644 --- a/spec/policies/calendar_policy_spec.rb +++ b/spec/policies/calendar_policy_spec.rb @@ -5,18 +5,24 @@ RSpec.describe CalendarPolicy, type: :policy do    permissions :create? do -    it_behaves_like 'permitted policy', 'calendars.create', archived: true +    it_behaves_like 'permitted policy', 'calendars.create' +  end +  permissions :share? do +    it_behaves_like 'permitted policy and same organisation', 'calendars.share' +  end +  permissions :share? do +    it_behaves_like 'permitted policy and same organisation', 'calendars.share'    end    permissions :destroy? do -    it_behaves_like 'permitted policy and same organisation', 'calendars.destroy', archived: true +    it_behaves_like 'permitted policy and same organisation', 'calendars.destroy'    end    permissions :edit? do -    it_behaves_like 'permitted policy and same organisation', 'calendars.update', archived: true +    it_behaves_like 'permitted policy and same organisation', 'calendars.update'    end    permissions :new? do -    it_behaves_like 'permitted policy', 'calendars.create', archived: true +    it_behaves_like 'permitted policy', 'calendars.create'    end    permissions :update? do -    it_behaves_like 'permitted policy and same organisation', 'calendars.update', archived: true +    it_behaves_like 'permitted policy and same organisation', 'calendars.update'    end  end diff --git a/spec/policies/line_referential_policy_spec.rb b/spec/policies/line_referential_policy_spec.rb new file mode 100644 index 000000000..7e0a9da8e --- /dev/null +++ b/spec/policies/line_referential_policy_spec.rb @@ -0,0 +1,9 @@ +RSpec.describe LineReferentialPolicy, type: :policy do + +  let( :record ){ build_stubbed :line_referential } +  before { stub_policy_scope(record) } + +  permissions :synchronize? do +    it_behaves_like 'permitted policy', 'line_referentials.synchronize' +  end +end diff --git a/spec/policies/sto_area_referential_policy_spec.rb b/spec/policies/sto_area_referential_policy_spec.rb new file mode 100644 index 000000000..5bd6da427 --- /dev/null +++ b/spec/policies/sto_area_referential_policy_spec.rb @@ -0,0 +1,9 @@ +RSpec.describe StopAreaReferentialPolicy, type: :policy do + +  let( :record ){ build_stubbed :stop_area_referential } +  before { stub_policy_scope(record) } + +  permissions :synchronize? do +    it_behaves_like 'permitted policy', 'stop_area_referentials.synchronize' +  end +end diff --git a/spec/support/controller_spec_helper.rb b/spec/support/controller_spec_helper.rb new file mode 100644 index 000000000..1d0288dea --- /dev/null +++ b/spec/support/controller_spec_helper.rb @@ -0,0 +1,18 @@ +module ControllerSpecHelper +  def with_permission permission, &block +    context "with permission #{permission}" do +      login_user +      before(:each) do +        @user.permissions << permission +        @user.save! +        sign_in @user +      end +      context('', &block) if block_given? +    end +  end + +end + +RSpec.configure do |config| +  config.extend ControllerSpecHelper, type: :controller +end diff --git a/spec/support/integration_spec_helper.rb b/spec/support/integration_spec_helper.rb new file mode 100644 index 000000000..78efb9027 --- /dev/null +++ b/spec/support/integration_spec_helper.rb @@ -0,0 +1,49 @@ +module IntegrationSpecHelper + +  def paginate_collection klass, decorator, page=1 +    ModelDecorator.decorate( klass.page(page), with: decorator ) +  end + +  def build_paginated_collection factory, decorator, opts={} +    count = opts.delete(:count) || 2 +    page = opts.delete(:page) || 1 +    klass = nil +    count.times { klass ||= create(factory, opts).class } +    paginate_collection klass, decorator, page +  end + +  module Methods +    def with_permission permission, &block +      context "with permission #{permission}" do +        let(:permissions){ [permission] } +        context('', &block) if block_given? +      end +    end +  end + +  def self.included into +    into.extend Methods +  end +end + +RSpec.configure do |config| +  config.include IntegrationSpecHelper, type: :view +end + +RSpec::Matchers.define :have_link_for_each_item do |collection, name, href| +  match do |actual| +    collection.each do |item| +      expect(rendered).to have_selector("tr.#{TableBuilderHelper.item_row_class_name(collection)}-#{item.id} .actions a[href='#{href.call(item)}']", count: 1) +    end +  end +  description { "have #{name} link for each item" } +end + +RSpec::Matchers.define :have_the_right_number_of_links do |collection, count| +  match do |actual| +    collection.each do |item| +      expect(rendered).to have_selector("tr.#{TableBuilderHelper.item_row_class_name(collection)}-#{item.id} .actions a", count: count) +    end +  end +  description { "have #{count} links for each item" } +end diff --git a/spec/support/pundit/pundit_view_policy.rb b/spec/support/pundit/pundit_view_policy.rb index b8434cac0..91be0624c 100644 --- a/spec/support/pundit/pundit_view_policy.rb +++ b/spec/support/pundit/pundit_view_policy.rb @@ -1,16 +1,16 @@  module Pundit    module PunditViewPolicy -    extend ActiveSupport::Concern +    def self.included into +      into.let(:permissions){ nil } +      into.let(:organisation){ referential.try(:organisation) } +      into.let(:current_referential){ referential || build_stubbed(:referential) } +      into.let(:current_user){ build_stubbed :user, permissions: permissions, organisation: organisation } +      into.let(:pundit_user){ UserContext.new(current_user, referential: current_referential) } +      into.before do +        allow(view).to receive(:pundit_user) { pundit_user } -    included do -      before do -        controller.singleton_class.class_eval do -          def policy(instance) -            Class.new do -              def method_missing(*args, &block); true; end -            end.new -          end -          helper_method :policy +        allow(view).to receive(:policy) do |instance| +          ::Pundit.policy pundit_user, instance          end        end      end diff --git a/spec/views/connection_links/index.html.erb_spec.rb b/spec/views/connection_links/index.html.erb_spec.rb index a01380094..1f133e31e 100644 --- a/spec/views/connection_links/index.html.erb_spec.rb +++ b/spec/views/connection_links/index.html.erb_spec.rb @@ -17,9 +17,11 @@ describe "/connection_links/index", :type => :view do      end    end -  it "should render a link to create a new group" do -    render -    expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{new_referential_connection_link_path(referential)}']") +  with_permission "connection_links.create" do +    it "should render a link to create a new group" do +      render +      expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{new_referential_connection_link_path(referential)}']") +    end    end  end diff --git a/spec/views/connection_links/show.html.erb_spec.rb b/spec/views/connection_links/show.html.erb_spec.rb deleted file mode 100644 index c04a4f3f1..000000000 --- a/spec/views/connection_links/show.html.erb_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require 'spec_helper' - -describe "/connection_links/show", :type => :view do - -  assign_referential -  let!(:connection_link) { assign(:connection_link, create(:connection_link)) } -  let!(:map) { assign(:map, double(:to_html => '<div id="map"/>'.html_safe)) } - -  before do -    allow(view).to receive_messages(current_organisation: referential.organisation) -  end - -  it "should render h2 with the connection_link name" do -    render -    expect(rendered).to have_selector("h2", :text => Regexp.new(connection_link.name)) -  end - -#  it "should display a map with class 'connection_link'" do -#    pending ": map not yet implemented" -#     render -#     expect(rendered).to have_selector("#map", :class => 'connection_link') -#  end - -  it "should render a link to edit the connection_link" do -    render -    expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{view.edit_referential_connection_link_path(referential, connection_link)}']") -  end - -  it "should render a link to remove the connection_link" do -    render -    expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{view.referential_connection_link_path(referential, connection_link)}'][class='remove']") -  end - -end - diff --git a/spec/views/connection_links/show.html.slim_spec.rb b/spec/views/connection_links/show.html.slim_spec.rb new file mode 100644 index 000000000..afe94fc6c --- /dev/null +++ b/spec/views/connection_links/show.html.slim_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe "/connection_links/show", :type => :view do + +  assign_referential +  let!(:connection_link) { assign(:connection_link, create(:connection_link)) } +  let!(:map) { assign(:map, double(:to_html => '<div id="map"/>'.html_safe)) } + +  before do +    allow(view).to receive_messages(current_organisation: referential.organisation) +  end + +  it "should render h2 with the connection_link name" do +    render +    expect(rendered).to have_selector("h2", :text => Regexp.new(connection_link.name)) +  end + +  with_permission "connection_links.update" do +    it "should render a link to edit the connection_link" do +      render +      expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{view.edit_referential_connection_link_path(referential, connection_link)}']") +    end +  end + +  with_permission "connection_links.destroy" do +    it "should render a link to remove the connection_link" do +      render +      expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{view.referential_connection_link_path(referential, connection_link)}'][class='remove']") +    end +  end + +end diff --git a/spec/views/line_referentials/show.html.slim_spec.rb b/spec/views/line_referentials/show.html.slim_spec.rb new file mode 100644 index 000000000..0516677cb --- /dev/null +++ b/spec/views/line_referentials/show.html.slim_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe "/line_referentials/show", :type => :view do + +  let!(:line_referential) { assign :line_referential, create(:line_referential) } + +  before :each do +    render +  end + +  it "should not present syncing infos and button" do +    expect(view.content_for(:page_header_actions)).to_not have_selector("a[href=\"#{view.sync_line_referential_path(line_referential)}\"]") +    expect(view.content_for(:page_header_meta)).to_not have_selector(".last-update") +  end + +  with_permission "line_referentials.synchronize" do +    it "should present syncing infos and button" do +      expect(view.content_for(:page_header_actions)).to have_selector("a[href=\"#{view.sync_line_referential_path(line_referential)}\"]", count: 1) +      expect(view.content_for(:page_header_meta)).to have_selector(".last-update", count: 1) +    end +  end +end diff --git a/spec/views/line_referentials/stop_area_referentials/show.html.slim_spec.rb b/spec/views/line_referentials/stop_area_referentials/show.html.slim_spec.rb new file mode 100644 index 000000000..71a8d16f5 --- /dev/null +++ b/spec/views/line_referentials/stop_area_referentials/show.html.slim_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe "/stop_area_referentials/show", :type => :view do + +  let!(:stop_area_referential) { assign :stop_area_referential, create(:stop_area_referential) } + +  before :each do +    render +  end + +  it "should not present syncing infos and button" do +    expect(view.content_for(:page_header_actions)).to_not have_selector("a[href=\"#{view.sync_stop_area_referential_path(stop_area_referential)}\"]") +    expect(view.content_for(:page_header_meta)).to_not have_selector(".last-update") +  end + +  with_permission "stop_area_referentials.synchronize" do +    it "should present syncing infos and button" do +      expect(view.content_for(:page_header_actions)).to have_selector("a[href=\"#{view.sync_stop_area_referential_path(stop_area_referential)}\"]", count: 1) +      expect(view.content_for(:page_header_meta)).to have_selector(".last-update", count: 1) +    end +  end +end diff --git a/spec/views/offer_workbenches/show.html.erb_spec.rb b/spec/views/offer_workbenches/show.html.erb_spec.rb index 40b09268a..138a1560d 100644 --- a/spec/views/offer_workbenches/show.html.erb_spec.rb +++ b/spec/views/offer_workbenches/show.html.erb_spec.rb @@ -1,5 +1,56 @@ -require 'rails_helper' +require 'spec_helper' -RSpec.describe "workbenches/show.html.erb", :type => :view do +RSpec::Matchers.define :have_box_for_item do |item, disabled| +  match do |actual| +    klass = "#{TableBuilderHelper.item_row_class_name([item])}-#{item.id}" +    if disabled +      selector = "tr.#{klass} [type=checkbox][disabled][value='#{item.id}']" +    else +      selector = "tr.#{klass} [type=checkbox][value='#{item.id}']:not([disabled])" +    end +    expect(actual).to have_selector(selector, count: 1) +  end +  description { "have a #{disabled ? "disabled ": ""}box for the item ##{item.id}" } +end + +describe "workbenches/show", :type => :view do +  let!(:ids) { ['STIF:CODIFLIGNE:Line:C00840', 'STIF:CODIFLIGNE:Line:C00086'] } +  let!(:lines) { +    ids.map do |id| +      create :line, objectid: id, line_referential: workbench.line_referential +    end +  } +  let!(:workbench){ assign :workbench, create(:workbench) } +  let!(:same_organisation_referential){ create :workbench_referential, workbench: workbench, metadatas: [create(:referential_metadata, lines: lines)] } +  let!(:different_organisation_referential){ create :workbench_referential, metadatas: [create(:referential_metadata, lines: lines)] } +  let!(:referentials){ +    same_organisation_referential && different_organisation_referential +    assign :wbench_refs, paginate_collection(Referential, ReferentialDecorator) +  } +  let!(:q) { assign :q_for_form, Ransack::Search.new(Referential) } +  before :each do +    lines +    controller.request.path_parameters[:id] = workbench.id +    expect(workbench.referentials).to     include same_organisation_referential +    expect(workbench.referentials).to_not include different_organisation_referential +    expect(workbench.all_referentials).to include same_organisation_referential +    expect(workbench.all_referentials).to include different_organisation_referential +    render +  end + +  it { should have_link_for_each_item(referentials, "show", -> (referential){ view.referential_path(referential) }) } + +  context "without permission" do +    it "should disable all the checkboxes" do +      expect(rendered).to have_box_for_item same_organisation_referential, false +      expect(rendered).to have_box_for_item different_organisation_referential, true +    end +  end +  with_permission "referentials.destroy" do +    it "should enable the checkbox for the referential which belongs to the same organisation and disable the other one" do +      expect(rendered).to have_box_for_item same_organisation_referential, false +      expect(rendered).to have_box_for_item different_organisation_referential, true +    end +  end  end diff --git a/spec/views/stop_areas/index.html.erb_spec.rb b/spec/views/stop_areas/index.html.erb_spec.rb deleted file mode 100644 index 2dfae1bfd..000000000 --- a/spec/views/stop_areas/index.html.erb_spec.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'spec_helper' - -describe "/stop_areas/index", :type => :view do - -  let!(:stop_area_referential) { assign :stop_area_referential, create(:stop_area_referential) } -  let!(:stop_areas) { assign :stop_areas, Array.new(2) { create(:stop_area, stop_area_referential: stop_area_referential) }.paginate } -  let!(:q) { assign :q, Ransack::Search.new(Chouette::StopArea) } - -  before :each do -    allow(view).to receive(:link_with_search).and_return("#") -  end - -  # it "should render a show link for each group" do -  #   render -  #   stop_areas.each do |stop_area| -  #     expect(rendered).to have_selector(".stop_area a[href='#{view.stop_area_referential_stop_area_path(stop_area_referential, stop_area)}']", :text => stop_area.name) -  #   end -  # end -  # -  # it "should render a link to create a new group" do -  #   render -  #   expect(view.content_for(:sidebar)).to have_selector(".actions a[href='#{new_stop_area_referential_stop_area_path(stop_area_referential)}']") -  # end - -end diff --git a/spec/views/stop_areas/index.html.slim_spec.rb b/spec/views/stop_areas/index.html.slim_spec.rb new file mode 100644 index 000000000..8daa5eb4b --- /dev/null +++ b/spec/views/stop_areas/index.html.slim_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe "/stop_areas/index", :type => :view do + +  let!(:stop_area_referential) { assign :stop_area_referential, create(:stop_area_referential) } +  let!(:stop_areas) do +    assign :stop_areas, build_paginated_collection(:stop_area, StopAreaDecorator, stop_area_referential: stop_area_referential) +  end +  let!(:q) { assign :q, Ransack::Search.new(Chouette::StopArea) } + +  before :each do +    allow(view).to receive(:link_with_search).and_return("#") +    allow(view).to receive(:collection).and_return(stop_areas) +    allow(view).to receive(:current_referential).and_return(stop_area_referential) +    controller.request.path_parameters[:stop_area_referential_id] = stop_area_referential.id +    render +  end + +  it { should have_link_for_each_item(stop_areas, "show", -> (stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) } +  it { should have_the_right_number_of_links(stop_areas, 1) } + +  with_permission "stop_areas.create" do +    it { should have_link_for_each_item(stop_areas, "show", -> (stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) } +    it { should_not have_link_for_each_item(stop_areas, "create", -> (stop_area){ view.new_stop_area_referential_stop_area_path(stop_area_referential) }) } +    it { should have_the_right_number_of_links(stop_areas, 1) } +  end + +  with_permission "stop_areas.update" do +    it { should have_link_for_each_item(stop_areas, "show", -> (stop_area){ view.stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) } +    it { should have_link_for_each_item(stop_areas, "edit", -> (stop_area){ view.edit_stop_area_referential_stop_area_path(stop_area_referential, stop_area) }) } +    it { should have_the_right_number_of_links(stop_areas, 2) } +  end + +end diff --git a/spec/workers/referential_cloning_worker_spec.rb b/spec/workers/referential_cloning_worker_spec.rb index 7e4a2357a..2b9a54805 100644 --- a/spec/workers/referential_cloning_worker_spec.rb +++ b/spec/workers/referential_cloning_worker_spec.rb @@ -2,52 +2,35 @@ require 'spec_helper'  require 'ostruct'  RSpec.describe ReferentialCloningWorker do +  alias_method :worker, :subject    context "given a referential cloning" do +    let(:id) { double } +    let(:referential_cloning) { double } -    let( :id ){ double } +    it "invokes the clone! method of the associated ReferentialCloning" do +      expect(ReferentialCloning).to receive(:find).with(id).and_return(referential_cloning) +      expect(referential_cloning).to receive(:clone!) -    let( :worker ){ described_class.new } - -    def make_referential(schema_name) -      return OpenStruct.new( slug: schema_name ) -    end - -    let( :source_schema ){ "source_schema" } -    let( :target_schema ){ "target_schema" } -    let( :referential_cloning ){ OpenStruct.new(source_referential: make_referential(source_schema), -                                                target_referential: make_referential(target_schema)) } -    let( :cloner ){ 'cloner' } - - -    before do -      expect( ReferentialCloning ).to receive(:find).with(id).and_return(referential_cloning) -      expect( AF83::SchemaCloner ).to receive(:new).with( source_schema, target_schema ).and_return(cloner) -      expect( cloner ).to receive(:clone_schema) - -      expect( referential_cloning ).to receive(:run!) -    end - -    it "invokes the correct stored procedure, updates the database and the AASM" do -      expect( referential_cloning ).to receive(:successful!)        worker.perform(id)      end    end -  it "should clone an existing Referential" do -    source_referential = create :referential - -    source_referential.switch -    source_time_table = create :time_table +  context 'with existing Referential' do +    it "preserve existing data" do +      source_referential = create :referential -    target_referential = create :referential, created_from: source_referential +      source_referential.switch +      source_time_table = create :time_table -    cloning = ReferentialCloning.create source_referential: source_referential, target_referential: target_referential -    ReferentialCloningWorker.new.perform(cloning) +      target_referential = create :referential, created_from: source_referential -    target_referential.switch -    expect(Chouette::TimeTable.where(objectid: source_time_table.objectid).exists?) -  end +      cloning = ReferentialCloning.create source_referential: source_referential, target_referential: target_referential +      worker.perform(cloning.id) +      target_referential.switch +      expect(Chouette::TimeTable.where(objectid: source_time_table.objectid).exists?) +    end +  end  end | 
