Skip to content

Corrige testes relacionados com editorialboard journal issue - #1486

Merged
robertatakenaka merged 12 commits into
scieloorg:mainfrom
robertatakenaka:fix_testes_editorialboard_journal_issue_
Oct 6, 2026
Merged

robertatakenaka merged 12 commits into
scieloorg:mainfrom
robertatakenaka:fix_testes_editorialboard_journal_issue_

Conversation

@robertatakenaka

Copy link
Copy Markdown
Member

O que esse PR faz?

Este Pull Request engloba duas melhorias e ajustes principais na aplicação:

  1. Flexibilização na importação de CSVs (core_settings): Adiciona suporte ao cabeçalho organization_name nas tarefas de importação de pesquisadores (importar_csv_task_newresearcher) e membros do conselho editorial (importar_csv_task_editorialboardmember). A chave mantém um fallback seguro para affiliation, garantindo compatibilidade com arquivos antigos.
  2. Ajuste de teste de integração/unidade (issue): Atualiza as asserções do teste test_format_code_sections.py para validar que o parâmetro journal_toc é passado junto com journal_toc__language nas chamadas do método select_related.

Onde a revisão poderia começar?

Recomenda-se iniciar a revisão pelo arquivo principal das tarefas:

  1. core_settings/tasks.py — Verifique a lógica do .get("organization_name") or row.get("affiliation").
  2. core_settings/tests.py — Observe os cabeçalhos atualizados dos arquivos CSV de teste.
  3. issue/test_format_code_sections.py — Avalie o ajuste na asserção do select_related.

Como este poderia ser testado manualmente?

  1. Testes automatizados:
    Execute a suíte de testes com o pytest ou manage.py test:
python manage.py test core_settings issue
  1. Importação via CSV:
  • Faça upload de um CSV de New Researcher contendo a coluna organization_name em vez de affiliation e verifique se o cadastro do usuário/organização ocorre com sucesso.
  • Repita o teste enviando um CSV no formato antigo (usando affiliation) para validar a compatibilidade retroativa.

Algum cenário de contexto que queira dar?

Alguns fornecedores e fluxos externos passaram a gerar os relatórios utilizando a nomenclatura organization_name em vez de affiliation. Para evitar falhas silenciosas na importação de dados e garantir maior resiliência no processamento assíncrono do Celery/Django, adicionou-se a validação flexível. O ajuste no teste do módulo issue adequa o mocking às consultas otimizadas do ORM.

Screenshots

N/A (Alterações restritas a rotinas de backend, testes e processamento de tarefas em segundo plano).

Quais são os tickets relevantes?

Referências

  • Documentação de buscas do Django ORM (select_related)
  • Convenções de imports de CSV da plataforma

Segurança da informação (NSI.04)

Seção obrigatória. Marque as opções aplicáveis e justificadas. Referência: NSI.04 - Norma de Desenvolvimento Seguro.

Este PR manipula dados sensíveis ou pessoais (LGPD)?

  • Sim — descreva os controles de proteção aplicados (criptografia, mascaramento, anonimização, etc.):
  • Não

Este PR altera autenticação, autorização, controle de acesso ou gerenciamento de sessão?

  • Sim — descreva o que mudou e por quê:
  • Não

Este PR introduz, atualiza ou remove dependências de terceiros?

  • Sim — as novas dependências foram verificadas no SBOM/Trivy sem vulnerabilidades críticas/altas em aberto?

  • Verificado e aprovado

  • Pendente / vulnerabilidade aceita com justificativa:

  • Não

Este PR foi validado pelo pipeline de segurança (SonarQube / Trivy)?

  • Sim — link do job: (Adicione o link da pipeline de CI/CD)
  • Não aplicável a este PR (justifique):

Este PR concatena, monta ou executa comandos SQL, HTML ou JavaScript a partir de entrada externa?

  • Sim — confirme que há sanitização/parametrização (prepared statements, escaping, etc.):
  • Não

Este PR expõe novos endpoints, telas ou serviços?

  • Sim — HTTPS obrigatório está garantido e o acesso segue o princípio de menor privilégio?
  • Não

Algum segredo, senha, chave ou token está sendo adicionado ao código-fonte?

  • Não, nenhum segredo foi commitado
  • Sim (bloquear merge e corrigir antes de prosseguir)

…esquisador

A importação via CSV passa a registrar os membros com NewResearcher em vez do modelo legado Researcher. A afiliação, o ORCID, o Lattes e o e-mail passam a ser gravados nas estruturas próprias do novo modelo, e o ano informado é armazenado como data.

