Merge pull request #5647 from betagouv/dev

2020-09-29-01
This commit is contained in:
Keirua 2020-09-29 14:28:59 +02:00 committed by GitHub
commit 05391be93a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 135 additions and 126 deletions

View file

@ -289,7 +289,7 @@ Layout/SpaceInsideReferenceBrackets:
Layout/SpaceInsideStringInterpolation:
Enabled: true
Layout/Tab:
Layout/IndentationStyle:
Enabled: true
Layout/TrailingEmptyLines:
@ -506,7 +506,7 @@ Lint/UselessAssignment:
Exclude:
- "spec/**/*"
Lint/UselessComparison:
Lint/BinaryOperatorWithIdenticalOperands:
Enabled: true
Lint/UselessElseWithoutRescue:
@ -1045,7 +1045,7 @@ Style/MethodCalledOnDoEndBlock:
Style/MethodDefParentheses:
Enabled: true
Style/MethodMissingSuper:
Lint/MissingSuper:
Enabled: false
Style/MinMax:
@ -1315,3 +1315,34 @@ Style/YodaCondition:
Style/ZeroLengthPredicate:
Enabled: true
Rails/ActiveRecordCallbacksOrder:
Enabled: false
Rails/AfterCommitOverride:
Enabled: true
Rails/FindById:
Enabled: true
Rails/Inquiry:
Enabled: true
Rails/MailerName:
Enabled: true
Rails/MatchRoute:
Enabled: true
Rails/NegateInclude:
Enabled: false
Rails/Pluck:
Enabled: false
Rails/PluckInWhere:
Enabled: true
Rails/RenderInline:
Enabled: true
Rails/RenderPlainText:
Enabled: true
Rails/ShortI18n:
Enabled: true
Rails/SquishedSQLHeredocs:
Enabled: true
Rails/WhereExists:
Enabled: true
Rails/WhereNot:
Enabled: true

View file

@ -3,8 +3,8 @@ source 'https://rubygems.org'
gem 'aasm'
gem 'active_link_to' # Automatically set a class on active links
gem 'active_model_serializers'
gem 'active_storage_validations'
gem 'activestorage-openstack'
gem 'active_storage_validations'
gem 'administrate'
gem 'after_party'
gem 'anchored'
@ -31,13 +31,13 @@ gem 'flipper-active_record'
gem 'flipper-ui'
gem 'font-awesome-rails'
gem 'fugit'
gem 'geo_coord', require: "geo/coord"
gem 'geocoder'
gem 'geo_coord', require: "geo/coord"
gem 'gon'
gem 'graphql'
gem 'graphql-batch'
gem 'graphql-rails_logger'
gem 'graphql_playground-rails'
gem 'graphql-rails_logger'
gem 'groupdate'
gem 'haml-rails'
gem 'hashie'
@ -118,8 +118,8 @@ group :development, :test do
gem 'graphql-schema_comparator'
gem 'mina', git: 'https://github.com/mina-deploy/mina.git', require: false # Deploy
gem 'pry-byebug'
gem 'rspec-rails'
gem 'rspec_junit_formatter', require: false
gem 'rspec-rails'
gem 'ruby-debug-ide', require: false
gem 'simple_xlsx_reader'
gem 'spring' # Spring speeds up development by keeping your application running in the background

View file

