diff options
| author | Luc Donnet | 2017-07-03 15:37:45 +0200 |
|---|---|---|
| committer | Luc Donnet | 2017-07-03 15:37:45 +0200 |
| commit | 9ada6224335862b51c460dc78d7487596323fef8 (patch) | |
| tree | 6b8694d94abd5aaf5cee7b3a0e9b2aa98ebaefea | |
| parent | b9faf2b87816ffc67af4bf10826ea51d049e2a48 (diff) | |
| parent | 5220e7bad9e252983e1bfc1850fd3459ca802267 (diff) | |
| download | chouette-core-9ada6224335862b51c460dc78d7487596323fef8.tar.bz2 | |
Merge branch 'master' of github.com:AF83/stif-boiv
38 files changed, 347 insertions, 531 deletions
diff --git a/.gitignore b/.gitignore index 1bca870cb..0cdaa7c9f 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,8 @@ bin/ # Ignore node modules /node_modules + +# Every machine shall create its binstubs +/bin/rake +/bin/rails +/bin/rspec diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js b/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js index 43c40a4d5..18ed5f889 100644 --- a/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js +++ b/app/assets/javascripts/es6_browserified/journey_patterns/components/JourneyPattern.js @@ -43,75 +43,79 @@ class JourneyPattern extends Component{ ) } + getErrors(errors) { + let err = Object.keys(errors).map((key, index) => { + return ( + <li key={index} style={{listStyleType: 'disc'}}> + <strong>{key}</strong> { errors[key] } + </li> + ) + }) + + return ( + <ul className="alert alert-danger">{err}</ul> + ) + } + render() { this.previousCity = undefined return ( - <div className={'t2e-item' + (this.props.value.deletable ? ' disabled' : '') + (this.props.value.object_id ? '' : ' to_record')}> + <div className={'t2e-item' + (this.props.value.deletable ? ' disabled' : '') + (this.props.value.object_id ? '' : ' to_record') + (this.props.value.errors ? ' has-error': '')}> {/* Errors */} - {(this.props.value.errors) && ( - <ul className='alert alert-danger small' style={{paddingLeft: 30}}> - {Object.keys(this.props.value.errors).map(function(key, i) { - return ( - <li key={i} style={{listStyleType: 'disc'}}> - <strong>'{key}'</strong> {this.props.value.errors[key]} - </li> - ) - })} - </ul> - )} + {/* this.props.value.errors ? this.getErrors(this.props.value.errors) : '' */} - <div className='th'> - <div className='strong mb-xs'>{this.props.value.object_id ? actions.humanOID(this.props.value.object_id) : '-'}</div> - <div>{this.props.value.registration_number}</div> - <div>{actions.getChecked(this.props.value.stop_points).length} arrêt(s)</div> + <div className='th'> + <div className='strong mb-xs'>{this.props.value.object_id ? actions.humanOID(this.props.value.object_id) : '-'}</div> + <div>{this.props.value.registration_number}</div> + <div>{actions.getChecked(this.props.value.stop_points).length} arrêt(s)</div> - <div className={this.props.value.deletable ? 'btn-group disabled' : 'btn-group'}> - <div - className={this.props.value.deletable ? 'btn dropdown-toggle disabled' : 'btn dropdown-toggle'} - data-toggle='dropdown' - > - <span className='fa fa-cog'></span> - </div> - <ul className='dropdown-menu'> - <li className={(this.props.value.deletable || this.props.status.policy['journey_patterns.edit'] == false) ? 'disabled' : ''}> - <button - type='button' - onClick={this.props.onOpenEditModal} - data-toggle='modal' - data-target='#JourneyPatternModal' - > - Editer + <div className={this.props.value.deletable ? 'btn-group disabled' : 'btn-group'}> + <div + className={this.props.value.deletable ? 'btn dropdown-toggle disabled' : 'btn dropdown-toggle'} + data-toggle='dropdown' + > + <span className='fa fa-cog'></span> + </div> + <ul className='dropdown-menu'> + <li className={(this.props.value.deletable || this.props.status.policy['journey_patterns.edit'] == false) ? 'disabled' : ''}> + <button + type='button' + onClick={this.props.onOpenEditModal} + data-toggle='modal' + data-target='#JourneyPatternModal' + > + Editer + </button> + </li> + <li className={this.props.value.object_id ? '' : 'disabled'}> + {this.vehicleJourneyURL(this.props.value.object_id)} + </li> + <li className={'delete-action' + ((this.props.status.policy['journey_patterns.edit'] == false)? ' disabled' : '')}> + <button + type='button' + disabled={(this.props.status.policy['journey_patterns.edit'] == false)? 'disabled' : ''} + onClick={(e) => { + e.preventDefault() + this.props.onDeleteJourneyPattern(this.props.index)} + } + > + <span className='fa fa-trash'></span>Supprimer </button> </li> - <li className={this.props.value.object_id ? '' : 'disabled'}> - {this.vehicleJourneyURL(this.props.value.object_id)} - </li> - <li className={'delete-action' + ((this.props.status.policy['journey_patterns.edit'] == false)? ' disabled' : '')}> - <button - type='button' - disabled={(this.props.status.policy['journey_patterns.edit'] == false)? 'disabled' : ''} - onClick={(e) => { - e.preventDefault() - this.props.onDeleteJourneyPattern(this.props.index)} - } - > - <span className='fa fa-trash'></span>Supprimer - </button> - </li> - </ul> - </div> + </ul> </div> - - {this.props.value.stop_points.map((stopPoint, i) =>{ - return ( - <div key={i} className='td'> - {this.cityNameChecker(stopPoint)} - </div> - ) - })} </div> - ) + + {this.props.value.stop_points.map((stopPoint, i) =>{ + return ( + <div key={i} className='td'> + {this.cityNameChecker(stopPoint)} + </div> + ) + })} + </div> + ) } } diff --git a/app/assets/javascripts/es6_browserified/journey_patterns/reducers/status.js b/app/assets/javascripts/es6_browserified/journey_patterns/reducers/status.js index 6241777da..d7ef12d0b 100644 --- a/app/assets/javascripts/es6_browserified/journey_patterns/reducers/status.js +++ b/app/assets/javascripts/es6_browserified/journey_patterns/reducers/status.js @@ -9,6 +9,8 @@ const status = (state = {}, action) => { return _.assign({}, state, {isFetching: true}) case 'RECEIVE_JOURNEY_PATTERNS': return _.assign({}, state, {fetchSuccess: true, isFetching: false}) + case 'RECEIVE_ERRORS': + return _.assign({}, state, {isFetching: false}) default: return state } diff --git a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js index a8a92c522..028974fc8 100644 --- a/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js +++ b/app/assets/javascripts/es6_browserified/time_tables/components/PeriodForm.js @@ -61,30 +61,30 @@ const PeriodForm = ({modal, timetable, metas, onOpenAddPeriodForm, onClosePeriod <div className="nested-fields"> <div className="wrapper"> <div> - <div className={'form-group date smart_date' + (modal.modalProps.error ? ' has-error' : '')}> + <div className={'form-group date ' + (modal.modalProps.error ? ' has-error' : '')}> <div className="form-inline"> - <select value={formatNumber(modal.modalProps.begin.day)} onChange={(e) => onUpdatePeriodForm(e, 'begin', 'day')} id="q_validity_period_begin_gteq_3i" className="date required form-control"> + <select value={formatNumber(modal.modalProps.begin.day)} onChange={(e) => onUpdatePeriodForm(e, 'begin', 'day', modal.modalProps)} id="q_validity_period_begin_gteq_3i" className="date required form-control"> {makeDaysOptions(modal.modalProps.begin.day)} </select> - <select value={formatNumber(modal.modalProps.begin.month)} onChange={(e) => onUpdatePeriodForm(e, 'begin', 'month')} id="q_validity_period_begin_gteq_2i" className="date required form-control"> + <select value={formatNumber(modal.modalProps.begin.month)} onChange={(e) => onUpdatePeriodForm(e, 'begin', 'month', modal.modalProps)} id="q_validity_period_begin_gteq_2i" className="date required form-control"> {makeMonthsOptions(modal.modalProps.begin.month)} </select> - <select value={modal.modalProps.begin.year} onChange={(e) => onUpdatePeriodForm(e, 'begin', 'year')} id="q_validity_period_begin_gteq_1i" className="date required form-control"> + <select value={modal.modalProps.begin.year} onChange={(e) => onUpdatePeriodForm(e, 'begin', 'year', modal.modalProps)} id="q_validity_period_begin_gteq_1i" className="date required form-control"> {makeYearsOptions(modal.modalProps.begin.year)} </select> </div> </div> </div> <div> - <div className={'form-group date smart_date' + (modal.modalProps.error ? ' has-error' : '')}> + <div className={'form-group date ' + (modal.modalProps.error ? ' has-error' : '')}> <div className="form-inline"> - <select value={formatNumber(modal.modalProps.end.day)} onChange={(e) => onUpdatePeriodForm(e, 'end', 'day')} id="q_validity_period_end_gteq_3i" className="date required form-control"> + <select value={formatNumber(modal.modalProps.end.day)} onChange={(e) => onUpdatePeriodForm(e, 'end', 'day', modal.modalProps)} id="q_validity_period_end_gteq_3i" className="date required form-control"> {makeDaysOptions(modal.modalProps.end.day)} </select> - <select value={formatNumber(modal.modalProps.end.month)} onChange={(e) => onUpdatePeriodForm(e, 'end', 'month')} id="q_validity_period_end_gteq_2i" className="date required form-control"> + <select value={formatNumber(modal.modalProps.end.month)} onChange={(e) => onUpdatePeriodForm(e, 'end', 'month', modal.modalProps)} id="q_validity_period_end_gteq_2i" className="date required form-control"> {makeMonthsOptions(modal.modalProps.end.month)} </select> - <select value={modal.modalProps.end.year} onChange={(e) => onUpdatePeriodForm(e, 'end', 'year')} id="q_validity_period_end_gteq_1i" className="date required form-control"> + <select value={modal.modalProps.end.year} onChange={(e) => onUpdatePeriodForm(e, 'end', 'year', modal.modalProps)} id="q_validity_period_end_gteq_1i" className="date required form-control"> {makeYearsOptions(modal.modalProps.end.year)} </select> </div> diff --git a/app/assets/javascripts/es6_browserified/time_tables/containers/PeriodForm.js b/app/assets/javascripts/es6_browserified/time_tables/containers/PeriodForm.js index a7edbc328..7f2db785a 100644 --- a/app/assets/javascripts/es6_browserified/time_tables/containers/PeriodForm.js +++ b/app/assets/javascripts/es6_browserified/time_tables/containers/PeriodForm.js @@ -1,6 +1,7 @@ var connect = require('react-redux').connect var PeriodFormComponent = require('../components/PeriodForm') var actions = require('../actions') +var _ = require('lodash') const mapStateToProps = (state) => { return { @@ -18,10 +19,13 @@ const mapDispatchToProps = (dispatch) => { onClosePeriodForm: () => { dispatch(actions.closePeriodForm()) }, - onUpdatePeriodForm: (e, group, selectType) => { + onUpdatePeriodForm: (e, group, selectType, modalProps) => { dispatch(actions.updatePeriodForm(e.currentTarget.value, group, selectType)) - let selector = '#q_validity_period_' + group + '_gteq_3i' - dispatch(actions.updatePeriodForm($(selector).val(), group, 'day')) + let mProps = _.assign({}, modalProps) + mProps[group][selectType] = e.currentTarget.value + let val = window.correctDay([parseInt(mProps[group]['day']), parseInt(mProps[group]['month']), parseInt(mProps[group]['year'])]) + val = (val < 10) ? '0' + String(val) : String(val) + dispatch(actions.updatePeriodForm(val, group, 'day')) }, onValidatePeriodForm: (modalProps, timeTablePeriods, metas) => { dispatch(actions.validatePeriodForm(modalProps, timeTablePeriods, metas)) diff --git a/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js b/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js index e90d2d307..c30f460d8 100644 --- a/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js +++ b/app/assets/javascripts/es6_browserified/vehicle_journeys/actions/index.js @@ -449,12 +449,18 @@ const actions = { if (parseInt(schedule.departure_time.minute) < 0){ hours = Math.floor(parseInt(schedule.departure_time.minute) / 60) minutes = (parseInt(schedule.departure_time.minute) % 60) + 60 + if(minutes == 60){ + minutes = 0 + } schedule.departure_time.minute = actions.simplePad(minutes, 'minute') schedule.departure_time.hour = parseInt(schedule.departure_time.hour) + hours } if (parseInt(schedule.arrival_time.minute) < 0){ hours = Math.floor(parseInt(schedule.arrival_time.minute) / 60) minutes = (parseInt(schedule.arrival_time.minute) % 60) + 60 + if(minutes == 60){ + minutes = 0 + } schedule.arrival_time.minute = actions.simplePad(minutes, 'minute') schedule.arrival_time.hour = parseInt(schedule.arrival_time.hour) + hours } diff --git a/app/assets/javascripts/smart_date.coffee b/app/assets/javascripts/smart_date.coffee index afc0c7ddf..48aa1c2f9 100644 --- a/app/assets/javascripts/smart_date.coffee +++ b/app/assets/javascripts/smart_date.coffee @@ -2,8 +2,6 @@ window.legalDaysPerMonth = false: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], true: [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] - -window.legal window.correctDay = (dateValues) -> [day, month, year] = dateValues return day unless day > 0 && month > 0 && year > 0 diff --git a/app/assets/stylesheets/components/_tables.sass b/app/assets/stylesheets/components/_tables.sass index 20679a3ba..b991e7b8d 100644 --- a/app/assets/stylesheets/components/_tables.sass +++ b/app/assets/stylesheets/components/_tables.sass @@ -296,7 +296,7 @@ border-right: 1px solid rgba($grey, 0.5) .th - > div + > div:not(.btn-group) min-height: 19px > *:first-child diff --git a/app/assets/stylesheets/modules/_jp_collection.sass b/app/assets/stylesheets/modules/_jp_collection.sass index c109fc71a..f579cf87b 100644 --- a/app/assets/stylesheets/modules/_jp_collection.sass +++ b/app/assets/stylesheets/modules/_jp_collection.sass @@ -98,3 +98,33 @@ left: -23px top: 50% margin-top: -8px + + // Errors + .table-2entries .t2e-item-list + .t2e-item + position: relative + + .th .vj_tt + display: inline-block + vertical-align: top + + + .vj_tt + margin-left: 5px + + &.has-error + &:before + content: '' + position: absolute + top: 0 + left: 0 + right: 0 + bottom: 0 + border: 2px solid $red + + > .th + > div:first-child, > div:first-child + div + color: $red + + // Reset default behaviour + .form-control + border-color: #ccc diff --git a/app/controllers/time_tables_controller.rb b/app/controllers/time_tables_controller.rb index 3704f2885..6d2639981 100644 --- a/app/controllers/time_tables_controller.rb +++ b/app/controllers/time_tables_controller.rb @@ -49,8 +49,8 @@ class TimeTablesController < ChouetteController calendar.dates.each_with_index do |date, i| @time_table.dates << Chouette::TimeTableDate.new(date: date, position: i, in_out: true) end - calendar.date_ranges.each_with_index do |date_range, i| - @time_table.periods << Chouette::TimeTablePeriod.new(period_start: date_range.begin, period_end: date_range.end, position: i) + calendar.periods.each_with_index do |period, i| + @time_table.periods << Chouette::TimeTablePeriod.new(period_start: period.begin, period_end: period.end, position: i) end end diff --git a/app/helpers/links_helper.rb b/app/helpers/links_helper.rb index 683b66a52..4fb7a797d 100644 --- a/app/helpers/links_helper.rb +++ b/app/helpers/links_helper.rb @@ -1,5 +1,5 @@ module LinksHelper def destroy_link_content(translation_key = 'actions.destroy') - content_tag(:span, nil, class: 'fa fa-trash') + t(translation_key) + content_tag(:span, nil, class: 'fa fa-trash mr-xs') + t(translation_key) end end diff --git a/app/models/calendar.rb b/app/models/calendar.rb index 70fea9619..fb575515a 100644 --- a/app/models/calendar.rb +++ b/app/models/calendar.rb @@ -28,7 +28,7 @@ class Calendar < ActiveRecord::Base self.dates.each do |d| tt.dates << Chouette::TimeTableDate.new(date: d, in_out: true) end - self.date_ranges.each do |p| + self.periods.each do |p| tt.periods << Chouette::TimeTablePeriod.new(period_start: p.begin, period_end: p.end) end end diff --git a/app/models/chouette/journey_pattern.rb b/app/models/chouette/journey_pattern.rb index a146dcff1..868d8121e 100644 --- a/app/models/chouette/journey_pattern.rb +++ b/app/models/chouette/journey_pattern.rb @@ -27,7 +27,7 @@ class Chouette::JourneyPattern < Chouette::TridentActiveRecord jp = find_by(objectid: item['object_id']) || state_create_instance(route, item) next if item['deletable'] && jp.persisted? && jp.destroy # Update attributes and stop_points associations - jp.update_attributes(state_permited_attributes(item)) + jp.update_attributes(state_permited_attributes(item)) unless item['new_record'] jp.state_stop_points_update(item) if !jp.errors.any? && jp.persisted? item['errors'] = jp.errors if jp.errors.any? end @@ -53,6 +53,13 @@ class Chouette::JourneyPattern < Chouette::TridentActiveRecord def self.state_create_instance route, item # Flag new record, so we can unset object_id if transaction rollback jp = route.journey_patterns.create(state_permited_attributes(item)) + + # FIXME + # DefaultAttributesSupport will trigger some weird validation on after save + # wich will call to valid?, wich will populate errors + # In this case, we mark jp to be valid if persisted? return true + jp.errors.clear if jp.persisted? + item['object_id'] = jp.objectid item['new_record'] = true jp diff --git a/app/models/chouette/time_table.rb b/app/models/chouette/time_table.rb index c566452f4..d907d797e 100644 --- a/app/models/chouette/time_table.rb +++ b/app/models/chouette/time_table.rb @@ -496,33 +496,39 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord self.convert_continuous_dates_to_periods end + def included_days_in_dates_and_periods + in_day = self.dates.select {|d| d.in_out }.map(&:date) + out_day = self.dates.select {|d| !d.in_out }.map(&:date) + + in_periods = self.periods.map{|p| (p.period_start..p.period_end).to_a }.flatten + days = in_periods + in_day + days -= out_day + days + end + # remove dates form tt which aren't in another_tt def intersect!(another_tt) transaction do - - # transform tt as effective dates and get common ones - days = another_tt.intersects(self.effective_days) & self.intersects(another_tt.effective_days) + days = self.included_days_in_dates_and_periods & another_tt.included_days_in_dates_and_periods self.dates.clear - days.each {|d| self.dates << Chouette::TimeTableDate.new( :date =>d, :in_out => true)} self.periods.clear - self.dates.to_a.sort! { |a,b| a.date <=> b.date} + days.sort.each do |d| + self.dates << Chouette::TimeTableDate.new(:date => d, :in_out => true) + end self.save! end self.convert_continuous_dates_to_periods end - + # remove days from another calendar def disjoin!(another_tt) transaction do - # remove days from another calendar - days_to_exclude = self.intersects(another_tt.effective_days) - days = self.effective_days - days_to_exclude + days = self.included_days_in_dates_and_periods - another_tt.included_days_in_dates_and_periods self.dates.clear self.periods.clear - days.each {|d| self.dates << Chouette::TimeTableDate.new( :date =>d, :in_out => true)} - - self.dates.to_a.sort! { |a,b| a.date <=> b.date} - self.periods.to_a.sort! { |a,b| a.period_start <=> b.period_start} + days.sort.each do |d| + self.dates << Chouette::TimeTableDate.new(:date => d, :in_out => true) + end self.save! end self.convert_continuous_dates_to_periods diff --git a/app/models/clean_up.rb b/app/models/clean_up.rb index e39928a17..cbcde72f5 100644 --- a/app/models/clean_up.rb +++ b/app/models/clean_up.rb @@ -16,10 +16,13 @@ class CleanUp < ActiveRecord::Base def clean {}.tap do |result| - result['time_table'] = send("destroy_time_tables_#{self.date_type}").try(:count) + processed = send("destroy_time_tables_#{self.date_type}") + if processed + result['time_table'] = processed[:time_tables].try(:count) + result['vehicle_journey'] = processed[:vehicle_journeys].try(:count) + end result['time_table_date'] = send("destroy_time_tables_dates_#{self.date_type}").try(:count) result['time_table_period'] = send("destroy_time_tables_periods_#{self.date_type}").try(:count) - result['vehicle_journey'] = destroy_vehicle_journey_without_time_table.try(:count) self.overlapping_periods.each do |period| exclude_dates_in_overlapping_period(period) end @@ -106,13 +109,16 @@ class CleanUp < ActiveRecord::Base end def destroy_time_tables(time_tables) + results = { :time_tables => [], :vehicle_journeys => [] } # Delete vehicle_journey time_table association time_tables.each do |time_table| time_table.vehicle_journeys.each do |vj| vj.time_tables.delete(time_table) + results[:vehicle_journeys] << vj.destroy if vj.time_tables.empty? end end - time_tables.destroy_all + results[:time_tables] = time_tables.destroy_all + results end aasm column: :status do diff --git a/app/models/referential_metadata.rb b/app/models/referential_metadata.rb index 357465c63..b774072c7 100644 --- a/app/models/referential_metadata.rb +++ b/app/models/referential_metadata.rb @@ -44,8 +44,8 @@ class ReferentialMetadata < ActiveRecord::Base validate :check_end_greather_than_begin def check_end_greather_than_begin - if self.begin and self.end and self.begin > self.end - errors.add(:end, :invalid) + if self.begin and self.end and self.begin >= self.end + errors.add(:base, I18n.t('referentials.errors.short_period')) end end diff --git a/app/views/access_link_pairs/_access_link_pair.html.slim b/app/views/access_link_pairs/_access_link_pair.html.slim index 3eebfd7f6..c313f9044 100644 --- a/app/views/access_link_pairs/_access_link_pair.html.slim +++ b/app/views/access_link_pairs/_access_link_pair.html.slim @@ -1,5 +1,4 @@ tr - - require 'pry'; binding.pry td .link .access_point diff --git a/app/views/calendars/show.html.slim b/app/views/calendars/show.html.slim index 26248cea8..4ce5de57f 100644 --- a/app/views/calendars/show.html.slim +++ b/app/views/calendars/show.html.slim @@ -25,4 +25,4 @@ Calendar.human_attribute_name(:shared) => t("#{@calendar.shared}"), 'Organisation' => @calendar.organisation.name, Calendar.human_attribute_name(:dates) => @calendar.dates.collect{|d| l(d, format: :short)}.join(', ').html_safe, - Calendar.human_attribute_name(:date_ranges) => @calendar.date_ranges.collect{|d| t('validity_range', debut: l(d.begin, format: :short), end: l(d.end, format: :short))}.join('<br>').html_safe } + Calendar.human_attribute_name(:date_ranges) => @calendar.periods.map{|d| t('validity_range', debut: l(d.begin, format: :short), end: l(d.end, format: :short))}.join('<br>').html_safe } diff --git a/bin/bundle b/bin/bundle deleted file mode 100755 index 66e9889e8..000000000 --- a/bin/bundle +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) -load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails deleted file mode 100755 index f2b0313dd..000000000 --- a/bin/rails +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError => e - raise unless e.message.include?('spring') -end -APP_PATH = File.expand_path('../../config/application', __FILE__) -require_relative '../config/boot' -require 'rails/commands' diff --git a/bin/rake b/bin/rake deleted file mode 100755 index d87d5f578..000000000 --- a/bin/rake +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError => e - raise unless e.message.include?('spring') -end -require_relative '../config/boot' -require 'rake' -Rake.application.run diff --git a/bin/spring b/bin/spring deleted file mode 100755 index fb2ec2ebb..000000000 --- a/bin/spring +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env ruby - -# This file loads spring without using Bundler, in order to be fast. -# It gets overwritten when you run the `spring binstub` command. - -unless defined?(Spring) - require 'rubygems' - require 'bundler' - - lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read) - spring = lockfile.specs.detect { |spec| spec.name == "spring" } - if spring - Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path - gem 'spring', spring.version - require 'spring/binstub' - end -end diff --git a/config/deploy.rb b/config/deploy.rb index 0445ec480..4ab888e92 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -51,7 +51,7 @@ namespace :deploy do end task :bundle_link do - run "ln -fs #{bundle_cmd} #{release_path}/bin/bundle" + run "mkdir -p #{release_path}/bin && ln -fs #{bundle_cmd} #{release_path}/bin/bundle" end after "bundle:install", "deploy:bundle_link" diff --git a/config/locales/referentials.fr.yml b/config/locales/referentials.fr.yml index b9e337503..f69c26276 100644 --- a/config/locales/referentials.fr.yml +++ b/config/locales/referentials.fr.yml @@ -41,6 +41,7 @@ fr: user_excluded: "%{user} est une valeur réservée" overlapped_referential: "%{referential} couvre le même périmètre d'offre" overlapped_period: "Une autre période chevauche cette période" + short_period: La durée minimum d'une période est de deux jours activerecord: models: referential: diff --git a/spec/helpers/table_builder_helper_spec.rb b/spec/helpers/table_builder_helper_spec.rb index 8f4d98c88..67980fc2c 100644 --- a/spec/helpers/table_builder_helper_spec.rb +++ b/spec/helpers/table_builder_helper_spec.rb @@ -81,7 +81,7 @@ describe TableBuilderHelper, type: :helper do <li><a href="/referentials/#{referential.id}/time_tables">Calendriers</a></li> <li><a href="/referentials/new?from=#{referential.id}">Dupliquer</a></li> <li><a rel="nofollow" data-method="put" href="/referentials/#{referential.id}/archive">Conserver</a></li> - <li class="delete-action"><a data-confirm="Etes vous sûr de vouloir supprimer ce jeu de données ?" rel="nofollow" data-method="delete" href="/referentials/#{referential.id}"><span class="fa fa-trash"></span>Supprimer</a></li> + <li class="delete-action"><a data-confirm="Etes vous sûr de vouloir supprimer ce jeu de données ?" rel="nofollow" data-method="delete" href="/referentials/#{referential.id}"><span class="fa fa-trash mr-xs"></span>Supprimer</a></li> </ul> </div> </td> diff --git a/spec/models/calendar_spec.rb b/spec/models/calendar_spec.rb index cf7e4aa27..f5020ebf8 100644 --- a/spec/models/calendar_spec.rb +++ b/spec/models/calendar_spec.rb @@ -8,13 +8,13 @@ RSpec.describe Calendar, :type => :model do it { is_expected.to validate_uniqueness_of(:short_name) } describe '#to_time_table' do - let(:calendar) { create(:calendar, date_ranges: [Date.today..(Date.today + 1.month)]) } + let(:calendar) { create(:calendar, date_ranges: [Date.today...(Date.today + 1.month)]) } it 'should convert calendar to an instance of Chouette::TimeTable' do time_table = calendar.convert_to_time_table expect(time_table).to be_an_instance_of(Chouette::TimeTable) - expect(time_table.periods[0].period_start).to eq(calendar.date_ranges[0].begin) - expect(time_table.periods[0].period_end).to eq(calendar.date_ranges[0].end) + expect(time_table.periods[0].period_start).to eq(calendar.periods[0].begin) + expect(time_table.periods[0].period_end).to eq(calendar.periods[0].end) expect(time_table.dates.map(&:date)).to match_array(calendar.dates) end end diff --git a/spec/models/chouette/journey_pattern_spec.rb b/spec/models/chouette/journey_pattern_spec.rb index aaf9a694f..6601ed5f4 100644 --- a/spec/models/chouette/journey_pattern_spec.rb +++ b/spec/models/chouette/journey_pattern_spec.rb @@ -20,6 +20,11 @@ describe Chouette::JourneyPattern, :type => :model do expect(journey_pattern).to_not be_valid expect(journey_pattern.errors).to have_key(:stop_points) end + + it 'should only validate on update' do + jp = build(:journey_pattern_common) + expect(jp).to be_valid + end end describe "state_update" do diff --git a/spec/models/chouette/time_table_spec.rb b/spec/models/chouette/time_table_spec.rb index 76c5def5c..bd74a2d4c 100644 --- a/spec/models/chouette/time_table_spec.rb +++ b/spec/models/chouette/time_table_spec.rb @@ -7,6 +7,10 @@ describe Chouette::TimeTable, :type => :model do it { is_expected.to validate_presence_of :comment } it { is_expected.to validate_uniqueness_of :objectid } + def create_time_table_periode time_table, start_date, end_date + create(:time_table_period, time_table: time_table, :period_start => start_date, :period_end => end_date) + end + 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 } } @@ -72,6 +76,134 @@ describe Chouette::TimeTable, :type => :model do end end + describe "#disjoin!" do + let(:another_tt) { create(:time_table) } + + context 'dates' do + before do + subject.periods.clear + another_tt.periods.clear + end + + it 'should remove common dates' do + subject.disjoin!(another_tt) + expect(subject.reload.dates).to be_empty + end + + it 'should remove common dates with mixed none common dates' do + another_tt.dates.clear + another_tt.dates << create(:time_table_date, time_table: another_tt, date: subject.dates[0].date) + + subject.disjoin!(another_tt) + expect(subject.reload.dates.map(&:date)).to_not include(another_tt.dates[0].date) + end + end + + context 'periods' do + let(:another_tt_periods_to_range) { another_tt.periods.map{|p| p.period_start..p.period_end } } + # Clear dates as we are testing periods + before do + subject.dates.clear + another_tt.dates.clear + end + + it 'should remove common dates in periods' do + subject.disjoin!(another_tt) + expect(subject_periods_to_range).to_not include(*another_tt_periods_to_range) + end + + it 'should build new period without common dates in periods' do + subject.periods.clear + another_tt.periods.clear + + subject.periods << create_time_table_periode(subject, Date.today, Date.today + 10.day) + another_tt.periods << create_time_table_periode(another_tt, Date.tomorrow, Date.today + 3.day) + + subject.disjoin!(another_tt) + expected_range = Date.tomorrow..Date.today + 3.day + + expect(subject_periods_to_range).to_not include(expected_range) + expect(subject.periods.count).to eq 1 + end + end + end + + describe '#intersect! with time_table' do + let(:another_tt) { create(:time_table) } + + context 'dates' do + # Clear periods as we are testing dates + before do + subject.periods.clear + another_tt.periods.clear + end + + it 'should keep common dates' do + days = subject.dates.map(&:date) + subject.intersect!(another_tt) + expect(subject.included_days_in_dates_and_periods).to include(*days) + end + + it 'should not keep dates who are not in common' do + # Add 1 year interval, to make sur we have not dates in common + another_tt.dates.map{|d| d.date = d.date + 1.year } + subject.intersect!(another_tt) + + expect(subject.reload.dates).to be_empty + end + end + + context 'periods' do + let(:another_tt_periods_to_range) { another_tt.periods.map{|p| p.period_start..p.period_end } } + # Clear dates as we are testing periods + before do + subject.dates.clear + another_tt.dates.clear + end + + it 'should keep common dates in periods' do + subject.intersect!(another_tt) + expect(subject_periods_to_range).to include(*another_tt_periods_to_range) + end + + it 'should build new period with common dates in periods' do + subject.periods.clear + another_tt.periods.clear + + subject.periods << create_time_table_periode(subject, Date.today, Date.today + 10.day) + another_tt.periods << create_time_table_periode(another_tt, Date.tomorrow, Date.today + 3.day) + + subject.intersect!(another_tt) + expected_range = Date.tomorrow..Date.today + 3.day + + expect(subject_periods_to_range).to include(expected_range) + expect(subject.periods.count).to eq 1 + end + + it 'should not keep dates in periods who are not in common' do + another_tt.periods.map do |p| + p.period_start = p.period_start + 1.year + p.period_end = p.period_end + 1.year + end + + subject.intersect!(another_tt) + expect(subject.periods).to be_empty + end + + context 'with calendar' do + let(:period_start) { subject.periods[0].period_start } + let(:period_end) { subject.periods[0].period_end } + let(:another_tt) { create(:calendar, date_ranges: [period_start..period_end]).convert_to_time_table } + + it 'should keep common dates in periods' do + subject.intersect!(another_tt) + expect(subject.reload.periods.count).to eq 1 + expect(subject_periods_to_range).to include(*another_tt_periods_to_range) + end + end + end + end + describe "actualize" do let(:calendar) { create(:calendar) } let(:int_day_types) { 508 } @@ -1037,378 +1169,6 @@ end end end - describe "#intersect!" do - context "timetables have periods with common day_types " do - before do - subject.periods.clear - subject.dates.clear - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,1), :period_end => Date.new(2014,8,6)) - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,6,30), :period_end => Date.new(2014,7,20)) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,16), :in_out => true) - subject.int_day_types = 4|16|32|128 - another_tt = create(:time_table , :int_day_types => (4|16|64|128) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,6), :period_end => Date.new(2014,8,12)) - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,7,15), :period_end => Date.new(2014,7,25)) - subject.intersect! another_tt - subject.reload - end - it "should have no period" do - expect(subject.periods.size).to eq(0) - end - it "should have date all common days" do - expect(subject.dates.size).to eq(3) - expect(subject.dates[0].date).to eq(Date.new(2014,7,16)) - expect(subject.dates[1].date).to eq(Date.new(2014,7,19)) - expect(subject.dates[2].date).to eq(Date.new(2014,8,6)) - end - end - context "timetables have periods or dates " do - before do - subject.periods.clear - subject.dates.clear - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,16), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,17), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,18), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,19), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,20), :in_out => true) - subject.int_day_types = 0 - another_tt = create(:time_table , :int_day_types => (4|16|64|128) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,6), :period_end => Date.new(2014,8,12)) - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,7,17), :period_end => Date.new(2014,7,25)) - subject.intersect! another_tt - subject.reload - end - it "should have 0 period" do - expect(subject.periods.size).to eq(0) - end - it "should not modify day_types" do - expect(subject.int_day_types).to eq(0) - end - it "should have date reduced for period" do - expect(subject.dates.size).to eq(2) - expect(subject.dates[0].date).to eq(Date.new(2014,7,18)) - expect(subject.dates[1].date).to eq(Date.new(2014,7,19)) - end - end - context "with only periods : intersect timetable have no one day period" do - before do - subject.periods.clear - subject.dates.clear - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,1), :period_end => Date.new(2014,8,6)) - subject.int_day_types = 4|8|16 - another_tt = create(:time_table , :int_day_types => (4|8|16) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,6), :period_end => Date.new(2014,8,12)) - subject.intersect! another_tt - subject.reload - end - it "should have 0 result periods" do - expect(subject.periods.size).to eq(0) - end - it "should not modify day_types" do - expect(subject.int_day_types).to eq(4|8|16) - end - it "should have 1 date " do - expect(subject.dates.size).to eq(1) - expect(subject.dates[0].date).to eq(Date.new(2014,8,6)) - end - end - - end - - describe "#disjoin!" do - context "timetables have periods with common day_types " do - before do - subject.periods.clear - subject.dates.clear - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,1), :period_end => Date.new(2014,8,6)) - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,6,30), :period_end => Date.new(2014,7,20)) - subject.int_day_types = 4|16|32|128 - another_tt = create(:time_table , :int_day_types => (4|16|64|128) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,6), :period_end => Date.new(2014,8,12)) - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,7,15), :period_end => Date.new(2014,8,2)) - subject.disjoin! another_tt - subject.reload - end - it "should have 0 periods" do - expect(subject.periods.size).to eq(0) - end - it "should have only dates " do - expect(subject.dates.size).to eq(11) - expect(subject.dates[0].date).to eq(Date.new(2014,6,30)) - expect(subject.dates[1].date).to eq(Date.new(2014,7,2)) - expect(subject.dates[2].date).to eq(Date.new(2014,7,3)) - expect(subject.dates[3].date).to eq(Date.new(2014,7,5)) - expect(subject.dates[4].date).to eq(Date.new(2014,7,7)) - expect(subject.dates[5].date).to eq(Date.new(2014,7,9)) - expect(subject.dates[6].date).to eq(Date.new(2014,7,10)) - expect(subject.dates[7].date).to eq(Date.new(2014,7,12)) - expect(subject.dates[8].date).to eq(Date.new(2014,7,14)) - expect(subject.dates[9].date).to eq(Date.new(2014,7,17)) - expect(subject.dates[10].date).to eq(Date.new(2014,8,4)) - end - end - context "timetables have periods or dates " do - before do - subject.periods.clear - subject.dates.clear - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,16), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,17), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,18), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,19), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,20), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,8,6), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,8,7), :in_out => true) - subject.int_day_types = 0 - another_tt = create(:time_table , :int_day_types => (4|16|64|128) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,6), :period_end => Date.new(2014,8,12)) - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,7,17), :period_end => Date.new(2014,7,25)) - subject.disjoin! another_tt - subject.reload - end - it "should have 0 period" do - expect(subject.periods.size).to eq(0) - end - it "should not modify day_types" do - expect(subject.int_day_types).to eq(0) - end - it "should have date reduced for period" do - expect(subject.dates.size).to eq(4) - expect(subject.dates[0].date).to eq(Date.new(2014,7,16)) - expect(subject.dates[1].date).to eq(Date.new(2014,7,17)) - expect(subject.dates[2].date).to eq(Date.new(2014,7,20)) - expect(subject.dates[3].date).to eq(Date.new(2014,8,7)) - end - end - context "disjoined timetable have all periods in removed ones " do - before do - subject.periods.clear - subject.dates.clear - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,1), :period_end => Date.new(2014,8,8)) - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,6,30), :period_end => Date.new(2014,7,20)) - subject.int_day_types = 4|16|32|128 - another_tt = create(:time_table , :int_day_types => (4|16|64|128) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,7,31), :period_end => Date.new(2014,8,12)) - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,6,30), :period_end => Date.new(2014,7,20)) - subject.disjoin! another_tt - subject.reload - end - it "should have 0 result periods" do - expect(subject.periods.size).to eq(0) - end - it "should have dates for period reduced" do - expect(subject.dates.size).to eq(4) - expect(subject.dates[0].date).to eq(Date.new(2014,7,3)) - expect(subject.dates[1].date).to eq(Date.new(2014,7,10)) - expect(subject.dates[2].date).to eq(Date.new(2014,7,17)) - expect(subject.dates[3].date).to eq(Date.new(2014,8,7)) - end - end - - context "timetable with dates against timetable with dates and periods" do - before do - subject.periods.clear - subject.dates.clear - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,16), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,17), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,18), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,19), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,20), :in_out => true) - subject.int_day_types = 0 - another_tt = create(:time_table , :int_day_types => (4|16|64|128) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,7,31), :period_end => Date.new(2014,8,12)) - another_tt.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,17), :in_out => true) - another_tt.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,18), :in_out => true) - subject.disjoin! another_tt - subject.reload - end - it "should have 0 result periods" do - expect(subject.periods.size).to eq(0) - end - it "should have 3 dates left" do - expect(subject.dates.size).to eq(3) - expect(subject.dates[0].date).to eq(Date.new(2014,7,16)) - expect(subject.dates[1].date).to eq(Date.new(2014,7,19)) - expect(subject.dates[2].date).to eq(Date.new(2014,7,20)) - end - end - - context "timetable with dates against timetable with dates and periods all covered" do - before do - subject.periods.clear - subject.dates.clear - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,1), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,2), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,5), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,6), :in_out => true) - subject.int_day_types = 512 - another_tt = create(:time_table , :int_day_types => (32|64|512) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,6,30), :period_end => Date.new(2014,7,11)) - another_tt.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,1), :in_out => true) - another_tt.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,2), :in_out => true) - another_tt.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,5), :in_out => true) - another_tt.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,6), :in_out => true) - subject.disjoin! another_tt - subject.reload - end - - it "should have 0 result periods" do - expect(subject.periods.size).to eq(0) - end - - it "should have 0 dates left" do - expect(subject.dates.size).to eq(0) - end - end - - context "with only periods : disjoined timetable have no empty period" do - before do - subject.periods.clear - subject.dates.clear - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,1), :period_end => Date.new(2014,8,8)) - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,10), :period_end => Date.new(2014,8,31)) - subject.int_day_types = 4|8 - another_tt = create(:time_table , :int_day_types => (4|8) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,4), :period_end => Date.new(2014,8,7)) - subject.disjoin! another_tt - subject.reload - end - - it "should have 0 result periods" do - expect(subject.periods.size).to eq(0) - end - - it "should have 6 dates " do - expect(subject.dates.size).to eq(6) - expect(subject.dates[0].date).to eq(Date.new(2014,8,11)) - expect(subject.dates[1].date).to eq(Date.new(2014,8,12)) - expect(subject.dates[2].date).to eq(Date.new(2014,8,18)) - expect(subject.dates[3].date).to eq(Date.new(2014,8,19)) - expect(subject.dates[4].date).to eq(Date.new(2014,8,25)) - expect(subject.dates[5].date).to eq(Date.new(2014,8,26)) - end - end - - context "with only periods : disjoined timetable have no one day period" do - before do - subject.periods.clear - subject.dates.clear - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,1), :period_end => Date.new(2014,8,6)) - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,10), :period_end => Date.new(2014,8,31)) - subject.int_day_types = 4|8|16 - another_tt = create(:time_table , :int_day_types => (4|8) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,4), :period_end => Date.new(2014,8,5)) - subject.disjoin! another_tt - subject.reload - end - - it "should have 3 result periods" do - expect(subject.periods.size).to eq(3) - [ - ['2014-08-11', '2014-08-13'], - ['2014-08-18', '2014-08-20'], - ['2014-08-25', '2014-08-27'] - ].each_with_index do |period, index| - expect(subject.periods[index].period_start.to_s).to eq(period[0]) - expect(subject.periods[index].period_end.to_s).to eq(period[1]) - end - end - - it "should not modify day_types" do - expect(subject.int_day_types).to eq(4|8|16) - end - - it "should have 1 dates " do - expect(subject.dates.size).to eq(1) - expect(subject.dates.first.date.to_s).to eq('2014-08-06') - end - end - - context "with periods against dates: disjoined timetable have no unused excluded date" do - before do - subject.periods.clear - subject.dates.clear - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,1), :period_end => Date.new(2014,8,8)) - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,10), :period_end => Date.new(2014,8,31)) - subject.int_day_types = 4|8|16 - another_tt = create(:time_table , :int_day_types => (0) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,8,4), :in_out => true) - another_tt.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,8,5), :in_out => true) - another_tt.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,8,7), :in_out => true) - subject.disjoin! another_tt - subject.reload - end - - it "should have same 3 result periods" do - expect(subject.periods.size).to eq(3) - [ - ['2014-08-11', '2014-08-13'], - ['2014-08-18', '2014-08-20'], - ['2014-08-25', '2014-08-27'] - ].each_with_index do |period, index| - expect(subject.periods[index].period_start.to_s).to eq(period[0]) - expect(subject.periods[index].period_end.to_s).to eq(period[1]) - end - end - - it "should not modify day_types" do - expect(subject.int_day_types).to eq(4|8|16) - end - - it "should have only 1 dates " do - expect(subject.dates.size).to eq(1) - expect(subject.dates.first.date.to_s).to eq('2014-08-06') - end - end - - - context "with same definition : dsjointed timetable should be empty" do - before do - subject.periods.clear - subject.dates.clear - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2015,6,1), :period_end => Date.new(2015,6,30)) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2015,6,16), :in_out => true) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2015,6,22), :in_out => false) - subject.int_day_types = 4|8|16|32|64|128|256 - another_tt = create(:time_table , :int_day_types => ( 4|8|16|32|64|128|256) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2015,6,1), :period_end => Date.new(2015,6,30)) - another_tt.dates << Chouette::TimeTableDate.new( :date => Date.new(2015,6,16), :in_out => true) - another_tt.dates << Chouette::TimeTableDate.new( :date => Date.new(2015,6,22), :in_out => false) - subject.disjoin! another_tt - subject.reload - end - it "should have same 0 result periods" do - expect(subject.periods.size).to eq(0) - end - it "should have 0 dates " do - expect(subject.dates.size).to eq(0) - end - end - end - describe "#duplicate" do it 'should also copy tags' do subject.tag_list.add('tag1', 'tag2') diff --git a/spec/models/clean_up_spec.rb b/spec/models/clean_up_spec.rb index ee88ca773..4dc692ab2 100644 --- a/spec/models/clean_up_spec.rb +++ b/spec/models/clean_up_spec.rb @@ -200,9 +200,17 @@ RSpec.describe CleanUp, :type => :model do end it 'should destroy time_table vehicle_journey association' do + vj = create(:vehicle_journey, time_tables: [time_table, create(:time_table)]) + cleaner.destroy_time_tables(Chouette::TimeTable.where(id: time_table.id)) + + expect(vj.reload.time_tables.map(&:id)).to_not include(time_table.id) + end + + it 'should also destroy associated vehicle_journey if it belongs to any other time_table' do vj = create(:vehicle_journey, time_tables: [time_table]) - cleaner.destroy_time_tables(Chouette::TimeTable.all) - expect(vj.reload.time_tables).to be_empty + expect{cleaner.destroy_time_tables(Chouette::TimeTable.all)}.to change { + Chouette::VehicleJourney.count + }.by(-1) end end diff --git a/spec/models/referential_metadata_spec.rb b/spec/models/referential_metadata_spec.rb index 0f628c8d1..91a2a7fc2 100644 --- a/spec/models/referential_metadata_spec.rb +++ b/spec/models/referential_metadata_spec.rb @@ -87,7 +87,7 @@ RSpec.describe ReferentialMetadata, :type => :model do it "should validate that end is greather than or equlals to begin" do expect(period(begin: "2016-11-21", end: "2016-11-22")).to be_valid - expect(period(begin: "2016-11-21", end: "2016-11-21")).to be_valid + expect(period(begin: "2016-11-21", end: "2016-11-21")).to_not be_valid expect(period(begin: "2016-11-22", end: "2016-11-21")).to_not be_valid end diff --git a/spec/policies/application_policy_spec.rb b/spec/policies/application_policy_spec.rb index a7234461e..3ec177209 100644 --- a/spec/policies/application_policy_spec.rb +++ b/spec/policies/application_policy_spec.rb @@ -7,7 +7,7 @@ RSpec.describe ApplicationPolicy, type: :policy do end it "allows a user with a different organisation" do - user.update_attribute :organisation, referential.organisation + user.organisation = referential.organisation expect_it.to permit(user_context, referential) end end diff --git a/spec/policies/boiv_policy_spec.rb b/spec/policies/boiv_policy_spec.rb index 514534adc..6787ab2ac 100644 --- a/spec/policies/boiv_policy_spec.rb +++ b/spec/policies/boiv_policy_spec.rb @@ -1,5 +1,7 @@ RSpec.describe BoivPolicy, type: :policy do + let( :record ){ nil } + permissions :index? do it_behaves_like 'permitted policy and same organisation', 'boiv:read-offer' end diff --git a/spec/policies/line_policy_spec.rb b/spec/policies/line_policy_spec.rb index ead5918aa..e720b2bc7 100644 --- a/spec/policies/line_policy_spec.rb +++ b/spec/policies/line_policy_spec.rb @@ -1,5 +1,8 @@ RSpec.describe LinePolicy, type: :policy do + let( :record ){ build_stubbed :line } + + %w{create destroy edit}.each do | permission | footnote_permission = "#{permission}_footnote" permissions "#{footnote_permission}?".to_sym do diff --git a/spec/policies/route_policy_spec.rb b/spec/policies/route_policy_spec.rb index baf14c9fc..cc949ff45 100644 --- a/spec/policies/route_policy_spec.rb +++ b/spec/policies/route_policy_spec.rb @@ -1,5 +1,7 @@ RSpec.describe RoutePolicy, type: :policy do + let( :record ){ build_stubbed :route } + permissions :create? do it_behaves_like 'permitted policy', 'routes.create', archived: true end diff --git a/spec/policies/routing_constraint_zone_policy_spec.rb b/spec/policies/routing_constraint_zone_policy_spec.rb index 4b0f2cafe..2508b49f9 100644 --- a/spec/policies/routing_constraint_zone_policy_spec.rb +++ b/spec/policies/routing_constraint_zone_policy_spec.rb @@ -1,5 +1,8 @@ RSpec.describe RoutingConstraintZonePolicy, type: :policy do + let( :record ){ build_stubbed :routing_constraint_zone } + + permissions :create? do it_behaves_like 'permitted policy', 'routing_constraint_zones.create', archived: true end diff --git a/spec/policies/time_table_policy_spec.rb b/spec/policies/time_table_policy_spec.rb index 1283a9fcf..90e6600ea 100644 --- a/spec/policies/time_table_policy_spec.rb +++ b/spec/policies/time_table_policy_spec.rb @@ -1,5 +1,8 @@ RSpec.describe TimeTablePolicy, type: :policy do + let( :record ){ build_stubbed :time_table } + + permissions :duplicate? do it_behaves_like 'permitted policy and same organisation', 'time_tables.create', archived: true end diff --git a/spec/support/pundit/policies.rb b/spec/support/pundit/policies.rb index 56433b2ee..02fea2944 100644 --- a/spec/support/pundit/policies.rb +++ b/spec/support/pundit/policies.rb @@ -24,8 +24,8 @@ module Support into.module_eval do subject { described_class } let( :user_context ) { create_user_context(user: user, referential: referential) } - let( :referentail ) { create :referential } - let( :user ) { create :user } + let( :referential ) { build_stubbed :referential } + let( :user ) { build_stubbed :user } end end def with_user_permission(permission, &blk) diff --git a/spec/support/pundit/shared_examples.rb b/spec/support/pundit/shared_examples.rb index 4d14c46da..33ed1ffae 100644 --- a/spec/support/pundit/shared_examples.rb +++ b/spec/support/pundit/shared_examples.rb @@ -3,11 +3,11 @@ RSpec.shared_examples 'permitted policy and same organisation' do context 'permission absent → ' do it "denies a user with a different organisation" do - expect_it.not_to permit(user_context, referential) + expect_it.not_to permit(user_context, record) end it 'and also a user with the same organisation' do - user.update_attribute :organisation, referential.organisation - expect_it.not_to permit(user_context, referential) + user.organisation = referential.organisation + expect_it.not_to permit(user_context, record) end end @@ -17,19 +17,19 @@ RSpec.shared_examples 'permitted policy and same organisation' do end it 'denies a user with a different organisation' do - expect_it.not_to permit(user_context, referential) + expect_it.not_to permit(user_context, record) end it 'but allows it for a user with the same organisation' do - user.update_attribute :organisation, referential.organisation - expect_it.to permit(user_context, referential) + user.organisation = referential.organisation + expect_it.to permit(user_context, record) end if archived it 'removes the permission for archived referentials' do - user.update_attribute :organisation, referential.organisation - referential.update_attribute :archived_at, 42.seconds.ago - expect_it.not_to permit(user_context, referential) + user.organisation = referential.organisation + referential.archived_at = 42.seconds.ago + expect_it.not_to permit(user_context, record) end end end @@ -39,7 +39,7 @@ RSpec.shared_examples 'permitted policy' do | permission, archived: false| context 'permission absent → ' do it "denies a user with a different organisation" do - expect_it.not_to permit(user_context, referential) + expect_it.not_to permit(user_context, record) end end context 'permission present → ' do @@ -47,13 +47,13 @@ RSpec.shared_examples 'permitted policy' do add_permissions(permission, for_user: user) end it 'allows a user with a different organisation' do - expect_it.to permit(user_context, referential) + expect_it.to permit(user_context, record) end if archived it 'removes the permission for archived referentials' do - referential.update_attribute :archived_at, 42.seconds.ago - expect_it.not_to permit(user_context, referential) + referential.archived_at = 42.seconds.ago + expect_it.not_to permit(user_context, record) end end end |