Detalhes de implementação:
- substitui Researcher.create_or_update por NewResearcher.get_or_create
- cria a afiliação com Organization.create_or_update quando a coluna "Instituição" está preenchida, usando a localização da linha
- cria o ORCID com ResearcherOrcid.get_or_create quando a coluna "ORCID iD" está preenchida
- associa o Lattes e o e-mail com researcher.add_lattes_id e researcher.add_email
- converte a coluna "Data" em date(ano, 1, 1) para editorial_board_initial_year e editorial_board_final_year
- deixa de repassar declared_name, aff_div1 e aff_div2, que não fazem parte de NewResearcher
…or e o fluxo real do formulário

Os testes passam a usar NewResearcher e ResearcherOrcid e a validar o formulário da mesma forma que o admin do Wagtail o recebe, com dados submetidos. As verificações condicionais foram substituídas por asserções explícitas, para que falhas de gravação não passem despercebidas.

Detalhes de implementação:
- adiciona get_editorialboard_form, que gera a classe de formulário a partir dos panels (get_edit_handler) e inclui o management form do InlinePanel role_editorial_board
- adiciona autocomplete_value para montar o valor esperado pelo widget de AutocompletePanel (researcher e manual_institution_country)
- substitui a criação de ResearcherIds para ORCID, Lattes e e-mail por ResearcherOrcid, add_lattes_id e add_email no setUp
- chama form.is_valid() antes de save_all e verifica non_field_errors no lugar de chamar clean() diretamente
- usa translation.override("en") para verificar a mensagem original, pois LANGUAGE_CODE é pt-br
- troca os blocos if por assertIsNotNone e assertEqual para afiliação, ORCID, Lattes e e-mail
- corrige o Lattes esperado para o valor completo de 16 dígitos
- no teste de importação, guarda o membro, o pesquisador e o cargo em variáveis locais, inclui verificações de afiliação e ORCID e compara initial_year e final_year com date(2020, 1, 1)
- altera o ORCID do CSV de teste e o acrônimo da organização
- remove o caso de ORCID com dígito verificador inválido do teste de clean_orcid, que valida somente o formato (o dígito verificador é validado por ResearcherOrcid.validate_orcid)
…a coleta do ArticleMeta

Os eventos inesperados gerados no registro de periódicos vindos do ArticleMeta passam a informar o identificador pelo campo atual do modelo, evitando falha ao montar o detalhe do erro.

Detalhes de implementação:
- substitui journal_am.scielo_issn por journal_am.pid no campo "issn" do detail dos dois UnexpectedEvent de _register_journal_data
- remove os comentários provisórios sobre a troca de campo
…de uso

A carga de licenças de uso a partir dos dados do ArticleMeta passa a obter o identificador do periódico pelo campo atual do modelo AMJournal.

Detalhes de implementação:
- em load_license_of_use_in_journal, substitui journal.scielo_issn por journal.pid
…e de migração confiável

O teste da migração de URLs do periódico foi reescrito para funcionar com o Django 5.2 e não deixar o banco de testes em estado inconsistente para as execuções seguintes. Os demais testes passam a usar os nomes de campos atuais dos modelos.

Detalhes de implementação:
- MigrationTestCase passa a herdar de TransactionTestCase e recebe @tag(MIGRATION_TEST_MARKER), pois o Migrator recria o banco no estado de migrate_from
- usa Migrator diretamente porque MigratorTestCase (django-test-migrations 1.3.0) é incompatível com Django 5.2
- define migrate_from e migrate_to como atributos da classe
- une os testes de ida e de reversão em test_migration_adding_and_deleting_journal_urls
- na reversão, verifica que o modelo JournalURL deixa de existir no estado histórico e que a tabela é removida do banco
- registra cleanups para executar migrator.reset() e depois remover o periódico criado
- sobrescreve _fixture_teardown para não fazer flush, preservando os dados das data migrations (ex.: coleção raiz do Wagtail) com --keepdb / --reuse-db
- substitui scielo_issn por pid na criação de AMJournal
- substitui name por main_name na criação de Collection
- em RawOrganizationMixinTestCase, deixa de passar raw_text e verifica que ele recebe o valor de original_data
… core_settings

As verificações do membro importado passam a indicar explicitamente quando o membro ou o cargo não foram criados, em vez de falhar com AttributeError.

Detalhes de implementação:
- guarda o membro e o primeiro cargo em variáveis locais, evitando repetir as consultas
- adiciona assertIsNotNone para o membro e para o cargo antes das demais asserções
… 5.2 e independente do banco

