diff --git a/spec/controllers/faq_controller_spec.rb b/spec/controllers/faq_controller_spec.rb new file mode 100644 index 000000000..4d1daf1b9 --- /dev/null +++ b/spec/controllers/faq_controller_spec.rb @@ -0,0 +1,65 @@ +RSpec.describe FAQController, type: :controller do + describe "GET #index" do + render_views + + it "displays titles and render links for all entries" do + get :index + + # Usager + expect(response.body).to include("Gestion de mon compte") + expect(response.body).to include("Je veux changer mon adresse email") + expect(response.body).to include(faq_path(category: "usager", slug: "je-veux-changer-mon-adresse-email")) + + # Instructeur + expect(response.body).to include("Je dois confirmer mon compte à chaque connexion") + + # Instructeur + expect(response.body).to include("Les blocs répétables") + end + + context "with invalid subcategory" do + before do + service = instance_double(FAQsLoaderService, all: faqs) + allow(FAQsLoaderService).to receive(:new).and_return(service) + end + + let(:faqs) do + { + 'usager' => { + 'oops' => [{ category: 'usager', subcategory: 'oops', title: 'FAQ Title 1', slug: 'faq1' }] + } + } + end + + it "fails so we can't make a typo and publish non translated subcategories" do + expect { get :index }.to raise_error(ActionView::Template::Error) + end + end + end + + describe "GET #show" do + before do + allow(Current).to receive(:application_name).and_return('demarches.gouv.fr') + end + + render_views + + context "when the FAQ exists" do + it "renders the show template with the FAQ content and metadata" do + get :show, params: { category: 'usager', slug: 'je-veux-changer-mon-adresse-email' } + expect(response.body).to include('Si vous disposez d’un compte usager sur demarches.gouv.fr') + + # link to siblings + expect(response.body).to include(faq_path(category: 'usager', slug: 'je-veux-changer-mon-mot-de-passe')) + end + end + + context "when the FAQ does not exist" do + it "raises a routing error for a missing FAQ" do + expect { + get :show, params: { category: 'nonexistent', slug: 'nofaq' } + }.to raise_error(ActionController::RoutingError) + end + end + end +end diff --git a/spec/services/faqs_loader_service_spec.rb b/spec/services/faqs_loader_service_spec.rb new file mode 100644 index 000000000..ce9ad6c95 --- /dev/null +++ b/spec/services/faqs_loader_service_spec.rb @@ -0,0 +1,86 @@ +require 'rails_helper' + +RSpec.describe FAQsLoaderService do + let(:substitutions) { { application_name: "demarches.gouv.fr", application_base_url: APPLICATION_BASE_URL, contact_email: CONTACT_EMAIL } } + let(:service) { FAQsLoaderService.new(substitutions) } + + context "behavior with stubbed markdown files" do + before do + allow(Dir).to receive(:glob).and_return(['path/to/faq1.md', 'path/to/faq2.md']) + + # Mock File.read calls to fake md files + # but call original otherwise (rspec or debuggning uses File.read to load some files) + allow(File).to receive(:read).and_wrap_original do |original_method, *args| + case args.first + when 'path/to/faq1.md' + <<~MD + --- + title: FAQ1 + slug: faq1 + category: usager + subcategory: account + --- + Welcome to %{application_name} + MD + when 'path/to/faq2.md' + <<~MD + --- + title: FAQ2 + slug: faq2 + category: admin + subcategory: general + --- + This is for %{application_base_url} + MD + else + original_method.call(*args) + end + end + end + + describe '#find' do + it 'returns a file with variable substitutions' do + expect(service.find('usager/faq1').content).to include('Welcome to demarches.gouv.fr') + end + end + + describe '#all' do + it 'returns all FAQs' do + expect(service.all).to eq({ + "usager" => { "account" => [{ category: "usager", file_path: "path/to/faq1.md", slug: "faq1", subcategory: "account", title: "FAQ1" }] }, + "admin" => { "general" => [{ category: "admin", file_path: "path/to/faq2.md", slug: "faq2", subcategory: "general", title: "FAQ2" }] } + }) + end + end + + describe '#faqs_for_category' do + it 'returns FAQs grouped by subcategory for a given category' do + result = service.faqs_for_category('usager') + expect(result).to eq({ + 'account' => [{ category: 'usager', subcategory: 'account', title: 'FAQ1', slug: 'faq1', file_path: 'path/to/faq1.md' }] + }) + end + end + + describe 'caching' do + it 'works', caching: true do + 2.times { + service = FAQsLoaderService.new(substitutions) + service.all + expect(Dir).to have_received(:glob).once + } + + # depends on substitutions + service = FAQsLoaderService.new(substitutions.merge(application_name: "other name")) + service.all + expect(Dir).to have_received(:glob).twice + end + end + end + + context "with actual files" do + it 'load, perform substitutions and returns all FAQs' do + expect(service.all.keys).to match_array(["administrateur", "instructeur", "usager"]) + end + end +end