From 4bdf23c646aa80c1859d3f3956f4032491caeb20 Mon Sep 17 00:00:00 2001 From: vmg192 Date: Mon, 15 Dec 2025 17:04:50 -0300 Subject: [PATCH 1/2] =?UTF-8?q?Cria=C3=A7=C3=A3o=20de=20testes=20rspec=20p?= =?UTF-8?q?ara=20sigaa=5Fimports=5Fcontroller=20e=20respostas=5Fcontroller?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/controllers/respostas_controller_spec.rb | 231 ++++++++++++++++++ .../sigaa_imports_controller_spec.rb | 222 +++++++++++++++++ 2 files changed, 453 insertions(+) create mode 100644 spec/controllers/respostas_controller_spec.rb create mode 100644 spec/controllers/sigaa_imports_controller_spec.rb diff --git a/spec/controllers/respostas_controller_spec.rb b/spec/controllers/respostas_controller_spec.rb new file mode 100644 index 0000000000..0c2369675f --- /dev/null +++ b/spec/controllers/respostas_controller_spec.rb @@ -0,0 +1,231 @@ +require 'rails_helper' + +RSpec.describe RespostasController, type: :controller do + let(:user) do + User.create!( + email_address: 'aluno@test.com', + login: 'aluno_test', + password: 'password123', + password_confirmation: 'password123', + nome: 'Aluno Test', + matricula: '123456789', + eh_admin: false + ) + end + + let(:modelo) do + m = Modelo.new(titulo: 'Template Test', ativo: true) + m.perguntas.build(enunciado: 'Pergunta 1', tipo: 'escala') + m.perguntas.build(enunciado: 'Pergunta 2', tipo: 'texto_curto') + m.save! + m + end + + let(:turma) do + Turma.create!( + codigo: 'TEST001', + nome: 'Turma Teste', + semestre: '2024/1' + ) + end + + let(:avaliacao) do + Avaliacao.create!( + turma: turma, + modelo: modelo, + data_inicio: 1.day.ago, + data_fim: 7.days.from_now + ) + end + + let(:avaliacao_expirada) do + Avaliacao.create!( + turma: turma, + modelo: modelo, + data_inicio: 30.days.ago, + data_fim: 1.day.ago + ) + end + + let(:avaliacao_futura) do + Avaliacao.create!( + turma: turma, + modelo: modelo, + data_inicio: 1.day.from_now, + data_fim: 7.days.from_now + ) + end + + def login_as(user) + session = Session.create!(user: user) + cookies.signed[:session_id] = session.id + end + + describe "GET #index" do + context "when logged in" do + before { login_as(user) } + + it "redirects to root path" do + get :index + expect(response).to redirect_to(root_path) + end + end + + context "when not logged in" do + it "redirects to login" do + get :index + expect(response).to redirect_to(new_session_path) + end + end + end + + describe "GET #new" do + context "when logged in" do + before { login_as(user) } + + context "with valid avaliacao" do + it "returns a successful response" do + get :new, params: { avaliacao_id: avaliacao.id } + expect(response).to be_successful + end + end + + context "with expired avaliacao" do + it "redirects to root with alert" do + get :new, params: { avaliacao_id: avaliacao_expirada.id } + expect(response).to redirect_to(root_path) + expect(flash[:alert]).to include("encerrada") + end + end + + context "with future avaliacao" do + it "redirects to root with alert" do + get :new, params: { avaliacao_id: avaliacao_futura.id } + expect(response).to redirect_to(root_path) + expect(flash[:alert]).to include("não está disponível") + end + end + + context "when user already responded" do + before do + Submissao.create!( + avaliacao: avaliacao, + aluno: user, + data_envio: Time.current + ) + end + + it "redirects to root with alert" do + get :new, params: { avaliacao_id: avaliacao.id } + expect(response).to redirect_to(root_path) + expect(flash[:alert]).to include("já respondeu") + end + end + end + + context "when not logged in" do + it "redirects to login" do + get :new, params: { avaliacao_id: avaliacao.id } + expect(response).to redirect_to(new_session_path) + end + end + end + + describe "POST #create" do + context "when logged in" do + before { login_as(user) } + + context "with valid params" do + let(:valid_params) do + { + avaliacao_id: avaliacao.id, + submissao: { + respostas_attributes: modelo.perguntas.each_with_index.map do |pergunta, i| + { pergunta_id: pergunta.id, conteudo: (i + 1).to_s } + end + } + } + end + + it "creates a new submissao" do + expect { + post :create, params: valid_params + }.to change(Submissao, :count).by(1) + end + + it "creates respostas for each pergunta" do + expect { + post :create, params: valid_params + }.to change(Resposta, :count).by(modelo.perguntas.count) + end + + it "assigns the current user as aluno" do + post :create, params: valid_params + expect(Submissao.last.aluno).to eq(user) + end + + it "sets the data_envio" do + post :create, params: valid_params + expect(Submissao.last.data_envio).not_to be_nil + end + + it "redirects to root with success notice" do + post :create, params: valid_params + expect(response).to redirect_to(root_path) + expect(flash[:notice]).to include("sucesso") + end + + it "saves snapshot of pergunta enunciado" do + post :create, params: valid_params + resposta = Resposta.last + expect(resposta.snapshot_enunciado).not_to be_nil + end + end + + context "with missing submissao params" do + it "handles missing params gracefully" do + expect { + post :create, params: { avaliacao_id: avaliacao.id } + }.to raise_error(ActionController::ParameterMissing) + end + end + + context "with expired avaliacao" do + it "redirects to root with alert" do + post :create, params: { + avaliacao_id: avaliacao_expirada.id, + submissao: { respostas_attributes: [] } + } + expect(response).to redirect_to(root_path) + expect(flash[:alert]).to include("encerrada") + end + end + + context "when user already responded" do + before do + Submissao.create!( + avaliacao: avaliacao, + aluno: user, + data_envio: Time.current + ) + end + + it "redirects to root with alert" do + post :create, params: { + avaliacao_id: avaliacao.id, + submissao: { respostas_attributes: [] } + } + expect(response).to redirect_to(root_path) + expect(flash[:alert]).to include("já respondeu") + end + end + end + + context "when not logged in" do + it "redirects to login" do + post :create, params: { avaliacao_id: avaliacao.id, submissao: {} } + expect(response).to redirect_to(new_session_path) + end + end + end +end diff --git a/spec/controllers/sigaa_imports_controller_spec.rb b/spec/controllers/sigaa_imports_controller_spec.rb new file mode 100644 index 0000000000..cbc356be6f --- /dev/null +++ b/spec/controllers/sigaa_imports_controller_spec.rb @@ -0,0 +1,222 @@ +require 'rails_helper' + +RSpec.describe SigaaImportsController, type: :controller do + let(:admin_user) do + User.create!( + email_address: 'admin@test.com', + login: 'admin_test', + password: 'password123', + password_confirmation: 'password123', + nome: 'Admin User', + matricula: '000000001', + eh_admin: true + ) + end + + let(:regular_user) do + User.create!( + email_address: 'user@test.com', + login: 'regular_test', + password: 'password123', + password_confirmation: 'password123', + nome: 'Regular User', + matricula: '000000002', + eh_admin: false + ) + end + + def login_as(user) + session = Session.create!(user: user) + cookies.signed[:session_id] = session.id + end + + describe "GET #new" do + context "when logged in as admin" do + before { login_as(admin_user) } + + it "returns a successful response" do + get :new + expect(response).to be_successful + end + + it "renders successfully" do + get :new + expect(response).to be_successful + end + end + + context "when logged in as regular user" do + before { login_as(regular_user) } + + it "redirects to root path" do + get :new + expect(response).to redirect_to(root_path) + end + + it "sets access denied alert" do + get :new + expect(flash[:alert]).to include("Acesso negado") + end + end + + context "when not logged in" do + it "redirects to login" do + get :new + expect(response).to redirect_to(new_session_path) + end + end + end + + describe "POST #create" do + context "when logged in as admin" do + before { login_as(admin_user) } + + context "when import succeeds" do + before do + allow(File).to receive(:exist?).and_call_original + allow(File).to receive(:exist?).with(Rails.root.join("class_members.json")).and_return(true) + allow(File).to receive(:exist?).with(Rails.root.join("classes.json")).and_return(true) + + mock_service = instance_double(SigaaImportService) + allow(SigaaImportService).to receive(:new).and_return(mock_service) + allow(mock_service).to receive(:process).and_return({ + turmas_created: 1, + turmas_updated: 0, + users_created: 5, + matriculas_created: 5, + errors: [] + }) + end + + it "processes the import and redirects to success" do + post :create + expect(response).to have_http_status(:redirect) + end + + it "stores results in cache" do + expect(Rails.cache).to receive(:write).with(anything, anything, expires_in: 10.minutes) + post :create + end + end + + context "when class_members.json does not exist" do + it "redirects to new with alert" do + allow(File).to receive(:exist?).with(Rails.root.join("class_members.json")).and_return(false) + + post :create + expect(response).to redirect_to(new_sigaa_import_path) + expect(flash[:alert]).to include("não encontrado") + end + end + + context "when import has errors" do + it "redirects to new with error message" do + allow(File).to receive(:exist?).and_return(true) + + mock_service = instance_double(SigaaImportService) + allow(SigaaImportService).to receive(:new).and_return(mock_service) + allow(mock_service).to receive(:process).and_return({ + turmas_created: 0, + users_created: 0, + errors: ["Erro de teste"] + }) + + post :create + expect(response).to redirect_to(new_sigaa_import_path) + expect(flash[:alert]).to include("Erro de teste") + end + end + end + + context "when logged in as regular user" do + before { login_as(regular_user) } + + it "redirects to root path" do + post :create + expect(response).to redirect_to(root_path) + end + end + end + + describe "PATCH #update" do + context "when logged in as admin" do + before { login_as(admin_user) } + + context "when update succeeds" do + before do + allow(File).to receive(:exist?).and_call_original + allow(File).to receive(:exist?).with(Rails.root.join("class_members.json")).and_return(true) + allow(File).to receive(:exist?).with(Rails.root.join("classes.json")).and_return(true) + + mock_service = instance_double(SigaaImportService) + allow(SigaaImportService).to receive(:new).and_return(mock_service) + allow(mock_service).to receive(:process).and_return({ + turmas_created: 0, + turmas_updated: 1, + users_created: 0, + matriculas_created: 0, + errors: [] + }) + end + + it "processes the update and redirects to success" do + patch :update, params: { id: 1 } + expect(response).to have_http_status(:redirect) + end + end + + context "when file does not exist" do + it "redirects with alert" do + allow(File).to receive(:exist?).with(Rails.root.join("class_members.json")).and_return(false) + + patch :update, params: { id: 1 } + expect(response).to redirect_to(new_sigaa_import_path) + end + end + end + + context "when logged in as regular user" do + before { login_as(regular_user) } + + it "redirects to root path" do + patch :update, params: { id: 1 } + expect(response).to redirect_to(root_path) + end + end + end + + describe "GET #success" do + context "when logged in as admin" do + before { login_as(admin_user) } + + context "with missing or expired cache key" do + it "redirects to root when no key provided" do + get :success + expect(response).to redirect_to(root_path) + end + + it "redirects to root when key is invalid" do + get :success, params: { key: "nonexistent_key" } + expect(response).to redirect_to(root_path) + expect(flash[:alert]).to include("expirado") + end + end + + context "without cache key" do + it "redirects to root with alert" do + get :success + expect(response).to redirect_to(root_path) + end + end + end + + context "when logged in as regular user" do + before { login_as(regular_user) } + + it "redirects to root path" do + get :success, params: { key: "test" } + expect(response).to redirect_to(root_path) + end + end + end +end From 65dd1be7982c9d394d3097fadb1bb81c85997364 Mon Sep 17 00:00:00 2001 From: Marcos Date: Mon, 15 Dec 2025 23:02:35 -0300 Subject: [PATCH 2/2] Resolve problema linter --- spec/controllers/sigaa_imports_controller_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/controllers/sigaa_imports_controller_spec.rb b/spec/controllers/sigaa_imports_controller_spec.rb index cbc356be6f..b7160cd99e 100644 --- a/spec/controllers/sigaa_imports_controller_spec.rb +++ b/spec/controllers/sigaa_imports_controller_spec.rb @@ -76,7 +76,7 @@ def login_as(user) allow(File).to receive(:exist?).and_call_original allow(File).to receive(:exist?).with(Rails.root.join("class_members.json")).and_return(true) allow(File).to receive(:exist?).with(Rails.root.join("classes.json")).and_return(true) - + mock_service = instance_double(SigaaImportService) allow(SigaaImportService).to receive(:new).and_return(mock_service) allow(mock_service).to receive(:process).and_return({ @@ -112,13 +112,13 @@ def login_as(user) context "when import has errors" do it "redirects to new with error message" do allow(File).to receive(:exist?).and_return(true) - + mock_service = instance_double(SigaaImportService) allow(SigaaImportService).to receive(:new).and_return(mock_service) allow(mock_service).to receive(:process).and_return({ turmas_created: 0, users_created: 0, - errors: ["Erro de teste"] + errors: [ "Erro de teste" ] }) post :create @@ -147,7 +147,7 @@ def login_as(user) allow(File).to receive(:exist?).and_call_original allow(File).to receive(:exist?).with(Rails.root.join("class_members.json")).and_return(true) allow(File).to receive(:exist?).with(Rails.root.join("classes.json")).and_return(true) - + mock_service = instance_double(SigaaImportService) allow(SigaaImportService).to receive(:new).and_return(mock_service) allow(mock_service).to receive(:process).and_return({