O teste da migração journal.0025_journalurl deixa de aplicar e reverter migrações reais, o que dependia do django-test-migrations (incompatível com Django 5.2), exigia contornos no teardown para não apagar dados das data migrations e tornava a execução lenta e frágil com --keepdb/--reuse-db. Passa a validar diretamente as funções de RunPython da migração, com os modelos mockados, cobrindo tanto a transferência de Journal.journal_url para JournalURL quanto a reversão.

Detalhes de implementação:
- MigrationTestCase passa de TransactionTestCase para SimpleTestCase, garantindo que nenhuma consulta ao banco seja feita
- remove o uso de Migrator, MIGRATION_TEST_MARKER, connection, _fixture_teardown e a limpeza manual do Journal criado
- importa a migração via importlib e mocka apps.get_model para devolver MagicMocks de Journal e JournalURL
- verifica que a última operação da migração é o RunPython com transfer_journal_url_to_journal_urls_inline_panel e reverse_transfer_journal_url_to_journal_urls_inline_panel
- verifica o filtro journal_url__isnull=False, a criação de JournalURL com journal e url e o bulk_create
- verifica que a reversão chama JournalURL.objects.all().delete()
…ports

Allows importing CSV files using 'organization_name' header while maintaining backward compatibility with 'affiliation'.
Include 'journal_toc' alongside 'journal_toc__language' in the select_related assertion.
@pitangainnovare

Copy link
Copy Markdown
Contributor

@robertatakenaka, o PR #1486 está com conflito com a main: ele mantém a migração collection/migrations/0008_collection_network_classification_and_more.py e altera apenas a data do comentário, enquanto o #1487 excluiu esse arquivo.

É preciso atualizar a branch com a main e resolver esse conflito.

@robertatakenaka

Copy link
Copy Markdown
Member Author

@pitangainnovare por favor, revisar novamente

Comment thread editorialboard/views.py
)
orcid = None
if row.get("ORCID iD"):
orcid = ResearcherOrcid.get_or_create(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notei que o save do ResearcherOrcid salva apenas o código, removendo http e outros elementos. A busca, no entanto, apenas valida o conteúdo frente a um regex que permite ou não ter http. Tudo bem, o sistema funciona assim, mas seria interessante padronizar (buscar também só pelo código orcid usando o mesmo normalizador de dados usado no save).

Isso não bloqueia o PR.

Comment thread editorialboard/views.py
aff_name=row.get("Instituição"),
)
researcher.add_lattes_id(row.get("CV Lattes"), user)
researcher.add_email(row.get("Email"), user)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Como agora estamos usando o NewResearcher.get_or_create(...) e antes era Researcher.create_or_update(...), algumas coisas deixaram de ser usadas. Por exemplo, no email lá no antigo havia um tratamento que substituía , por ; e depois fazia .split(";"). Assim mais de um email informado era corretamente registrado no modelo.

Agora na nova versão, tem-se apenas o add_email, sem qualquer tratamento.

Isso não bloqueia o PR, mas pode ser importante colocar algum tratamento em algum lugar caso haja mais de um email na linha separado por , ou ;.

Comment thread editorialboard/views.py
given_names=given_names,
last_name=last_name,
suffix=row.get("Suffix"),
declared_name=row.get("declared_person_name"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

O valor da coluna declared_person_name deixou de ser enviado ao modelo, então o campo declared_name fica vazio nos novos registros.

Não é grave a ponto de bloquear o PR.

Comment thread core_settings/tasks.py
city=row.get("city_name"),
state=row.get("state_name"),
organization_name=row.get("affiliation"),
organization_name=row.get("organization_name") or row.get("affiliation"),

@pitangainnovare pitangainnovare Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Não faz parte de alteração do PR, mas em core_settings/views.py:12, na função validate_columns_csv():

required = MODEL_TO_IMPORT_CSV.get(type_csv)
columns = {item.strip().lower() for item in columns}
if not required.issubset(columns):

exige-se todas as colunas definidas em MODEL_TO_IMPORT_CSV, em config/settings/base.py:688. Lá não tem nada sobre affliation (o fallback usado aqui). Para pesquisadores e membros do conselho, essa configuração inclui organization_name.

Por isso, um CSV com apenas affiliation é rejeitado antes de executar a tarefa que contém o fallback.

Comment thread core_settings/tasks.py
city=row.get("city_name"),
state=row.get("state_name"),
organization_name=row.get("affiliation"),
organization_name=row.get("organization_name") or row.get("affiliation"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idem à linha 162

@pitangainnovare pitangainnovare left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Há alguns pontos que podem ser analisados e corrigidos, se julgar pertinentes, mas nada bloqueante.

@robertatakenaka
robertatakenaka merged commit 7db83a5 into scieloorg:main Oct 6, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants