diff --git a/app/admin/questions.rb b/app/admin/questions.rb index 49a1c5659..58f8327c2 100644 --- a/app/admin/questions.rb +++ b/app/admin/questions.rb @@ -15,8 +15,8 @@ controller do def import_xls - return if params[:file_xls].blank? - return invalide_format_xls unless ImportExport::ImportXls.fichier_xls?(params[:file_xls]) + return if fichier_import.blank? + return invalide_format_xls unless ImportExport::ImportXls.fichier_xls?(fichier_import) initialise_import flash[:success] = I18n.t('.layouts.succes.import_question') @@ -29,14 +29,22 @@ def import_xls private + def fichier_import + params[:question][:file_xls] + end + + def type_question + params[:question][:type] + end + def initialise_import - ImportExport::Questions::ImportExportDonnees.new(type: params[:type]) - .importe_donnees(params[:file_xls]) + ImportExport::Questions::ImportExportDonnees.new(type: type_question) + .importe_donnees(fichier_import) end def erreur_import(error) flash[:error] = error.message - redirect_to admin_import_xls_path(type: params[:type]) + redirect_to admin_import_xls_path(type: type_question) end private @@ -51,12 +59,12 @@ def redirection_apres_import QuestionClicDansTexte::QUESTION_TYPE => admin_questions_clic_dans_texte_path } - redirection_paths[params[:type]] || admin_questions_path + redirection_paths[type_question] || admin_questions_path end def invalide_format_xls flash[:error] = I18n.t('.layouts.erreurs.import_question.format_invalide', format: 'XLS') - redirect_to admin_import_xls_path(type: params[:type]) + redirect_to admin_import_xls_path(type: type_question) end end end diff --git a/app/models/import_export/questions/export.rb b/app/models/import_export/questions/export.rb index e034a783e..51573d74f 100644 --- a/app/models/import_export/questions/export.rb +++ b/app/models/import_export/questions/export.rb @@ -33,85 +33,25 @@ def remplis_la_feuille end def remplis_champs_commun - @onglet.set_valeur(@ligne, 0, @question.libelle) - @onglet.set_valeur(@ligne, 1, @question.nom_technique) - @onglet.set_valeur(@ligne, 2, @question.illustration_url) - @onglet.set_valeur(@ligne, 3, @question.transcription_intitule&.ecrit) - @onglet.set_valeur(@ligne, 4, @question.transcription_intitule&.audio_url) - remplis_champs_additionnels + col = -1 + @onglet.set_valeur(@ligne, col += 1, @question.libelle) + @onglet.set_valeur(@ligne, col += 1, @question.nom_technique) + @onglet.set_valeur(@ligne, col += 1, @question.illustration_url) + @onglet.set_valeur(@ligne, col += 1, @question.transcription_intitule&.ecrit) + @onglet.set_valeur(@ligne, col += 1, @question.transcription_intitule&.audio_url) + remplis_champs_additionnels(col) end - def remplis_champs_additionnels + def remplis_champs_additionnels(col) return if @question.sous_consigne? - @onglet.set_valeur(@ligne, 5, @question.transcription_modalite_reponse&.ecrit) - @onglet.set_valeur(@ligne, 6, @question.transcription_modalite_reponse&.audio_url) - @onglet.set_valeur(@ligne, 7, @question.description) - remplis_champs_specifiques + @onglet.set_valeur(@ligne, col += 1, @question.transcription_modalite_reponse&.ecrit) + @onglet.set_valeur(@ligne, col += 1, @question.transcription_modalite_reponse&.audio_url) + @onglet.set_valeur(@ligne, col += 1, @question.description) + remplis_champs_specifiques(col) end - def remplis_champs_specifiques - case @question.type - when QuestionClicDansImage::QUESTION_TYPE then remplis_champs_clic_dans_image - when QuestionGlisserDeposer::QUESTION_TYPE then remplis_champs_glisser_deposer - when QuestionQcm::QUESTION_TYPE then remplis_champs_qcm - when QuestionSaisie::QUESTION_TYPE then remplis_champs_saisie - when QuestionClicDansTexte::QUESTION_TYPE then remplis_champs_clic_dans_texte - end - end - - def remplis_champs_clic_dans_image - @onglet.set_valeur(@ligne, 8, @question.zone_cliquable_url) - @onglet.set_valeur(@ligne, 9, @question.image_au_clic_url) - end - - def remplis_champs_glisser_deposer - @onglet.set_valeur(@ligne, 8, @question.zone_depot_url) - @question.reponses.each_with_index { |choix, index| ajoute_reponses(choix, index) } - end - - def remplis_champs_saisie - @onglet.set_valeur(@ligne, 8, @question.suffix_reponse) - @onglet.set_valeur(@ligne, 9, @question.reponse_placeholder) - @onglet.set_valeur(@ligne, 10, @question.type_saisie) - @question.reponses.each_with_index { |reponse, index| ajoute_saisies(reponse, index) } - end - - def remplis_champs_qcm - @onglet.set_valeur(@ligne, 8, @question.type_qcm) - @question.choix.each_with_index { |choix, index| ajoute_choix(choix, index) } - end - - def remplis_champs_clic_dans_texte - @onglet.set_valeur(@ligne, 8, @question.texte_sur_illustration) - end - - def ajoute_choix(choix, index) - columns = %w[intitule nom_technique type_choix audio_url] - columns.each_with_index do |col, i| - colonne = 9 + (index * columns.size) + i - @onglet.set_valeur(0, colonne, "choix_#{index + 1}_#{col}") - @onglet.set_valeur(@ligne, colonne, choix.send(col)) - end - end - - def ajoute_saisies(reponse, index) - columns = %w[intitule nom_technique type_choix] - columns.each_with_index do |col, i| - colonne = 11 + (index * columns.size) + i - @onglet.set_valeur(0, colonne, "reponse_#{index + 1}_#{col}") - @onglet.set_valeur(@ligne, colonne, reponse.send(col)) - end - end - - def ajoute_reponses(choix, index) - columns = %w[nom_technique position_client type_choix illustration_url] - columns.each_with_index do |col, i| - colonne = 9 + (index * columns.size) + i - @onglet.set_valeur(0, colonne, "reponse_#{index + 1}_#{col}") - @onglet.set_valeur(@ligne, colonne, choix.send(col).to_s) - end - end + def remplis_champs_specifiques(col); end end end end diff --git a/app/models/import_export/questions/export/question_clic_dans_image.rb b/app/models/import_export/questions/export/question_clic_dans_image.rb new file mode 100644 index 000000000..241927606 --- /dev/null +++ b/app/models/import_export/questions/export/question_clic_dans_image.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module ImportExport + module Questions + class Export + class QuestionClicDansImage < ImportExport::Questions::Export + def initialize(questions, headers_commun) + headers = headers_commun + %i[zone_cliquable image_au_clic].freeze + super(questions, headers) + end + + def remplis_champs_specifiques(col) + @onglet.set_valeur(@ligne, col += 1, @question.zone_cliquable_url) + @onglet.set_valeur(@ligne, col += 1, @question.image_au_clic_url) # rubocop:disable Lint/UselessAssignment + end + end + end + end +end diff --git a/app/models/import_export/questions/export/question_clic_dans_texte.rb b/app/models/import_export/questions/export/question_clic_dans_texte.rb new file mode 100644 index 000000000..f89ab6b20 --- /dev/null +++ b/app/models/import_export/questions/export/question_clic_dans_texte.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module ImportExport + module Questions + class Export + class QuestionClicDansTexte < ImportExport::Questions::Export + def initialize(questions, headers_commun) + headers = headers_commun + %i[texte_sur_illustration].freeze + super(questions, headers) + end + + private + + def remplis_champs_specifiques(col) + @onglet.set_valeur(@ligne, col += 1, @question.texte_sur_illustration) # rubocop:disable Lint/UselessAssignment + end + end + end + end +end diff --git a/app/models/import_export/questions/export/question_glisser_deposer.rb b/app/models/import_export/questions/export/question_glisser_deposer.rb new file mode 100644 index 000000000..6ebc0ef93 --- /dev/null +++ b/app/models/import_export/questions/export/question_glisser_deposer.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module ImportExport + module Questions + class Export + class QuestionGlisserDeposer < ImportExport::Questions::Export + def initialize(questions, headers_commun) + headers = headers_commun + %i[zone_depot orientation].freeze + super(questions, headers) + end + + private + + def remplis_champs_specifiques(col) + @onglet.set_valeur(@ligne, col += 1, @question.zone_depot_url) + @onglet.set_valeur(@ligne, col += 1, @question.orientation) + @question.reponses.each_with_index do |choix, index| + ajoute_reponses(choix, index, col + 1) + end + end + + def ajoute_reponses(choix, index, col_debut) + columns = %w[nom_technique position_client type_choix illustration_url] + columns.each_with_index do |col, i| + colonne = col_debut + (index * columns.size) + i + @onglet.set_valeur(0, colonne, "reponse_#{index + 1}_#{col}") + @onglet.set_valeur(@ligne, colonne, choix.send(col).to_s) + end + end + end + end + end +end diff --git a/app/models/import_export/questions/export/question_qcm.rb b/app/models/import_export/questions/export/question_qcm.rb new file mode 100644 index 000000000..e31a5c223 --- /dev/null +++ b/app/models/import_export/questions/export/question_qcm.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module ImportExport + module Questions + class Export + class QuestionQcm < ImportExport::Questions::Export + def initialize(questions, headers_commun) + headers = headers_commun + %i[type_qcm].freeze + super(questions, headers) + end + + private + + def remplis_champs_specifiques(col) + @onglet.set_valeur(@ligne, col += 1, @question.type_qcm) + @question.choix.each_with_index do |choix, index| + ajoute_choix(choix, index, col + 1) + end + end + + def ajoute_choix(choix, index, col_debut) + columns = %w[intitule nom_technique type_choix audio_url] + columns.each_with_index do |col, i| + colonne = col_debut + (index * columns.size) + i + @onglet.set_valeur(0, colonne, "choix_#{index + 1}_#{col}") + @onglet.set_valeur(@ligne, colonne, choix.send(col)) + end + end + end + end + end +end diff --git a/app/models/import_export/questions/export/question_saisie.rb b/app/models/import_export/questions/export/question_saisie.rb new file mode 100644 index 000000000..86b59d197 --- /dev/null +++ b/app/models/import_export/questions/export/question_saisie.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module ImportExport + module Questions + class Export + class QuestionSaisie < ImportExport::Questions::Export + def initialize(questions, headers_commun) + headers = headers_commun + %i[suffix_reponse reponse_placeholder type_saisie + texte_a_trous].freeze + super(questions, headers) + end + + private + + def remplis_champs_specifiques(col) + @onglet.set_valeur(@ligne, col += 1, @question.suffix_reponse) + @onglet.set_valeur(@ligne, col += 1, @question.reponse_placeholder) + @onglet.set_valeur(@ligne, col += 1, @question.type_saisie) + @onglet.set_valeur(@ligne, col += 1, @question.texte_a_trous) + @question.reponses.each_with_index do |reponse, index| + ajoute_saisies(reponse, index, col + 1) + end + end + + def ajoute_saisies(reponse, index, col_debut) + columns = %w[intitule nom_technique type_choix] + columns.each_with_index do |col, i| + colonne = col_debut + (index * columns.size) + i + @onglet.set_valeur(0, colonne, "reponse_#{index + 1}_#{col}") + @onglet.set_valeur(@ligne, colonne, reponse.send(col)) + end + end + end + end + end +end diff --git a/app/models/import_export/questions/export/question_sous_consigne.rb b/app/models/import_export/questions/export/question_sous_consigne.rb new file mode 100644 index 000000000..0c2d39f5c --- /dev/null +++ b/app/models/import_export/questions/export/question_sous_consigne.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module ImportExport + module Questions + class Export + class QuestionSousConsigne < ImportExport::Questions::Export + def initialize(questions, _headers_commun) + headers = %i[libelle nom_technique illustration intitule_ecrit intitule_audio].freeze + super(questions, headers) + end + + private + + def remplis_champs_specifiques(col); end + end + end + end +end diff --git a/app/models/import_export/questions/import_export_donnees.rb b/app/models/import_export/questions/import_export_donnees.rb index 73774e42e..4b0010246 100644 --- a/app/models/import_export/questions/import_export_donnees.rb +++ b/app/models/import_export/questions/import_export_donnees.rb @@ -5,7 +5,7 @@ module Questions class ImportExportDonnees HEADERS_CLIC_DANS_IMAGE = %i[zone_cliquable image_au_clic].freeze HEADERS_CLIC_DANS_TEXTE = %i[texte_sur_illustration].freeze - HEADERS_GLISSER_DEPOSER = %i[zone_depot].freeze + HEADERS_GLISSER_DEPOSER = %i[zone_depot orientation].freeze HEADERS_QCM = %i[type_qcm].freeze HEADERS_SAISIE = %i[suffix_reponse reponse_placeholder type_saisie texte_a_trous].freeze HEADERS_SOUS_CONSIGNE = %i[libelle nom_technique illustration intitule_ecrit @@ -20,6 +20,14 @@ class ImportExportDonnees QuestionSaisie::QUESTION_TYPE => HEADERS_COMMUN + HEADERS_SAISIE, QuestionSousConsigne::QUESTION_TYPE => HEADERS_SOUS_CONSIGNE }.freeze + EXPORTEURS = { + QuestionClicDansImage::QUESTION_TYPE => Export::QuestionClicDansImage, + QuestionClicDansTexte::QUESTION_TYPE => Export::QuestionClicDansTexte, + QuestionGlisserDeposer::QUESTION_TYPE => Export::QuestionGlisserDeposer, + QuestionQcm::QUESTION_TYPE => Export::QuestionQcm, + QuestionSaisie::QUESTION_TYPE => Export::QuestionSaisie, + QuestionSousConsigne::QUESTION_TYPE => Export::QuestionSousConsigne + }.freeze def initialize(questions: nil, type: nil) @questions = questions @@ -33,7 +41,7 @@ def importe_donnees(file) end def exporte_donnees - export = Export.new(@questions, HEADERS_ATTENDUS[@type]) + export = EXPORTEURS[@type].new(@questions, HEADERS_COMMUN) { xls: export.to_xls, content_type: export.content_type_xls, diff --git a/spec/features/admin/import_xls_spec.rb b/spec/features/admin/import_xls_spec.rb new file mode 100644 index 000000000..08ab7d2b8 --- /dev/null +++ b/spec/features/admin/import_xls_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'Import XLS', type: :feature do + let!(:compte) { create :compte_superadmin } + + before { connecte(compte) } + + it 'importe un fichier XLS de type QuestionGlisserDeposer' do + visit admin_import_xls_path(type: 'QuestionGlisserDeposer') + + stub_request(:get, %r{^https://stockagepreprod\.eva\.beta\.gouv\.fr(/.*)?$}) + .to_return(status: 200, body: '', headers: {}) + + chemin_fichier = Rails.root.join('spec/support/import_question_glisser_deposer.xls').to_s + attach_file('question[file_xls]', chemin_fichier) + click_button 'Importer le fichier' + + expect(page).to have_http_status(200) + end +end diff --git a/spec/models/import_export/questions/export/question_clic_dans_image_spec.rb b/spec/models/import_export/questions/export/question_clic_dans_image_spec.rb new file mode 100644 index 000000000..dca0ee1e0 --- /dev/null +++ b/spec/models/import_export/questions/export/question_clic_dans_image_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe ImportExport::Questions::Export::QuestionClicDansImage do + subject(:response_service) do + response_service = described_class.new( + [question], ImportExport::Questions::ImportExportDonnees::HEADERS_COMMUN + ) + response_service.to_xls + response_service + end + + let(:spreadsheet) { response_service.export.workbook } + let(:worksheet) { spreadsheet.worksheet(0) } + let(:headers_xls) { worksheet.row(0).map { |header| header.parameterize.underscore.to_sym } } + + let(:question) do + create(:question_clic_dans_image, description: 'Ceci est une description', + nom_technique: 'clic') + end + let!(:intitule) do + create(:transcription, :avec_audio, question_id: question.id, categorie: :intitule, + ecrit: 'Ceci est un intitulé') + end + let!(:consigne) do + create(:transcription, :avec_audio, question_id: question.id, + categorie: :modalite_reponse, + ecrit: 'Ceci est une consigne') + end + let(:headers) do + ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[question.type] + end + + it 'génére un fichier xls avec les entêtes sur chaque colonnes' do + expect(spreadsheet.worksheets.count).to eq(1) + + headers_attendus = ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[ + QuestionClicDansImage::QUESTION_TYPE + ] + expect(headers_xls).to eq headers_attendus + end + + it 'génére un fichier xls avec les détails de la question' do + ligne = worksheet.row(1) + expect(ligne[0]).to eq('Question clic dans image') + expect(ligne[1]).to eq('clic') + expect(ligne[2]).to be_nil + expect(ligne[3]).to eq('Ceci est un intitulé') + expect(ligne[4]).to eq(intitule.audio_url) + expect(ligne[5]).to eq('Ceci est une consigne') + expect(ligne[6]).to eq(consigne.audio_url) + expect(ligne[7]).to eq('Ceci est une description') + expect(ligne[8]).to eq(question.zone_cliquable_url) + expect(ligne[9]).to eq(question.image_au_clic_url) + end +end diff --git a/spec/models/import_export/questions/export/question_clic_dans_texte_spec.rb b/spec/models/import_export/questions/export/question_clic_dans_texte_spec.rb new file mode 100644 index 000000000..8857bda4f --- /dev/null +++ b/spec/models/import_export/questions/export/question_clic_dans_texte_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe ImportExport::Questions::Export::QuestionClicDansTexte do + subject(:response_service) do + response_service = described_class.new( + [question], ImportExport::Questions::ImportExportDonnees::HEADERS_COMMUN + ) + response_service.to_xls + response_service + end + + let(:spreadsheet) { response_service.export.workbook } + let(:worksheet) { spreadsheet.worksheet(0) } + let(:headers_xls) { worksheet.row(0).map { |header| header.parameterize.underscore.to_sym } } + + let(:question) do + create(:question_clic_dans_image, description: 'Ceci est une description', + nom_technique: 'clic') + end + let!(:intitule) do + create(:transcription, :avec_audio, question_id: question.id, categorie: :intitule, + ecrit: 'Ceci est un intitulé') + end + let!(:consigne) do + create(:transcription, :avec_audio, question_id: question.id, + categorie: :modalite_reponse, + ecrit: 'Ceci est une consigne') + end + let(:headers) do + ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[question.type] + end + + it 'génére un fichier xls avec les entêtes sur chaque colonnes' do + expect(spreadsheet.worksheets.count).to eq(1) + + headers_attendus = ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[ + QuestionClicDansTexte::QUESTION_TYPE + ] + expect(headers_xls).to eq headers_attendus + end + + it 'génére un fichier xls avec les détails de la question' do + ligne = worksheet.row(1) + expect(ligne[0]).to eq('Question clic dans image') + expect(ligne[1]).to eq('clic') + expect(ligne[2]).to be_nil + expect(ligne[3]).to eq('Ceci est un intitulé') + expect(ligne[4]).to eq(intitule.audio_url) + expect(ligne[5]).to eq('Ceci est une consigne') + expect(ligne[6]).to eq(consigne.audio_url) + expect(ligne[7]).to eq('Ceci est une description') + expect(ligne[8]).to eq(question.texte_sur_illustration) + end +end diff --git a/spec/models/import_export/questions/export/question_glisser_deposer_spec.rb b/spec/models/import_export/questions/export/question_glisser_deposer_spec.rb new file mode 100644 index 000000000..08713bc05 --- /dev/null +++ b/spec/models/import_export/questions/export/question_glisser_deposer_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe ImportExport::Questions::Export::QuestionGlisserDeposer do + subject(:response_service) do + response_service = described_class.new( + [question], ImportExport::Questions::ImportExportDonnees::HEADERS_COMMUN + ) + response_service.to_xls + response_service + end + + let(:spreadsheet) { response_service.export.workbook } + let(:worksheet) { spreadsheet.worksheet(0) } + let(:headers_xls) { worksheet.row(0).map { |header| header.parameterize.underscore.to_sym } } + + let!(:question) { create(:question_glisser_deposer) } + let(:headers) do + ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[question.type] + end + let!(:reponse) { create(:choix, :bon, question_id: question.id) } + let!(:reponse2) { create(:choix, :mauvais, question_id: question.id) } + + it 'génére un fichier xls avec les entêtes spécifiques' do + expect(spreadsheet.worksheets.count).to eq(1) + + headers_attendus = ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[ + QuestionGlisserDeposer::QUESTION_TYPE + ] + headers_attendus += %i[reponse_1_nom_technique reponse_1_position_client reponse_1_type_choix + reponse_1_illustration_url reponse_2_nom_technique + reponse_2_position_client reponse_2_type_choix + reponse_2_illustration_url] + + expect(headers_xls).to eq headers_attendus + end + + it 'génére un fichier xls avec les détails de la question' do + ligne = worksheet.row(1) + + expect(ligne[8]).to eq(question.zone_depot_url) + expect(ligne[9]).to eq(question.orientation) + expect(ligne[10]).to eq(reponse.nom_technique) + expect(ligne[11]).to eq(reponse.position_client.to_s) + expect(ligne[12]).to eq(reponse.type_choix) + expect(ligne[13]).to eq(reponse.illustration_url.to_s) + expect(ligne[14]).to eq(reponse2.nom_technique) + expect(ligne[15]).to eq(reponse2.position_client.to_s) + expect(ligne[16]).to eq(reponse2.type_choix) + expect(ligne[17]).to eq(reponse2.illustration_url.to_s) + end +end diff --git a/spec/models/import_export/questions/export/question_qcm_spec.rb b/spec/models/import_export/questions/export/question_qcm_spec.rb new file mode 100644 index 000000000..1b52ba069 --- /dev/null +++ b/spec/models/import_export/questions/export/question_qcm_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe ImportExport::Questions::Export::QuestionQcm do + subject(:response_service) do + response_service = described_class.new( + [question], ImportExport::Questions::ImportExportDonnees::HEADERS_COMMUN + ) + response_service.to_xls + response_service + end + + let(:spreadsheet) { response_service.export.workbook } + let(:worksheet) { spreadsheet.worksheet(0) } + let(:headers_xls) { worksheet.row(0).map { |header| header.parameterize.underscore.to_sym } } + + let(:question) { create(:question_qcm) } + let(:headers) do + ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[question.type] + end + let!(:reponse) { create(:choix, :bon, question_id: question.id) } + let!(:reponse2) { create(:choix, :mauvais, question_id: question.id) } + + it 'génére un fichier xls avec les entêtes spécifiques' do + expect(spreadsheet.worksheets.count).to eq(1) + + headers_attendus = ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[ + QuestionQcm::QUESTION_TYPE + ] + headers_attendus += %i[choix_1_intitule choix_1_nom_technique choix_1_type_choix + choix_1_audio_url choix_2_intitule choix_2_nom_technique + choix_2_type_choix choix_2_audio_url] + + expect(headers_xls).to eq headers_attendus + end + + it 'génére un fichier xls avec les détails de la question' do + ligne = worksheet.row(1) + expect(ligne[8]).to eq(question.type_qcm) + expect(ligne[9]).to eq(reponse.intitule) + expect(ligne[10]).to eq(reponse.nom_technique) + expect(ligne[11]).to eq(reponse.type_choix) + expect(ligne[12]).to eq(reponse.audio_url) + expect(ligne[13]).to eq(reponse2.intitule) + expect(ligne[14]).to eq(reponse2.nom_technique) + expect(ligne[15]).to eq(reponse2.type_choix) + expect(ligne[16]).to eq(reponse2.audio_url) + end +end diff --git a/spec/models/import_export/questions/export/question_saisie_spec.rb b/spec/models/import_export/questions/export/question_saisie_spec.rb new file mode 100644 index 000000000..7966bf999 --- /dev/null +++ b/spec/models/import_export/questions/export/question_saisie_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe ImportExport::Questions::Export::QuestionSaisie do + subject(:response_service) do + response_service = described_class.new( + [question], ImportExport::Questions::ImportExportDonnees::HEADERS_COMMUN + ) + response_service.to_xls + response_service + end + + let(:spreadsheet) { response_service.export.workbook } + let(:worksheet) { spreadsheet.worksheet(0) } + let(:headers_xls) { worksheet.row(0).map { |header| header.parameterize.underscore.to_sym } } + + let(:question) { create(:question_saisie) } + let(:headers) do + ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[question.type] + end + let!(:reponse) { create(:choix, :bon, question_id: question.id) } + + it 'génére un fichier xls avec les entêtes spécifiques' do + expect(spreadsheet.worksheets.count).to eq(1) + + headers_attendus = ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[ + QuestionSaisie::QUESTION_TYPE + ] + headers_attendus += %i[reponse_1_intitule reponse_1_nom_technique reponse_1_type_choix] + + expect(headers_xls).to eq headers_attendus + end + + it 'génére un fichier xls avec les détails de la question' do + ligne = worksheet.row(1) + expect(ligne[8]).to eq(question.suffix_reponse) + expect(ligne[9]).to eq(question.reponse_placeholder) + expect(ligne[10]).to eq(question.type_saisie) + expect(ligne[11]).to eq(question.texte_a_trous) + expect(ligne[12]).to eq(question.reponses.last.intitule) + expect(ligne[13]).to eq(question.reponses.last.nom_technique) + end +end diff --git a/spec/models/import_export/questions/export/question_sous_consigne_spec.rb b/spec/models/import_export/questions/export/question_sous_consigne_spec.rb new file mode 100644 index 000000000..18f2152d6 --- /dev/null +++ b/spec/models/import_export/questions/export/question_sous_consigne_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe ImportExport::Questions::Export::QuestionSousConsigne do + subject(:response_service) do + response_service = described_class.new( + [question], ImportExport::Questions::ImportExportDonnees::HEADERS_COMMUN + ) + response_service.to_xls + response_service + end + + let(:spreadsheet) { response_service.export.workbook } + let(:worksheet) { spreadsheet.worksheet(0) } + let(:headers_xls) { worksheet.row(0).map { |header| header.parameterize.underscore.to_sym } } + + let(:question) do + create(:question_clic_dans_image, description: 'Ceci est une description', + nom_technique: 'clic') + end + let!(:intitule) do + create(:transcription, :avec_audio, question_id: question.id, categorie: :intitule, + ecrit: 'Ceci est un intitulé') + end + let!(:consigne) do + create(:transcription, :avec_audio, question_id: question.id, + categorie: :modalite_reponse, + ecrit: 'Ceci est une consigne') + end + let(:headers) do + ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[question.type] + end + + it 'génére un fichier xls avec les entêtes sur chaque colonnes' do + expect(spreadsheet.worksheets.count).to eq(1) + + headers_attendus = ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[ + QuestionSousConsigne::QUESTION_TYPE + ] + expect(headers_xls).to eq headers_attendus + end + + it 'génére un fichier xls avec les détails de la question' do + ligne = worksheet.row(1) + expect(ligne[0]).to eq('Question clic dans image') + expect(ligne[1]).to eq('clic') + expect(ligne[2]).to be_nil + expect(ligne[3]).to eq('Ceci est un intitulé') + expect(ligne[4]).to eq(intitule.audio_url) + expect(ligne[5]).to eq('Ceci est une consigne') + expect(ligne[6]).to eq(consigne.audio_url) + expect(ligne[7]).to eq('Ceci est une description') + expect(ligne[8]).to eq(question.texte_sur_illustration) + end +end diff --git a/spec/models/import_export/questions/export_spec.rb b/spec/models/import_export/questions/export_spec.rb index bc71324f6..7921de28f 100644 --- a/spec/models/import_export/questions/export_spec.rb +++ b/spec/models/import_export/questions/export_spec.rb @@ -4,169 +4,26 @@ describe ImportExport::Questions::Export do subject(:response_service) do - response_service = described_class.new([question], headers) + response_service = exporteur.new( + [question], ImportExport::Questions::ImportExportDonnees::HEADERS_COMMUN + ) response_service.to_xls response_service end + let(:exporteur) { described_class } let(:headers) { [] } let(:question) { create(:question) } let(:spreadsheet) { response_service.export.workbook } let(:worksheet) { spreadsheet.worksheet(0) } - - describe 'pour une question clic' do - let(:question) do - create(:question_clic_dans_image, description: 'Ceci est une description', - nom_technique: 'clic') - end - let!(:intitule) do - create(:transcription, :avec_audio, question_id: question.id, categorie: :intitule, - ecrit: 'Ceci est un intitulé') - end - let!(:consigne) do - create(:transcription, :avec_audio, question_id: question.id, - categorie: :modalite_reponse, - ecrit: 'Ceci est une consigne') - end - let(:headers) do - ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[question.type] - end - - it 'génére un fichier xls avec les entêtes sur chaque colonnes' do - expect(spreadsheet.worksheets.count).to eq(1) - expect(worksheet.row(0)[0]).to eq('Libelle') - expect(worksheet.row(0)[1]).to eq('Nom technique') - expect(worksheet.row(0)[2]).to eq('Illustration') - expect(worksheet.row(0)[3]).to eq('Intitule ecrit') - expect(worksheet.row(0)[4]).to eq('Intitule audio') - expect(worksheet.row(0)[5]).to eq('Consigne ecrit') - expect(worksheet.row(0)[6]).to eq('Consigne audio') - expect(worksheet.row(0)[7]).to eq('Description') - expect(worksheet.row(0)[8]).to eq('Zone cliquable') - expect(worksheet.row(0)[9]).to eq('Image au clic') - end - - it 'génére un fichier xls avec les détails de la question' do - ligne = worksheet.row(1) - expect(ligne[0]).to eq('Question clic dans image') - expect(ligne[1]).to eq('clic') - expect(ligne[2]).to be_nil - expect(ligne[3]).to eq('Ceci est un intitulé') - expect(ligne[4]).to eq(intitule.audio_url) - expect(ligne[5]).to eq('Ceci est une consigne') - expect(ligne[6]).to eq(consigne.audio_url) - expect(ligne[7]).to eq('Ceci est une description') - expect(ligne[8]).to eq(question.zone_cliquable_url) - expect(ligne[9]).to eq(question.image_au_clic_url) - end - end - - describe 'pour une question glisser deposer' do - let!(:question) { create(:question_glisser_deposer) } - let(:headers) do - ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[question.type] - end - let!(:reponse) { create(:choix, :bon, question_id: question.id) } - let!(:reponse2) { create(:choix, :mauvais, question_id: question.id) } - - it 'génére un fichier xls avec les entêtes spécifiques' do - expect(spreadsheet.worksheets.count).to eq(1) - expect(worksheet.row(0)[8]).to eq('Zone depot') - expect(worksheet.row(0)[9]).to eq('reponse_1_nom_technique') - expect(worksheet.row(0)[10]).to eq('reponse_1_position_client') - expect(worksheet.row(0)[11]).to eq('reponse_1_type_choix') - expect(worksheet.row(0)[12]).to eq('reponse_1_illustration_url') - expect(worksheet.row(0)[13]).to eq('reponse_2_nom_technique') - expect(worksheet.row(0)[14]).to eq('reponse_2_position_client') - expect(worksheet.row(0)[15]).to eq('reponse_2_type_choix') - expect(worksheet.row(0)[16]).to eq('reponse_2_illustration_url') - end - - it 'génére un fichier xls avec les détails de la question' do - ligne = worksheet.row(1) - - expect(ligne[8]).to eq(question.zone_depot_url) - expect(ligne[9]).to eq(reponse.nom_technique) - expect(ligne[10]).to eq(reponse.position_client.to_s) - expect(ligne[11]).to eq(reponse.type_choix) - expect(ligne[12]).to eq(reponse.illustration_url.to_s) - expect(ligne[13]).to eq(reponse2.nom_technique) - expect(ligne[14]).to eq(reponse2.position_client.to_s) - expect(ligne[15]).to eq(reponse2.type_choix) - expect(ligne[16]).to eq(reponse2.illustration_url.to_s) - end - end - - describe 'pour une question saisie' do - let(:question) { create(:question_saisie) } - let(:headers) do - ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[question.type] - end - let!(:reponse) { create(:choix, :bon, question_id: question.id) } - - it 'génére un fichier xls avec les entêtes spécifiques' do - expect(spreadsheet.worksheets.count).to eq(1) - expect(worksheet.row(0)[8]).to eq('Suffix reponse') - expect(worksheet.row(0)[9]).to eq('Reponse placeholder') - expect(worksheet.row(0)[10]).to eq('Type saisie') - expect(worksheet.row(0)[11]).to eq('reponse_1_intitule') - expect(worksheet.row(0)[12]).to eq('reponse_1_nom_technique') - expect(worksheet.row(0)[13]).to eq('reponse_1_type_choix') - end - - it 'génére un fichier xls avec les détails de la question' do - ligne = worksheet.row(1) - expect(ligne[8]).to eq(question.suffix_reponse) - expect(ligne[9]).to eq(question.reponse_placeholder) - expect(ligne[10]).to eq(question.type_saisie) - expect(ligne[11]).to eq(question.reponses.last.intitule) - expect(ligne[12]).to eq(question.reponses.last.nom_technique) - end - end - - describe 'pour une question qcm' do - let(:question) { create(:question_qcm) } - let(:headers) do - ImportExport::Questions::ImportExportDonnees::HEADERS_ATTENDUS[question.type] - end - let!(:reponse) { create(:choix, :bon, question_id: question.id) } - let!(:reponse2) { create(:choix, :mauvais, question_id: question.id) } - - it 'génére un fichier xls avec les entêtes spécifiques' do - expect(spreadsheet.worksheets.count).to eq(1) - expect(worksheet.row(0)[8]).to eq('Type qcm') - expect(worksheet.row(0)[9]).to eq('choix_1_intitule') - expect(worksheet.row(0)[10]).to eq('choix_1_nom_technique') - expect(worksheet.row(0)[11]).to eq('choix_1_type_choix') - expect(worksheet.row(0)[12]).to eq('choix_1_audio_url') - expect(worksheet.row(0)[13]).to eq('choix_2_intitule') - expect(worksheet.row(0)[14]).to eq('choix_2_nom_technique') - expect(worksheet.row(0)[15]).to eq('choix_2_type_choix') - expect(worksheet.row(0)[16]).to eq('choix_2_audio_url') - end - - it 'génére un fichier xls avec les détails de la question' do - ligne = worksheet.row(1) - expect(ligne[8]).to eq(question.type_qcm) - expect(ligne[9]).to eq(reponse.intitule) - expect(ligne[10]).to eq(reponse.nom_technique) - expect(ligne[11]).to eq(reponse.type_choix) - expect(ligne[12]).to eq(reponse.audio_url) - expect(ligne[13]).to eq(reponse2.intitule) - expect(ligne[14]).to eq(reponse2.nom_technique) - expect(ligne[15]).to eq(reponse2.type_choix) - expect(ligne[16]).to eq(reponse2.audio_url) - end - end + let(:headers_xls) { worksheet.row(0).map { |header| header.parameterize.underscore.to_sym } } describe '#nom_du_fichier' do - let(:question) { create(:question_qcm) } - it 'genere le nom du fichier' do - date = DateTime.current.strftime('%Y%m%d') - nom_du_fichier_attendu = "#{date}-#{question.type}.xls" - - expect(response_service.nom_du_fichier(question.type)).to eq(nom_du_fichier_attendu) + Timecop.freeze(Date.new(2025, 2, 28)) do + nom_du_fichier_attendu = '20250228-QuestionQcm.xls' + expect(response_service.nom_du_fichier('QuestionQcm')).to eq(nom_du_fichier_attendu) + end end end diff --git a/spec/support/import_question_glisser.xls b/spec/support/import_question_glisser.xls index b1baf446a..6443e80a4 100644 Binary files a/spec/support/import_question_glisser.xls and b/spec/support/import_question_glisser.xls differ diff --git a/spec/support/import_question_glisser_deposer.xls b/spec/support/import_question_glisser_deposer.xls new file mode 100644 index 000000000..4143de3df Binary files /dev/null and b/spec/support/import_question_glisser_deposer.xls differ