@ -127,7 +127,7 @@ GEM
bootstrap-wysihtml5-rails (0.3.3.8)
railties (>= 3.0)
brakeman (4.9.1)
browser (4.2.0)
browser (5.0.0)
builder (3.2.4)
byebug (11.1.3)
capybara (3.33.0)
@ -265,7 +265,7 @@ GEM
et-orbi (~> 1.1, >= 1.1.8)
raabro (~> 1.1)
geo_coord (0.1.0)
geocoder (1.6.2)
geocoder (1.6.3)
globalid (0.4.2)
activesupport (>= 4.2.0)
gon (6.3.2)
@ -344,7 +344,6 @@ GEM
iban-tools (1.1.0)
ice_nine (0.11.2)
ipaddress (0.8.3)
jaro_winkler (1.5.4)
jquery-rails (4.4.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
@ -354,7 +353,7 @@ GEM
aes_key_wrap
bindata
jsonapi-renderer (0.2.2)
jwt (2.2.1)
jwt (2.2.2)
kaminari (1.2.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.1)
@ -450,7 +449,7 @@ GEM
webfinger (>= 1.0.1)
orm_adapter (0.5.0)
parallel (1.19.2)
parser (2.7.1.4)
parser (2.7.1.5)
ast (~> 2.4.1)
pdf-core (0.7.0)
pg (1.2.3)
@ -554,7 +553,7 @@ GEM
execjs
railties (>= 3.2)
tilt
regexp_parser (1.7.1)
regexp_parser (1.8.0)
request_store (1.5.0)
rack (>= 1.4)
responders (3.0.1)
@ -597,23 +596,28 @@ GEM
rspec-support (3.9.3)
rspec_junit_formatter (0.4.1)
rspec-core (>= 2, < 4, != 2.12.0)
rubocop (0.81.0)
jaro_winkler (~> 1.5.1)
rubocop (0.92.0)
parallel (~> 1.10)
parser (>= 2.7.0.1)
parser (>= 2.7.1.5)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.7)
rexml
rubocop-ast (>= 0.5.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-performance (1.5.2)
rubocop (>= 0.71.0)
rubocop-rails (2.5.2)
activesupport
rubocop-ast (0.7.0)
parser (>= 2.7.1.5)
strscan (>= 1.0.0)
rubocop-performance (1.8.1)
rubocop (>= 0.87.0)
rubocop-ast (>= 0.4.0)
rubocop-rails (2.8.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 0.72.0)
rubocop-rails_config (0.10.0)
rubocop (>= 0.87.0)
rubocop-rails_config (0.12.6)
railties (>= 5.0)
rubocop (~> 0.80)
rubocop (~> 0.82)
rubocop-performance (~> 1.3)
rubocop-rails (~> 2.0)
rubocop-rspec-focused (1.0.0)
@ -685,6 +689,7 @@ GEM
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
strscan (1.0.3)
swd (1.1.2)
activesupport (>= 3)
attr_required (>= 0.0.5)

View file

@ -360,7 +360,7 @@ class StatsController < ApplicationController
if weekly_dossiers_count == 0
result = 0
else
weekly_dossier_with_avis_count = weekly_dossiers.filter { |dossier| dossier.avis.present? }.count
weekly_dossier_with_avis_count = weekly_dossiers.count { |dossier| dossier.avis.present? }
result = percentage(weekly_dossier_with_avis_count, weekly_dossiers_count)
end

View file

@ -37,7 +37,7 @@ module ChampHelper
when GeoArea.sources.fetch(:cadastre)
capture do
concat "Parcelle n° #{geo_area.numero} - Feuille #{geo_area.code_arr} #{geo_area.section} #{geo_area.feuille} - #{geo_area.surface_parcelle.round} m"
concat content_tag(:sup, "2")
concat tag.sup("2")
end
when GeoArea.sources.fetch(:quartier_prioritaire)
"#{geo_area.commune} : #{geo_area.nom}"
@ -48,7 +48,7 @@ module ChampHelper
if geo_area.area.present?
capture do
concat "Une aire de surface #{geo_area.area} m"
concat content_tag(:sup, "2")
concat tag.sup("2")
end
else
"Une aire de surface inconnue"

View file

@ -75,7 +75,7 @@ module DossierHelper
def status_badge(state)
status_text = dossier_display_state(state, lower: true)
status_class = state.tr('_', '-')
content_tag(:span, status_text, class: "label #{status_class} ")
tag.span(status_text, class: "label #{status_class} ")
end
def deletion_reason_badge(reason)
@ -87,7 +87,7 @@ module DossierHelper
status_class = 'unknown'
end
content_tag(:span, status_text, class: "label #{status_class} ")
tag.span(status_text, class: "label #{status_class} ")
end
def demandeur_dossier(dossier)

View file

@ -8,7 +8,7 @@ module ProcedureHelper
end
def procedure_libelle(procedure)
parts = procedure.brouillon? ? [content_tag(:span, 'démarche en test', class: 'badge')] : []
parts = procedure.brouillon? ? [tag.span('démarche en test', class: 'badge')] : []
parts << procedure.libelle
safe_join(parts, ' ')
end

View file

@ -3,6 +3,10 @@ class ApiEntreprise::Job < ApplicationJob
DEFAULT_MAX_ATTEMPTS_API_ENTREPRISE_JOBS = 5
# If by the time the job runs the Etablissement has been deleted
# (it can happen through EtablissementUpdateJob for instance), ignore the job
discard_on ActiveRecord::RecordNotFound
rescue_from(ApiEntreprise::API::ResourceNotFound) do |exception|
error(self, exception)
end

View file

@ -9,7 +9,7 @@ class ApplicationMailer < ActionMailer::Base
end
rescue_from Net::SMTPServerBusy do |error|
if error.message =~ /unexpected recipients/
if /unexpected recipients/.match?(error.message)
message.perform_deliveries = false
end
end

View file

@ -10,7 +10,7 @@ class DeviseUserMailer < Devise::Mailer
end
rescue_from Net::SMTPServerBusy do |error|
if error.message =~ /unexpected recipients/
if /unexpected recipients/.match?(error.message)
message.perform_deliveries = false
end
end

View file

@ -17,30 +17,9 @@
class Champs::PieceJustificativeChamp < Champ
MAX_SIZE = 200.megabytes
ACCEPTED_FORMATS = [
"text/plain",
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"application/vnd.oasis.opendocument.text",
"application/vnd.oasis.opendocument.presentation",
"application/vnd.oasis.opendocument.spreadsheet",
"image/png",
"image/jpeg"
]
# TODO: once we're running on Rails 6, re-enable this validation.
# See https://github.com/betagouv/demarches-simplifiees.fr/issues/4926
#
# validates :piece_justificative_file,
# content_type: ACCEPTED_FORMATS,
# size: { less_than: MAX_SIZE }
before_save :update_skip_pj_validation
validates :piece_justificative_file,
size: { less_than: MAX_SIZE },
if: -> { !type_de_champ.skip_pj_validation }
def main_value_name
:piece_justificative_file
@ -63,8 +42,4 @@ class Champs::PieceJustificativeChamp < Champ
piece_justificative_file.service_url
end
end
def update_skip_pj_validation
type_de_champ.update(skip_pj_validation: true)
end
end

View file

@ -8,7 +8,7 @@
# updated_at :datetime not null
#
class Export < ApplicationRecord
MAX_DUREE_CONSERVATION_EXPORT = 15.minutes
MAX_DUREE_CONSERVATION_EXPORT = 1.hour
enum format: {
csv: 'csv',
@ -24,7 +24,7 @@ class Export < ApplicationRecord
scope :stale, -> { where('updated_at < ?', (Time.zone.now - MAX_DUREE_CONSERVATION_EXPORT)) }
after_save_commit :compute_async
after_create_commit :compute_async
def compute_async
ExportJob.perform_later(self)

View file

@ -295,8 +295,7 @@ class ProcedurePresentation < ApplicationRecord
def valid_columns_for_table(table)
@column_whitelist ||= fields
.group_by { |field| field['table'] }
.map { |table, fields| [table, Set.new(fields.pluck('column'))] }
.to_h
.transform_values { |fields| Set.new(fields.pluck('column')) }
@column_whitelist[table] || []
end

View file

@ -27,7 +27,7 @@ class AdministrateurUsageStatisticsService
nb_dossiers_roi = nb_dossiers_by_procedure_id.reject { |procedure_id, _count| is_brouillon(procedure_id) }.map { |_procedure_id, count| count }.sum
result = {
ds_sign_in_count: administrateur.user.sign_in_count,
ds_sign_in_count: administrateur&.user&.sign_in_count,
ds_created_at: administrateur.created_at,
ds_active: administrateur.user.active?,
ds_id: administrateur.id,
@ -62,11 +62,11 @@ class AdministrateurUsageStatisticsService
admin_roi_high: nb_dossiers_roi * 17
}
if administrateur.user.current_sign_in_at.present?
if administrateur&.user&.current_sign_in_at.present?
result[:ds_current_sign_in_at] = administrateur.user.current_sign_in_at
end
if administrateur.user.last_sign_in_at.present?
if administrateur&.user&.last_sign_in_at.present?
result[:ds_last_sign_in_at] = administrateur.user.last_sign_in_at
end
@ -81,16 +81,12 @@ class AdministrateurUsageStatisticsService
with_default(
0,
nb_dossiers_by_administrateur_id_and_procedure_id_and_synthetic_state[administrateur_id]
.map do |procedure_id, nb_dossiers_by_synthetic_state|
[
procedure_id,
nb_dossiers_by_synthetic_state
.transform_values do |nb_dossiers_by_synthetic_state|
nb_dossiers_by_synthetic_state
.reject { |synthetic_state, _count| ['brouillon', 'archive'].include?(synthetic_state) }
.map { |_synthetic_state, count| count }
.sum
]
end
.to_h
)
end
@ -105,8 +101,7 @@ class AdministrateurUsageStatisticsService
.reject { |procedure_id, _nb_dossiers_by_synthetic_state| is_brouillon(procedure_id) }
.flat_map { |_procedure_id, nb_dossiers_by_synthetic_state| nb_dossiers_by_synthetic_state.to_a }
.group_by { |synthetic_state, _count| synthetic_state }
.map { |synthetic_state, synthetic_states_and_counts| [synthetic_state, synthetic_states_and_counts.map { |_synthetic_state, count| count }.sum] }
.to_h
.transform_values { |synthetic_states_and_counts| synthetic_states_and_counts.map { |_synthetic_state, count| count }.sum }
)
end

View file

@ -73,7 +73,11 @@ class ProcedureExportService
{ instances: table.last, sheet_name: table.first }
end.merge(DEFAULT_STYLES)
options[:sheet_name] = options[:sheet_name].truncate(30)
# transliterate: convert to ASCII characteres
# to ensure truncate respects 30 bytes
options[:sheet_name] = I18n.transliterate(options[:sheet_name], '')
.truncate(30, omission: '')
options
end
end

View file

@ -1,5 +1,5 @@
# This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__)
require ::File.expand_path('config/environment', __dir__)
run Rails.application

View file

@ -2,3 +2,4 @@ fr:
errors:
messages:
content_type_invalid: nest pas dun type accepté
file_size_out_of_range: "est trop lourde, elle doit faire au plus 200 Mo."

View file

@ -213,8 +213,7 @@ feature 'The routing', js: true do
def register_instructeur_and_log_in(email)
confirmation_email = emails_sent_to(email)
.filter { |m| m.subject == 'Activez votre compte instructeur' }
.first
.find { |m| m.subject == 'Activez votre compte instructeur' }
token_params = confirmation_email.body.match(/token=[^"]+/)
visit "users/activate?#{token_params}"

View file

@ -176,6 +176,13 @@ feature 'The user' do
create(:procedure, :published, :for_individual, types_de_champ: tdcs)
end
let(:old_procedure_with_disabled_pj_validation) do
tdcs = [
create(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative 1', order_place: 1, skip_pj_validation: true)
]
create(:procedure, :published, :for_individual, types_de_champ: tdcs)
end
scenario 'add an attachment', js: true do
log_in(user, procedure_with_pjs)
fill_individual
@ -200,25 +207,14 @@ feature 'The user' do
expect(page).to have_text('RIB.pdf')
end
# TODO: once we're running on Rails 6, re-enable the validator on PieceJustificativeChamp,
# and unmark this spec as pending.
#
# See piece_justificative_champ.rb
# See https://github.com/betagouv/demarches-simplifiees.fr/issues/4926
scenario 'add an invalid attachment', js: true, pending: true do
log_in(user, procedure_with_pjs)
scenario 'add an invalid attachment on an old procedure where pj validation is disabled', js: true do
log_in(user, old_procedure_with_disabled_pj_validation)
fill_individual
# Test invalid file type
attach_file('Pièce justificative 1', Rails.root + 'spec/fixtures/files/invalid_file_format.json')
expect(page).to have_text('La pièce justificative nest pas dun type accepté')
expect(page).to have_no_button('Ré-essayer', visible: true)
# Replace the file by another with a valid type
attach_file('Pièce justificative 1', Rails.root + 'spec/fixtures/files/piece_justificative_0.pdf')
expect(page).to have_no_text('La pièce justificative nest pas dun type accepté')
expect(page).to have_text('analyse antivirus en cours')
expect(page).to have_text('piece_justificative_0.pdf')
expect(page).to have_text('analyse antivirus en cours', count: 1)
end
scenario 'retry on transcient upload error', js: true do

View file

@ -18,4 +18,14 @@ RSpec.describe ApiEntreprise::AssociationJob, type: :job do
subject
expect(Etablissement.find(etablissement.id).association_rna).to eq('W595001988')
end
context "when the etablissement has been deleted" do
before do
allow_any_instance_of(Etablissement).to receive(:find) { raise ActiveRecord::RecordNotFound }
end
it "ignores the error" do
expect { subject }.not_to raise_error
end
end
end

View file

@ -151,13 +151,11 @@ describe AttestationTemplate, type: :model do
context 'and their value in the dossier are not nil' do
before do
dossier.champs
.filter { |champ| champ.libelle == 'libelleA' }
.first
.find { |champ| champ.libelle == 'libelleA' }
.update(value: 'libelle1')
dossier.champs
.filter { |champ| champ.libelle == 'libelleB' }
.first
.find { |champ| champ.libelle == 'libelleB' }
.update(value: 'libelle2')
end

View file

@ -3,7 +3,7 @@ require 'active_storage_validations/matchers'
describe Champs::PieceJustificativeChamp do
include ActiveStorageValidations::Matchers
describe "update_skip_validation" do
describe "skip_validation is not set anymore" do
subject { champ_pj.type_de_champ.skip_pj_validation }
context 'before_save' do
@ -12,19 +12,24 @@ describe Champs::PieceJustificativeChamp do
end
context 'after_save' do
let(:champ_pj) { create (:champ_piece_justificative) }
it { is_expected.to be_truthy }
it { is_expected.to be_falsy }
end
end
# TODO: once we're running on Rails 6, re-enable the PieceJustificativeChamp validator,
# and re-enable this spec.
#
# See https://github.com/betagouv/demarches-simplifiees.fr/issues/4926
describe "validations", pending: true do
subject(:champ_pj) { build(:champ_piece_justificative) }
describe "validations" do
let(:champ_pj) { create(:champ_piece_justificative) }
subject { champ_pj }
it { is_expected.to validate_size_of(:piece_justificative_file).less_than(Champs::PieceJustificativeChamp::MAX_SIZE) }
it { is_expected.to validate_content_type_of(:piece_justificative_file).allowing(Champs::PieceJustificativeChamp::ACCEPTED_FORMATS) }
context "by default" do
it { is_expected.to validate_size_of(:piece_justificative_file).less_than(Champs::PieceJustificativeChamp::MAX_SIZE) }
it { expect(champ_pj.type_de_champ.skip_pj_validation).to be_falsy }
end
context "when validation is disabled" do
before { champ_pj.type_de_champ.update(skip_pj_validation: true) }
it { is_expected.not_to validate_size_of(:piece_justificative_file).less_than(Champs::PieceJustificativeChamp::MAX_SIZE) }
end
end
describe "#for_export" do

View file

@ -123,13 +123,11 @@ describe TagsSubstitutionConcern, type: :model do
context 'and their value in the dossier are not nil' do
before do
dossier.champs
.filter { |champ| champ.libelle == 'libelleA' }
.first
.find { |champ| champ.libelle == 'libelleA' }
.update(value: 'libelle1')
dossier.champs
.filter { |champ| champ.libelle == 'libelleB' }
.first
.find { |champ| champ.libelle == 'libelleB' }
.update(value: 'libelle2')
end
@ -151,8 +149,7 @@ describe TagsSubstitutionConcern, type: :model do
context 'and their value in the dossier are not nil' do
before do
dossier.champs
.filter { |champ| champ.libelle == "Intitulé de l'‘«\"évènement\"»’" }
.first
.find { |champ| champ.libelle == "Intitulé de l'‘«\"évènement\"»’" }
.update(value: 'ceci est mon évènement')
end
@ -302,13 +299,11 @@ describe TagsSubstitutionConcern, type: :model do
context 'and its value in the dossier are not nil' do
before do
dossier.champs
.filter { |champ| champ.type_champ == TypeDeChamp.type_champs.fetch(:date) }
.first
.find { |champ| champ.type_champ == TypeDeChamp.type_champs.fetch(:date) }
.update(value: '2017-04-15')
dossier.champs
.filter { |champ| champ.type_champ == TypeDeChamp.type_champs.fetch(:datetime) }
.first
.find { |champ| champ.type_champ == TypeDeChamp.type_champs.fetch(:datetime) }
.update(value: '2017-09-13 09:00')
end

View file

@ -4,16 +4,8 @@ describe ChampSerializer do
let(:serializable_object) { champ }
context 'when type champ is piece justificative' do
include Rails.application.routes.url_helpers
let(:champ) { create(:champ_piece_justificative) }
before do
champ.piece_justificative_file.attach({ filename: __FILE__, io: File.open(__FILE__) })
champ.piece_justificative_file.blob.send(:enqueue_virus_scan)
end
after { champ.piece_justificative_file.purge }
it { expect(subject[:value]).to match('/rails/active_storage/disk/') }
end

View file

@ -356,10 +356,10 @@ describe ProcedureExportService do
end
end
context 'with long libelle' do
context 'with long libelle composed of utf8 characteres' do
before do
procedure.types_de_champ.each do |c|
c.update!(libelle: "#{c.id} - Quam rem nam maiores numquam dolorem nesciunt. Cum et possimus et aut. Fugit voluptas qui qui.")
c.update!(libelle: "#{c.id} - éééé ééé ééé ééééééé ééééééé ééééééé éééééééé. ééé éé éééééééé éé ééé. ééééé éééééééé ééé ééé.")
end
champ_repetition.champs.each do |c|
c.type_de_champ.update!(libelle: "#{c.id} - Quam rem nam maiores numquam dolorem nesciunt. Cum et possimus et aut. Fugit voluptas qui qui.")