aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuc Donnet2017-07-26 10:10:57 +0200
committerLuc Donnet2017-07-26 10:10:57 +0200
commita486dbe65187aade64c998e21dae139f8bccc6d1 (patch)
tree4f25b8c5c08b7acd784db197440d1cf27632e7be
parenta692df1c4c336a971219f714bee01a156f4cf8e9 (diff)
parentcada0f02d732dce25492d7f7eb6d6232d56188dd (diff)
downloadchouette-core-a486dbe65187aade64c998e21dae139f8bccc6d1.tar.bz2
Merge branch 'master' into 4161_StopPoints_RouteEdit
-rw-r--r--app/assets/javascripts/cleanup.coffee11
-rw-r--r--app/controllers/time_tables_controller.rb2
-rw-r--r--app/helpers/breadcrumb_helper.rb8
-rw-r--r--app/models/chouette/line.rb2
-rw-r--r--app/models/chouette/stif_codifligne_objectid.rb18
-rw-r--r--app/models/chouette/stif_reflex_objectid.rb18
-rw-r--r--app/models/chouette/stop_area.rb17
-rw-r--r--app/models/chouette/time_table.rb90
-rw-r--r--app/models/concerns/stif_codifligne_attributes_support.rb21
-rw-r--r--app/models/concerns/stif_reflex_attributes_support.rb21
-rw-r--r--app/models/user.rb27
-rw-r--r--app/policies/login_policy.rb2
-rw-r--r--app/views/referentials/show.html.slim8
-rw-r--r--app/views/workbenches/show.html.slim2
-rw-r--r--lib/stif/permission_translator.rb40
-rw-r--r--spec/controllers/devise/cas_sessions_controller_spec.rb26
-rw-r--r--spec/lib/stif/permission_translator_spec.rb39
-rw-r--r--spec/models/chouette/line_spec.rb11
-rw-r--r--spec/models/chouette/stop_area_spec.rb19
-rw-r--r--spec/models/chouette/time_table_spec.rb39
-rw-r--r--spec/models/time_table_combination_spec.rb76
-rw-r--r--spec/models/user_spec.rb8
-rw-r--r--spec/support/permissions.rb1
23 files changed, 391 insertions, 115 deletions
diff --git a/app/assets/javascripts/cleanup.coffee b/app/assets/javascripts/cleanup.coffee
index 7e291aa9e..41aa1ff15 100644
--- a/app/assets/javascripts/cleanup.coffee
+++ b/app/assets/javascripts/cleanup.coffee
@@ -4,11 +4,16 @@ $(document).on("change", 'input[name="clean_up[date_type]"]', (e) ->
if type == 'before'
end_date.hide()
- $("label[for='clean_up_begin_date_3i']").html("Date de fin de la purge");
+ $('label.begin_date').addClass 'hidden'
+ $('label.end_date').removeClass 'hidden'
+
else if type == 'after'
end_date.hide()
- $("label[for='clean_up_begin_date_3i']").html("Date de début de la purge");
+ $('label.begin_date').removeClass 'hidden'
+ $('label.end_date').addClass 'hidden'
+
else
- $("label[for='clean_up_begin_date_3i']").html("Date de début de la purge");
+ $('label.begin_date').removeClass 'hidden'
+ $('label.end_date').addClass 'hidden'
end_date.show()
)
diff --git a/app/controllers/time_tables_controller.rb b/app/controllers/time_tables_controller.rb
index 6849b1592..0054963c9 100644
--- a/app/controllers/time_tables_controller.rb
+++ b/app/controllers/time_tables_controller.rb
@@ -35,7 +35,7 @@ class TimeTablesController < ChouetteController
def create
tt_params = time_table_params
- if tt_params[:calendar_id]
+ if tt_params[:calendar_id] && tt_params[:calendar_id] != ""
%i(monday tuesday wednesday thursday friday saturday sunday).map { |d| tt_params[d] = true }
calendar = Calendar.find(tt_params[:calendar_id])
tt_params[:calendar_id] = nil if tt_params.has_key?(:dates_attributes) || tt_params.has_key?(:periods_attributes)
diff --git a/app/helpers/breadcrumb_helper.rb b/app/helpers/breadcrumb_helper.rb
index 1f8690f38..55031d4f3 100644
--- a/app/helpers/breadcrumb_helper.rb
+++ b/app/helpers/breadcrumb_helper.rb
@@ -73,13 +73,13 @@ module BreadcrumbHelper
end
def calendar_breadcrumb(action)
- add_breadcrumb I18n.t('breadcrumbs.referentials'), referentials_path
+ add_breadcrumb I18n.t('breadcrumbs.referentials'), workbenches_path
add_breadcrumb I18n.t('calendars.index.title'), calendars_path
add_breadcrumb @calendar.name if %i(show edit).include? action
end
def workbench_breadcrumb(action)
- add_breadcrumb I18n.t("breadcrumbs.referentials"), referentials_path
+ add_breadcrumb I18n.t("breadcrumbs.referentials"), workbenches_path
add_breadcrumb breadcrumb_label(@workbench), workbench_path(@workbench), :title => breadcrumb_tooltip(@workbench)
end
@@ -215,7 +215,7 @@ module BreadcrumbHelper
end
def import_breadcrumb (action)
- add_breadcrumb I18n.t("breadcrumbs.referentials"), referentials_path
+ add_breadcrumb I18n.t("breadcrumbs.referentials"), workbenches_path
add_breadcrumb breadcrumb_label(@workbench), workbench_path(@workbench), :title => breadcrumb_tooltip(@workbench)
add_breadcrumb I18n.t("breadcrumbs.imports"), workbench_imports_path(@workbench)
@@ -257,7 +257,7 @@ module BreadcrumbHelper
end
def organisation_breadcrumb (action = :index)
- add_breadcrumb I18n.t("breadcrumbs.referentials"), referentials_path
+ add_breadcrumb I18n.t("breadcrumbs.referentials"), workbenches_path
add_breadcrumb breadcrumb_label(@organisation), organisation_path,:title => breadcrumb_tooltip(@organisation) unless action == :index
end
diff --git a/app/models/chouette/line.rb b/app/models/chouette/line.rb
index 33a2fbb00..63d2d1606 100644
--- a/app/models/chouette/line.rb
+++ b/app/models/chouette/line.rb
@@ -1,5 +1,5 @@
class Chouette::Line < Chouette::ActiveRecord
- include DefaultNetexAttributesSupport
+ include StifCodifligneAttributesSupport
include LineRestrictions
include LineReferentialSupport
include StifTransportModeEnumerations
diff --git a/app/models/chouette/stif_codifligne_objectid.rb b/app/models/chouette/stif_codifligne_objectid.rb
new file mode 100644
index 000000000..46109e24f
--- /dev/null
+++ b/app/models/chouette/stif_codifligne_objectid.rb
@@ -0,0 +1,18 @@
+class Chouette::StifCodifligneObjectid < String
+
+ @@format = /^([A-Za-z_]+):([A-Za-z]+):([A-Za-z]+):([0-9A-Za-z_-]+)$/
+ cattr_reader :format
+
+ def parts
+ match(format).try(:captures)
+ end
+
+ def object_type
+ parts.try(:third)
+ end
+
+ def local_id
+ parts.try(:fourth)
+ end
+
+end
diff --git a/app/models/chouette/stif_reflex_objectid.rb b/app/models/chouette/stif_reflex_objectid.rb
new file mode 100644
index 000000000..c41a9325a
--- /dev/null
+++ b/app/models/chouette/stif_reflex_objectid.rb
@@ -0,0 +1,18 @@
+class Chouette::StifReflexObjectid < String
+
+ @@format = /^([A-Za-z_]+):([0-9A-Za-z_-]+):([A-Za-z]+):([0-9A-Za-z_-]+):([A-Za-z]+)$/
+ cattr_reader :format
+
+ def parts
+ match(format).try(:captures)
+ end
+
+ def object_type
+ parts.try(:third)
+ end
+
+ def local_id
+ parts.try(:fourth)
+ end
+
+end
diff --git a/app/models/chouette/stop_area.rb b/app/models/chouette/stop_area.rb
index 4d98027d6..43bc82f7f 100644
--- a/app/models/chouette/stop_area.rb
+++ b/app/models/chouette/stop_area.rb
@@ -4,20 +4,16 @@ require 'geo_ruby'
class Chouette::StopArea < Chouette::ActiveRecord
# FIXME http://jira.codehaus.org/browse/JRUBY-6358
self.primary_key = "id"
+
include Geokit::Mappable
+ include StifReflexAttributesSupport
include ProjectionFields
include StopAreaRestrictions
+ include StopAreaReferentialSupport
extend Enumerize
enumerize :area_type, in: %i(zdep zder zdlp zdlr lda)
- def self.model_name
- ActiveModel::Name.new self, Chouette, self.name.demodulize
- end
- # Refs #1627
- # include DefaultAttributesSupport
- include StopAreaReferentialSupport
-
with_options dependent: :destroy do |assoc|
assoc.has_many :stop_points
assoc.has_many :access_points
@@ -57,13 +53,6 @@ class Chouette::StopArea < Chouette::ActiveRecord
after_update :clean_invalid_access_links
before_save :coordinates_to_lat_lng
- # Refs #1627
- before_validation :prepare_auto_columns
- def prepare_auto_columns
- self.object_version = 1
- self.creator_id = 'chouette'
- end
-
def combine_lat_lng
if self.latitude.nil? || self.longitude.nil?
""
diff --git a/app/models/chouette/time_table.rb b/app/models/chouette/time_table.rb
index d907d797e..713ce0b21 100644
--- a/app/models/chouette/time_table.rb
+++ b/app/models/chouette/time_table.rb
@@ -38,26 +38,26 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
validates_associated :periods
def continuous_dates
+ in_days = self.dates.where(in_out: true).sort_by(&:date)
chunk = {}
group = nil
- self.dates.where(in_out: true).each_with_index do |date, index|
+ in_days.each_with_index do |date, index|
group ||= index
- group = (date.date == dates[index - 1].date + 1.day) ? group : group + 1
+ group = (date.date == in_days[index - 1].date + 1.day) ? group : group + 1
chunk[group] ||= []
chunk[group] << date
end
- chunk.values
+ # Remove less than 2 continuous day chunk
+ chunk.values.delete_if {|dates| dates.count < 2}
end
def convert_continuous_dates_to_periods
chunks = self.continuous_dates
- # Remove less than 3 continuous day chunk
- chunks.delete_if {|chunk| chunk.count < 3}
transaction do
chunks.each do |chunk|
self.periods.create!(period_start: chunk.first.date, period_end: chunk.last.date)
- chunk.map(&:destroy)
+ self.dates.delete(chunk)
end
end
end
@@ -415,7 +415,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
def clone_periods
periods = []
self.periods.each { |p| periods << p.copy}
- periods
+ periods.sort_by(&:period_start)
end
def included_days
@@ -436,7 +436,7 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
# produce a copy of periods without anyone overlapping or including another
- def optimize_periods
+ def optimize_overlapping_periods
periods = self.clone_periods
optimized = []
i=0
@@ -461,6 +461,59 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
optimized.sort { |a,b| a.period_start <=> b.period_start}
end
+ def continuous_periods
+ periods = self.periods.sort_by(&:period_start)
+ chunk = {}
+ group = nil
+ periods.each_with_index do |period, index|
+ group ||= index
+ group = (period.period_start - 1.day == periods[index - 1].period_end) ? group : group + 1
+ chunk[group] ||= []
+ chunk[group] << period
+ end
+ chunk.values.delete_if {|periods| periods.count < 2}
+ end
+
+ def convert_continuous_periods_into_one
+ chunks = self.continuous_periods
+
+ transaction do
+ chunks.each do |chunk|
+ self.periods.create!(period_start: chunk.first.period_start, period_end: chunk.last.period_end)
+ self.periods.delete chunk
+ end
+ end
+ end
+
+ #update a period if a in_day is just before or after
+ def optimize_continuous_dates_and_periods
+ return self.periods if self.included_days.empty? || periods.empty?
+
+ periods = self.clone_periods
+ optimized = []
+
+ i = 0
+ while i < periods.length
+ period = periods[i]
+ j = 0
+ in_days = self.reload.dates.where(in_out: true).sort_by(&:date)
+ while j < in_days.length
+ day = in_days[j]
+ if period.period_start - 1.day === day.date
+ period.period_start = day.date
+ self.dates.delete day
+ elsif period.period_end + 1.day === day.date
+ period.period_end = day.date
+ self.dates.delete day
+ end
+ j += 1
+ end
+ i += 1
+ optimized << period
+ end
+ optimized
+ end
+
# add a peculiar day or switch it from excluded to included
def add_included_day(d)
if self.excluded_date?(d)
@@ -478,22 +531,27 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord
def merge!(another_tt)
transaction do
self.periods = another_tt.clone_periods + self.periods
- self.periods = self.optimize_periods
# For included dates
another_tt.included_days.map{ |d| add_included_day(d) }
# For excluded dates
- existing_out_date = self.dates.where(in_out: false).map(&:date)
- another_tt.dates.where(in_out: false).each do |d|
- unless existing_out_date.include?(d.date)
- self.dates << Chouette::TimeTableDate.new(:date => d.date, :in_out => false)
+ self.dates.where(in_out: false).each do |d|
+ self.dates.delete d if another_tt.include_in_periods?(d.date) && !another_tt.excluded_date?(d.date)
+ end
+
+ another_tt.excluded_days.each do |d|
+ unless self.reload.excluded_date?(d)
+ self.dates << Chouette::TimeTableDate.new(date: d, in_out: false)
end
+ self.save!
end
- self.save!
- end
- self.convert_continuous_dates_to_periods
+ self.convert_continuous_dates_to_periods
+ self.periods = self.optimize_continuous_dates_and_periods
+ self.convert_continuous_periods_into_one
+ self.periods = self.optimize_overlapping_periods
+ end
end
def included_days_in_dates_and_periods
diff --git a/app/models/concerns/stif_codifligne_attributes_support.rb b/app/models/concerns/stif_codifligne_attributes_support.rb
new file mode 100644
index 000000000..d4370e505
--- /dev/null
+++ b/app/models/concerns/stif_codifligne_attributes_support.rb
@@ -0,0 +1,21 @@
+module StifCodifligneAttributesSupport
+ extend ActiveSupport::Concern
+
+ included do
+ validates_presence_of :objectid
+ end
+
+ module ClassMethods
+ def object_id_key
+ model_name
+ end
+
+ def model_name
+ ActiveModel::Name.new self, Chouette, self.name.demodulize
+ end
+ end
+
+ def objectid
+ Chouette::StifCodifligneObjectid.new read_attribute(:objectid).to_s
+ end
+end
diff --git a/app/models/concerns/stif_reflex_attributes_support.rb b/app/models/concerns/stif_reflex_attributes_support.rb
new file mode 100644
index 000000000..e6236a146
--- /dev/null
+++ b/app/models/concerns/stif_reflex_attributes_support.rb
@@ -0,0 +1,21 @@
+module StifReflexAttributesSupport
+ extend ActiveSupport::Concern
+
+ included do
+ validates_presence_of :objectid
+ end
+
+ module ClassMethods
+ def object_id_key
+ model_name
+ end
+
+ def model_name
+ ActiveModel::Name.new self, Chouette, self.name.demodulize
+ end
+ end
+
+ def objectid
+ Chouette::StifReflexObjectid.new read_attribute(:objectid).to_s
+ end
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 64d66883f..c2aa14bda 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -29,29 +29,6 @@ class User < ActiveRecord::Base
scope :with_organisation, -> { where.not(organisation_id: nil) }
- def self.destructive_permissions_for(models)
- models.product( %w{create destroy update} ).map{ |model_action| model_action.join('.') }
- end
-
- @@edit_offer_permissions =
- destructive_permissions_for( %w[
- access_points
- connection_links
- calendars
- footnotes
- journey_patterns
- referentials
- routes
- routing_constraint_zones
- time_tables
- vehicle_journeys
- ]) << 'boiv:edit-offer'
-
- mattr_reader :edit_offer_permissions
-
- def self.all_permissions
- edit_offer_permissions
- end
# Callback invoked by DeviseCasAuthenticable::Model#authernticate_with_cas_ticket
def cas_extra_attributes=(extra_attributes)
@@ -59,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 = extra[:permissions].include?('boiv:edit-offer') ? @@edit_offer_permissions : []
+ self.permissions = Stif::PermissionTranslator.translate(extra[:permissions])
end
def self.portail_api_request
@@ -87,7 +64,7 @@ class User < ActiveRecord::Base
user.locked_at = el['locked_at']
user.organisation = Organisation.sync_update el['organization_code'], el['organization_name'], el['functional_scope']
user.synced_at = Time.now
- user.permissions = el['permissions'].include?('boiv:edit-offer') ? @@edit_offer_permissions : []
+ user.permissions = Stif::PermissionTranslator.translate(el['permissions'])
user.save
end
end
diff --git a/app/policies/login_policy.rb b/app/policies/login_policy.rb
index 3364c37ac..5b07b97f3 100644
--- a/app/policies/login_policy.rb
+++ b/app/policies/login_policy.rb
@@ -7,7 +7,7 @@ class LoginPolicy
end
def boiv?
- !(user.permissions || []).grep(%r{\Aboiv:.}).empty?
+ (user.permissions || []).include?('sessions:create')
end
end
diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim
index d3687c3a7..425f8014a 100644
--- a/app/views/referentials/show.html.slim
+++ b/app/views/referentials/show.html.slim
@@ -91,9 +91,13 @@
.row
.col-lg-8.col-ld-offset-2.col-md-8.col-md-offset-2.col-sm-8.col-sm-offset-2.col-xs-12
= f.input :date_type, as: :radio_buttons, label: false
- = f.input :begin_date, as: :date, label: t('titles.clean_up.begin_date'),:wrapper_html => { class: 'date smart_date', title: t('titles.clean_up.begin_date') }
- = f.input :end_date, as: :date, label: t('titles.clean_up.end_date'), :wrapper_html => { class: 'date cleanup_end_date_wrapper smart_date', title: t('titles.clean_up.end_date'), id: "end_date" }
+ .col-lg-8.col-ld-offset-2.col-md-8.col-md-offset-2.col-sm-8.col-sm-offset-2.col-xs-12
+ label.control-label.begin_date = t('titles.clean_up.begin_date')
+ label.control-label.end_date.hidden = t('titles.clean_up.end_date')
+ = f.input :begin_date, as: :date, label: false, wrapper_html: { class: 'date smart_date' }
+
+ = f.input :end_date, as: :date, label: t('titles.clean_up.end_date'), wrapper_html: { class: 'date cleanup_end_date_wrapper smart_date', id: "end_date" }
.modal-footer
button.btn.btn-link type='button' data-dismiss='modal' Annuler
diff --git a/app/views/workbenches/show.html.slim b/app/views/workbenches/show.html.slim
index bb8b71ab2..a9ce2f704 100644
--- a/app/views/workbenches/show.html.slim
+++ b/app/views/workbenches/show.html.slim
@@ -7,8 +7,8 @@
/ Below is secundary actions & optional contents (filters, ...)
.row.mb-sm
.col-lg-12.text-right
- = link_to t('actions.import'), workbench_imports_path(@workbench), class: 'btn btn-primary'
- if policy(Referential).create?
+ = link_to t('actions.import'), workbench_imports_path(@workbench), class: 'btn btn-primary'
= link_to t('actions.add'), new_referential_path(workbench_id: @workbench), class: 'btn btn-primary'
/ PageContent
diff --git a/lib/stif/permission_translator.rb b/lib/stif/permission_translator.rb
index 7032f910a..afe69756e 100644
--- a/lib/stif/permission_translator.rb
+++ b/lib/stif/permission_translator.rb
@@ -1,7 +1,45 @@
module Stif
module PermissionTranslator extend self
+
def translate(sso_extra_permissions)
- %w{sessions:create}
+ sso_extra_permissions
+ .sort
+ .flat_map(&method(:extra_permission_translation))
+ .uniq
+ end
+
+ private
+
+ def all_destructive_permissions
+ destructive_permissions_for( all_resources )
+ end
+
+ def all_resources
+ %w[
+ access_points
+ connection_links calendars
+ footnotes
+ journey_patterns
+ referentials routes routing_constraint_zones
+ time_tables
+ vehicle_journeys
+ ]
+ end
+
+ def destructive_permissions_for(models)
+ @__destructive_permissions_for__ ||=
+ models.product( %w{create destroy update} ).map{ |model_action| model_action.join('.') }
+ end
+
+ def extra_permission_translation extra_permission
+ translation_table.fetch(extra_permission, [])
+ end
+
+ def translation_table
+ {
+ "boiv:read-offer" => %w{sessions:create},
+ "boiv:edit-offer" => all_destructive_permissions + %w{sessions:create},
+ }
end
end
end
diff --git a/spec/controllers/devise/cas_sessions_controller_spec.rb b/spec/controllers/devise/cas_sessions_controller_spec.rb
index 950d141fd..c82fd2cdb 100644
--- a/spec/controllers/devise/cas_sessions_controller_spec.rb
+++ b/spec/controllers/devise/cas_sessions_controller_spec.rb
@@ -1,25 +1,37 @@
RSpec.describe Devise::CasSessionsController, type: :controller do
- login_user
+ before do
+ @user = signed_in_user
+ allow_any_instance_of(Warden::Proxy).to receive(:authenticate).and_return @user
+ allow_any_instance_of(Warden::Proxy).to receive(:authenticate!).and_return @user
+ @request.env["devise.mapping"] = Devise.mappings[:user]
+ end
+
context 'login is correctly redirected' do
+ let( :signed_in_user ){ build_stubbed :user }
it 'to #service' do
get :new
- expect(response).to redirect_to(unauthenticated_root_path)
+ expect( response ).to be_redirect
+ expect( response.redirect_url ).to eq("http://stif-portail-dev.af83.priv/sessions/login?service=http%3A%2F%2Ftest.host%2Fusers%2Fservice")
end
end
- context 'user does not have any boiv:.+ permission' do
- xit 'cannot login and will be redirected to the login page, with a corresponding message' do
+ context 'user does not have permission sessions:create' do
+ let( :signed_in_user ){ build_stubbed :user }
+
+ it 'cannot login and will be redirected to the login page, with a corresponding message' do
get :service
expect(controller).to set_flash[:alert].to(%r{IBOO})
- expect(response).to redirect_to("http://stif-portail-dev.af83.priv/sessions/login?service=http%3A%2F%2Ftest.host%2Fusers%2Fservice")
+ expect(response).to redirect_to "http://stif-portail-dev.af83.priv/sessions/logout?service=http%3A%2F%2Ftest.host%2Fusers%2Fservice"
end
end
- context 'user does have a boiv:.+ permission' do
+ context 'user does have permission sessions:create' do
+ let( :signed_in_user ){ build_stubbed :allmighty_user }
+
it 'can login and will be redirected to the referentials page' do
- @user.update_attribute :permissions, (@user.permissions << 'boiv:UnameIt')
+ @user.permissions << 'sessions:create'
get :service
expect(response).to redirect_to(authenticated_root_path)
end
diff --git a/spec/lib/stif/permission_translator_spec.rb b/spec/lib/stif/permission_translator_spec.rb
index 3672c7937..1af21364c 100644
--- a/spec/lib/stif/permission_translator_spec.rb
+++ b/spec/lib/stif/permission_translator_spec.rb
@@ -1,10 +1,45 @@
RSpec.describe Stif::PermissionTranslator do
- context "SSO Permission boiv:read:offer →" do
+ context "No SSO Permissions" do
+ it { expect(described_class.translate([])).to be_empty }
+ end
+
+ context "SSO Permission boiv:read-offer →" do
it "sessions:create only" do
- expect( described_class.translate(%w{boiv:read:offer}) ).to eq(%w{sessions:create})
+ expect( described_class.translate(%w{boiv:read-offer}) ).to eq(%w{sessions:create})
+ end
+
+ end
+
+ context "SSO Permission boiv:edit-offer →" do
+
+ it "all permissions" do
+ expect( described_class.translate(%w{boiv:edit-offer}) ).to eq(Support::Permissions.all_permissions)
+ end
+
+ it "all permissions, no doubletons" do
+ expect( described_class.translate(%w{boiv:edit-offer boiv:read-offer}) ).to eq(Support::Permissions.all_permissions)
end
+ it "all permissions, input order agnostic" do
+ expect( described_class.translate(%w{boiv:read-offer boiv:edit-offer}) ).to eq(Support::Permissions.all_permissions)
+ end
+ end
+
+ context "SSO Permission ignores garbage (no injection) →" do
+ it "remains empty" do
+ expect( described_class.translate(%w{referentials.create}) ).to be_empty
+ end
+
+ it "remains at boiv:read-offer level" do
+ expect( described_class.translate(%w{referentials.create boiv:read-offer calendars.delete}) ).to eq(%w{sessions:create})
+ end
+
+ it "does not add garbage or doubletons for boiv:edit-offer level" do
+ expect(
+ described_class.translate(%w{xxx boiv:read-offer lines.delete boiv:edit-offer footnotes.update})
+ ).to eq(Support::Permissions.all_permissions)
+ end
end
end
diff --git a/spec/models/chouette/line_spec.rb b/spec/models/chouette/line_spec.rb
index 5a339e7ed..2e5882012 100644
--- a/spec/models/chouette/line_spec.rb
+++ b/spec/models/chouette/line_spec.rb
@@ -1,17 +1,12 @@
require 'spec_helper'
describe Chouette::Line, :type => :model do
-
subject { create(:line) }
- it { is_expected.to belong_to(:line_referential) }
+ it { should belong_to(:line_referential) }
# it { is_expected.to validate_presence_of :network }
# it { is_expected.to validate_presence_of :company }
-
- it { is_expected.to validate_presence_of :name }
-
- # it { should validate_presence_of :objectid }
- it { is_expected.to validate_uniqueness_of :objectid }
+ it { should validate_presence_of :name }
describe '#display_name' do
it 'should display local_id, number, name and company name' do
@@ -22,7 +17,7 @@ describe Chouette::Line, :type => :model do
describe '#objectid' do
subject { super().objectid }
- it { is_expected.to be_kind_of(Chouette::NetexObjectId) }
+ it { is_expected.to be_kind_of(Chouette::StifCodifligneObjectid) }
end
# it { should validate_numericality_of :objectversion }
diff --git a/spec/models/chouette/stop_area_spec.rb b/spec/models/chouette/stop_area_spec.rb
index 1a2ff8ede..293ae5202 100644
--- a/spec/models/chouette/stop_area_spec.rb
+++ b/spec/models/chouette/stop_area_spec.rb
@@ -7,16 +7,15 @@ describe Chouette::StopArea, :type => :model do
let!(:commercial_stop_point) { create :stop_area, :area_type => "lda" }
let!(:stop_place) { create :stop_area, :area_type => "zdlp" }
- # Refs #1627
- # describe '#objectid' do
- # subject { super().objectid }
- # it { is_expected.to be_kind_of(Chouette::ObjectId) }
- # end
-
- it { is_expected.to belong_to(:stop_area_referential) }
- it { is_expected.to validate_presence_of :name }
- it { is_expected.to validate_numericality_of :latitude }
- it { is_expected.to validate_numericality_of :longitude }
+ describe '#objectid' do
+ subject { super().objectid }
+ it { should be_kind_of(Chouette::StifReflexObjectid) }
+ end
+
+ it { should belong_to(:stop_area_referential) }
+ it { should validate_presence_of :name }
+ it { should validate_numericality_of :latitude }
+ it { should validate_numericality_of :longitude }
# describe ".latitude" do
# it "should accept -90 value" do
diff --git a/spec/models/chouette/time_table_spec.rb b/spec/models/chouette/time_table_spec.rb
index bd74a2d4c..304cb0184 100644
--- a/spec/models/chouette/time_table_spec.rb
+++ b/spec/models/chouette/time_table_spec.rb
@@ -14,6 +14,8 @@ describe Chouette::TimeTable, :type => :model do
describe "#merge! with time_table" do
let(:another_tt) { create(:time_table) }
let(:another_tt_periods_to_range) { another_tt.periods.map{|p| p.period_start..p.period_end } }
+ let(:dates) { another_tt.dates.map(&:date) }
+ let(:continuous_dates) { another_tt.continuous_dates.flatten.map(&:date) }
# Make sur we don't have overlapping periods or dates
before do
@@ -22,12 +24,19 @@ describe Chouette::TimeTable, :type => :model do
p.period_end = p.period_end + 1.year
end
another_tt.dates.each{| d| d.date = d.date + 1.year }
+ another_tt.save
end
it 'should merge dates' do
subject.dates.clear
subject.merge!(another_tt)
- expect(subject.dates.map(&:date)).to include(*another_tt.dates.map(&:date))
+ expect(subject.dates.map(&:date)).to match_array(dates - continuous_dates)
+ end
+
+ it 'should not merge continuous dates' do
+ subject.dates.clear
+ subject.merge!(another_tt)
+ expect(subject.dates.map(&:date)).not_to include(*continuous_dates)
end
it 'should merge periods' do
@@ -50,28 +59,42 @@ describe Chouette::TimeTable, :type => :model do
subject.merge!(another_tt)
expect(subject.dates.map(&:date)).to include(another_tt.dates.last.date)
end
+
+ it 'should remove date in_out false if other tt doesnt have them' do
+ subject.dates.create(in_out: false, date: Date.today + 5.day + 1.year)
+
+ expect {
+ subject.merge!(another_tt)
+ }.to change {subject.reload.excluded_days.count}.by(-1)
+ end
end
context "#merge! with calendar" do
let(:calendar) { create(:calendar, date_ranges: [Date.today + 1.year..Date.tomorrow + 1.year]) }
+ let(:another_tt) { calendar.convert_to_time_table }
+ let(:dates) { subject.dates.map(&:date) }
+ let(:continuous_dates) { subject.continuous_dates.flatten.map(&:date) }
it 'should merge calendar dates' do
subject.dates.clear
- subject.merge!(calendar.convert_to_time_table)
- expect(subject.dates.map(&:date)).to include(*calendar.dates)
+ subject.merge!(another_tt)
+ expect(subject.dates.map(&:date)).to match_array(dates - continuous_dates)
+ end
+
+ it 'should not merge calendar continuous dates' do
+ subject.dates.clear
+ subject.merge!(another_tt)
+ expect(subject.dates.map(&:date)).not_to include(*continuous_dates)
end
it 'should merge calendar periods with no periods in source' do
subject.periods.clear
- another_tt = calendar.convert_to_time_table
subject.merge!(another_tt)
expect(subject_periods_to_range).to include(*calendar.date_ranges)
end
it 'should add calendar periods with existing periods in source' do
- another_tt = calendar.convert_to_time_table
subject.merge!(another_tt)
-
expect(subject_periods_to_range).to include(*calendar.date_ranges)
end
end
@@ -1109,7 +1132,7 @@ end
- describe "#optimize_periods" do
+ describe "#optimize_overlapping_periods" do
before do
subject.periods.clear
subject.periods << Chouette::TimeTablePeriod.new(
@@ -1127,7 +1150,7 @@ end
subject.int_day_types = 4|8|16
end
it "should return 2 ordered periods" do
- periods = subject.optimize_periods
+ periods = subject.optimize_overlapping_periods
expect(periods.size).to eq(2)
expect(periods[0].period_start).to eq(Date.new(2014, 6, 1))
expect(periods[0].period_end).to eq(Date.new(2014, 6, 14))
diff --git a/spec/models/time_table_combination_spec.rb b/spec/models/time_table_combination_spec.rb
index 3e60fa444..ee934f50d 100644
--- a/spec/models/time_table_combination_spec.rb
+++ b/spec/models/time_table_combination_spec.rb
@@ -8,30 +8,93 @@ describe TimeTableCombination, :type => :model do
describe '#continuous_dates' do
it 'should group continuous dates' do
dates = source.dates.where(in_out: true)
- expect(source.continuous_dates[0].count).to eq(dates.count)
+ expect(source.continuous_dates.flatten.count).to eq(dates.count)
- # 6 more continuous date, 1 isolated date
+ # 6 more continuous dates, 2 isolated dates
(10..15).each do |n|
source.dates.create(date: Date.today + n.day, in_out: true)
end
- source.dates.create(date: Date.today + 1.year, in_out: true)
+
+ (1..2).each do |n|
+ source.dates.create(date: Date.today + n.day + 1.year, in_out: true)
+ end
+
expect(source.reload.continuous_dates[1].count).to eq(6)
- expect(source.reload.continuous_dates[2].count).to eq(1)
+ expect(source.reload.continuous_dates[2].count).to eq(2)
end
end
describe '#convert_continuous_dates_to_periods' do
it 'should convert continuous dates to periods' do
+ source.dates.clear
+
(10..12).each do |n|
source.dates.create(date: Date.today + n.day, in_out: true)
end
- source.dates.create(date: Date.today + 1.year, in_out: true)
+
+ (1..3).each do |n|
+ source.dates.create(date: Date.today + n.day + 1.year, in_out: true)
+ end
expect {
source.reload.convert_continuous_dates_to_periods
}.to change {source.periods.count}.by(2)
- expect(source.reload.dates.where(in_out: true).count).to eq(1)
+ expect(source.reload.dates.where(in_out: true).count).to eq(0)
+ end
+ end
+
+ describe '#continuous_periods' do
+ it 'should group continuous periods' do
+ source.periods.clear
+
+ start_date = Date.today + 1.year
+ end_date = start_date + 10
+
+ # 6 more continuous dates, 2 isolated dates
+ 0.upto(4) do |i|
+ source.periods.create(period_start: start_date, period_end: end_date)
+ start_date = end_date + 1
+ end_date = start_date + 10
+ end
+
+ expect(source.reload.continuous_periods.flatten.count).to eq(5)
+ end
+ end
+
+ describe '#convert_continuous_periods_into_one' do
+ it 'should convert continuous periods into one' do
+ source.periods.clear
+
+ start_date = Date.today + 1.year
+ end_date = start_date + 10
+
+ # 6 more continuous dates, 2 isolated dates
+ 0.upto(4) do |i|
+ source.periods.create(period_start: start_date, period_end: end_date)
+ start_date = end_date + 1
+ end_date = start_date + 10
+ end
+
+ expect {
+ source.reload.convert_continuous_periods_into_one
+ }.to change {source.periods.count}.by(-4)
+ end
+ end
+
+ describe '#optimize_continuous_dates_and_periods' do
+ it 'should update period if timetable has in_date just before or after ' do
+ source.dates.clear
+ source.periods.clear
+
+ source.periods.create(period_start: Date.today, period_end: Date.today + 10.day)
+ source.dates.create(date: Date.today - 1.day, in_out: true)
+
+ expect {
+ source.periods = source.optimize_continuous_dates_and_periods
+ }.to change {source.dates.count}.by(-1)
+
+ expect(source.reload.periods.first.period_start).to eq(Date.today - 1.day)
end
end
@@ -129,4 +192,3 @@ describe TimeTableCombination, :type => :model do
end
end
end
-
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 6f98e5ce7..3a9ae37e9 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1,6 +1,4 @@
-require 'spec_helper'
-
-describe User, :type => :model do
+RSpec.describe User, :type => :model do
# it { should validate_uniqueness_of :email }
# it { should validate_presence_of :name }
@@ -116,9 +114,11 @@ describe User, :type => :model do
end
context 'permissions' do
+ let( :all_permissions ){ Stif::PermissionTranslator.translate(%w{boiv:edit-offer}) }
+
it 'should give edit permissions to user if user has "edit offer" permission in portail' do
User.portail_sync
- expect(User.find_by(username: 'vlatka.pavisic').permissions).to include_all(User.edit_offer_permissions)
+ expect(User.find_by(username: 'vlatka.pavisic').permissions).to eq(all_permissions)
expect(User.find_by(username: 'pierre.vabre').permissions).to be_empty
end
end
diff --git a/spec/support/permissions.rb b/spec/support/permissions.rb
index a13010f65..fcf9ae9c4 100644
--- a/spec/support/permissions.rb
+++ b/spec/support/permissions.rb
@@ -15,6 +15,7 @@ module Support
%w[
access_points
connection_links
+ calendars
footnotes
journey_patterns
referentials