Skip to content

feat(validation): Implementar validações para elemento <ext-link> conforme SPS 1.10 com i18n completo#1091

Merged
robertatakenaka merged 6 commits intomasterfrom
copilot/add-validations-for-ext-link
Feb 24, 2026
Merged

feat(validation): Implementar validações para elemento <ext-link> conforme SPS 1.10 com i18n completo#1091
robertatakenaka merged 6 commits intomasterfrom
copilot/add-validations-for-ext-link

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 13, 2026

O que esse PR faz?

Implementa 6 validações para o elemento <ext-link> conforme especificação SPS 1.10, aumentando conformidade de 0% para 67%. Inclui integração completa no pipeline de validação XML do packtools com suporte completo a internacionalização (i18n).

Validações P0 (Critical/Error):

  • Presença obrigatória de @ext-link-type e @xlink:href
  • Formato de URL (deve iniciar com http:// ou https://)
  • Valores permitidos: uri, doi, pmid, pmcid, clinical-trial

Validações P1 (Warning):

  • Texto descritivo (detecta frases genéricas em PT/EN, case-insensitive)
  • @xlink:title obrigatório quando texto é genérico ou URL

Características técnicas:

  • Suporte completo a i18n com _() wrapper em todos os advice_text
  • Uso de advice_text + advice_params para internacionalização
  • Extração de ext-links em artigo principal e sub-artigos
  • Tratamento correto do namespace XLink
  • Validações condicionais (skip quando atributo ausente)
  • Integração completa no xml_validator seguindo padrão article_xref
  • Arquivo de configuração ext_link_rules.json

Onde a revisão poderia começar?

  1. packtools/sps/validation/ext_link.py - Lógica de validação (6 métodos geradores) com i18n completo usando _()
  2. packtools/sps/models/ext_link.py - Extração de dados (herda de Fulltext)
  3. packtools/sps/validation_rules/ext_link_rules.json - Configuração de níveis de erro
  4. packtools/sps/validation/xml_validations.py - Função validate_ext_links() para integração
  5. packtools/sps/validation/xml_validator.py - Grupo "ext-link" no pipeline
  6. tests/sps/validation/test_ext_link.py - 26 testes de validação
  7. tests/sps/models/test_ext_link.py - 16 testes do modelo

Como este poderia ser testado manualmente?

Teste 1: Validação direta

from lxml import etree
from packtools.sps.validation.ext_link import ExtLinkValidation

# Caso 1: Atributos faltando (CRITICAL)
xml = """<article xmlns:xlink="http://www.w3.org/1999/xlink">
    <body><ext-link>Link</ext-link></body>
</article>"""
validator = ExtLinkValidation(etree.fromstring(xml))
list(validator.validate_ext_link_type_presence())  # CRITICAL
list(validator.validate_xlink_href_presence())     # CRITICAL

# Caso 2: URL sem protocolo (ERROR)
xml2 = """<article xmlns:xlink="http://www.w3.org/1999/xlink">
    <body><ext-link ext-link-type="uri" xlink:href="proxy.php?url=https%3A%2F%2Fgithub.com%2Fwww.example.com">Link</ext-link></body>
</article>"""
validator2 = ExtLinkValidation(etree.fromstring(xml2))
list(validator2.validate_xlink_href_format())  # ERROR

# Caso 3: Texto genérico (WARNING)
xml3 = """<article xmlns:xlink="http://www.w3.org/1999/xlink">
    <body><ext-link ext-link-type="uri" xlink:href="proxy.php?url=https%3A%2F%2Fexample.com">clique aqui</ext-link></body>
</article>"""
validator3 = ExtLinkValidation(etree.fromstring(xml3))
list(validator3.validate_descriptive_text())  # WARNING

Teste 2: Integração com xml_validator

from lxml import etree
from packtools.sps.validation.xml_validator import validate_xml_content

xml = """<article xmlns:xlink="http://www.w3.org/1999/xlink">
    <body>
        <ext-link xlink:href="proxy.php?url=https%3A%2F%2Fexample.com">Example</ext-link>
    </body>
</article>"""

xmltree = etree.fromstring(xml.encode())

# Verifica grupo ext-link no pipeline
for group_result in validate_xml_content(xmltree, {}):
    if group_result['group'] == 'ext-link':
        for item in group_result['items']:
            if item and item.get('response') != 'OK':
                print(f"{item['title']}: {item['response']}")

Executar testes:

# Testes de validação
python3 -m unittest tests.sps.validation.test_ext_link -v

# Testes do modelo
python3 -m unittest tests.sps.models.test_ext_link -v

# Todos os testes ext-link
python3 -m unittest tests.sps.validation.test_ext_link tests.sps.models.test_ext_link -v

Algum cenário de contexto que queira dar?

Padrões seguidos:

  • build_response() com i18n completo (análogo a article_doi.py, article_contribs.py, accessibility_data.py)
  • Todos os advice_text envolvidos com _() para internacionalização
  • Modelo herda de Fulltext para contexto de parent (análogo a related_articles.py)
  • Validações condicionais retornam early quando dependências ausentes
  • Namespace XLink tratado: {http://www.w3.org/1999/xlink}hrefxlink_href
  • Integração no xml_validator seguindo padrão de article_xref

Internacionalização (i18n):

  • Importado gettext e definido _ = gettext.gettext
  • Todas as 6 strings de advice_text envolvidas com _() para suporte multilíngue
  • Padrão consistente com accessibility_data.py e outras validações do packtools

Integração no pipeline de validação:

  • Arquivo ext_link_rules.json criado em packtools/sps/validation_rules/
  • Função validate_ext_links() adicionada em xml_validations.py
  • Grupo "ext-link" integrado em xml_validator.py
  • Todas as validações executam automaticamente através do validate_xml_content()

Frases genéricas detectadas:
leia mais, clique aqui, acesse, veja mais, saiba mais, click here, read more, see more, learn more, more info

Regras não implementadas (fora de escopo):

  • Validação específica de formato DOI (já existe em utils.validate_doi_format())
  • Validação de formato PMID/PMCID (baixa prioridade, requer integração com APIs externas)

Garantias de qualidade:

  • ✅ 42 testes unitários (26 validação + 16 modelo) - 100% pass rate
  • ✅ Integração verificada: validações executam através do xml_validator
  • Internacionalização completa: todos os advice_text usam _()
  • ✅ CodeQL: 0 vulnerabilidades
  • ✅ Testes existentes não afetados
  • ✅ Code review: todos os feedbacks implementados

Screenshots

N/A - Validações backend sem interface gráfica.

Quais são tickets relevantes?

TK #1082

Referências

Original prompt

This section details on the original issue you should resolve

<issue_title>Criar validações para o elemento </issue_title>
<issue_description>## Objetivo

Implementar validações para o elemento <ext-link> conforme a especificação SPS 1.10, aumentando a conformidade de 0% para 67% (6 de 9 regras).


Contexto

O elemento <ext-link> é usado para marcar links ou hyperlink text externos em artigos científicos, garantindo acessibilidade e interoperabilidade. Validações corretas asseguram que os links estejam bem formados, possuam atributos obrigatórios e sigam boas práticas de acessibilidade (texto descritivo ao invés de URLs genéricas).

Conformidade atual: 0 de 9 regras implementadas (0%)
Meta após implementação: 6 de 9 regras (67%)


Documentação SPS

Referência oficial: https://docs.google.com/document/d/1GTv4Inc2LS_AXY-ToHT3HmO66UT0VAHWJNOIqzBNSgA/edit?tab=t.0#heading=h.n2z5yrri2aba

Regras principais conforme SPS 1.10:

  1. Atributos obrigatórios:

    • @ext-link-type (obrigatório)
    • @xlink:href (obrigatório)
  2. Valores permitidos para @ext-link-type:

    • uri - Link para website
    • doi - Link DOI (deve incluir doi.org/ ou dx.doi.org/)
    • pmid - Link para PubMed
    • pmcid - Link para PubMed Central
    • clinical-trial - Link para registro de ensaio clínico
  3. Formato do @xlink:href:

    • Deve ser URL completa iniciando com http:// ou https://
  4. Acessibilidade:

    • Texto dentro de <ext-link> deve ser descritivo
    • Evitar textos genéricos como "Leia mais", "clique aqui", "acesse"
    • Quando o texto não for descritivo suficiente, usar @xlink:title com descrição
  5. Restrições:

    • Não usar <uri> ou <self-uri> (substituídos por <ext-link>)
    • Exceto em referências bibliográficas onde a URL pode ser exposta

Regras a Implementar

P0 – Críticas (implementar obrigatoriamente)

# Regra Nível Descrição
1 Validar presença de @ext-link-type CRITICAL O atributo @ext-link-type é obrigatório em todos os <ext-link>
2 Validar presença de @xlink:href CRITICAL O atributo @xlink:href é obrigatório em todos os <ext-link>
3 Validar formato de @xlink:href ERROR O valor de @xlink:href deve ser URL completa começando com http:// ou https://
4 Validar valor de @ext-link-type ERROR O valor de @ext-link-type deve ser um dos permitidos: uri, doi, pmid, pmcid, clinical-trial

P1 – Importantes (implementar se possível)

# Regra Nível Descrição
5 Validar texto descritivo WARNING O texto do link não deve ser genérico ("leia mais", "clique aqui", "acesse", "veja mais", "saiba mais", "click here", "read more", "see more"). Validação case-insensitive.
6 Validar @xlink:title quando texto genérico WARNING Quando o texto for genérico ou for a própria URL, o atributo @xlink:title deve estar presente com descrição do destino do link

P2 – Futuras (fora do escopo deste Issue)

# Regra Motivo de exclusão
7 Validar formato específico de DOI em @xlink:href Validação de formato DOI específico já existe em utils.validate_doi_format()
8 Validar formato de PMID Baixa prioridade - depende de integração com PubMed API
9 Validar formato de PMCID Baixa prioridade - depende de integração com PMC API

Arquivos a Criar/Modificar

Criar:

  • packtools/sps/models/ext_link.py – Modelo de extração de dados
  • packtools/sps/validation/ext_link.py – Validações
  • packtools/sps/validation/rules/ext_link_rules.json – Configuração de níveis de erro
  • tests/sps/validation/test_ext_link.py – Testes unitários

Referenciar (implementações similares):

  • packtools/sps/models/related_article.py – Modelo similar (também é link)
  • packtools/sps/validation/article_doi.py – Validação de atributos obrigatórios e formato
  • packtools/sps/validation/utils.py – Funções auxiliares (build_response, is_valid_url_format)

Exemplos de XML

XML Válido (deve passar sem erros):

<!-- Exemplo 1: hyperlink text descritivo -->
<p>
    <ext-link ext-link-type="uri" xlink:href="https://www.scielo.br/">SciELO Brasil</ext-link>
</p>

<!-- Exemplo 2: link com @xlink:title para contexto adicional -->
<p>
    <ext-link ext-link-type="uri" 
              xlink:href="https://docs.google.com/document/d/123/edit" 
              xlink:title="Guia de uso de elementos e atributos XML para documentos SPS">
        Leia mais sobre link no SPS
    </ext-link>
</p>

<!-- Exemplo 3: link DOI -->
<p>
    <ext-link ext-link-type="doi" xlink:href="https://doi.org/10.1590/1806-9584-2025v33n1103677">
        https://doi.org/10.1590/1806-9584-2025v33n1103677
    </ext-link>
</p>

<!-- Exemplo 4: link para ensaio clínico -->
<p>
    <ext-link ext-link-type="clinical-trial" xlink...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes scieloorg/packtools#1082

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.

Copilot AI changed the title [WIP] Implement validations for ext-link element feat(validation): Implementar validações para elemento <ext-link> conforme SPS 1.10 Feb 13, 2026
@Rossi-Luciano
Copy link
Copy Markdown
Collaborator

Complementar os seguintes arquivos para considerar a nova validação:

  • packtools/sps/validation/xml_validations.py
  • packtools/sps/validation/xml_validator.py
  • packtools/sps/validation/xml_validator_rules.py

Considere o padrão apresentado para a validação do elemento article_xref.
Adicionar suite de testes para o novo modelo: packtools/sps/models/ext_link.py

self.params.setdefault("xlink_href_format_error_level", "ERROR")
self.params.setdefault("ext_link_type_value_error_level", "ERROR")
self.params.setdefault("descriptive_text_error_level", "WARNING")
self.params.setdefault("xlink_title_error_level", "WARNING")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Adicionar dicionário com níveis de validação em um módulo separado, como em packtools/sps/validation_rules/article_ids_rules.json

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in commit 47ec6b7. Created packtools/sps/validation_rules/ext_link_rules.json with validation error level settings following the pattern from article_ids_rules.json.

@Rossi-Luciano Rossi-Luciano self-requested a review February 20, 2026 11:54
self.params.setdefault("xlink_href_format_error_level", "ERROR")
self.params.setdefault("ext_link_type_value_error_level", "ERROR")
self.params.setdefault("descriptive_text_error_level", "WARNING")
self.params.setdefault("xlink_title_error_level", "WARNING")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot Adicionar dicionário com níveis de validação em um módulo separado, como em packtools/sps/validation_rules/article_ids_rules.json

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in commit 47ec6b7. Created packtools/sps/validation_rules/ext_link_rules.json with validation error level settings following the pattern from article_ids_rules.json.

Comment thread packtools/sps/validation/ext_link.py Outdated

is_valid = bool(xlink_href)

advice_text = 'Add @xlink:href attribute to <ext-link> with text "{text}"'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot todos os advice_text tem que ter a internacionalização (uso de _( e ))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in commit 1f61b9a. Added internationalization to all advice_text strings:

  • Imported gettext and defined _ = gettext.gettext
  • Wrapped all 6 advice_text strings with _() for i18n support
  • All 42 tests still passing

@robertatakenaka
Copy link
Copy Markdown
Member

@copilot Complementar os seguintes arquivos para considerar a nova validação:

packtools/sps/validation/xml_validations.py
packtools/sps/validation/xml_validator.py
packtools/sps/validation/xml_validator_rules.py
Considere o padrão apresentado para a validação do elemento article_xref.
Adicionar suite de testes para o novo modelo: packtools/sps/models/ext_link.py

- Created ext_link_rules.json with validation error levels
- Integrated ExtLinkValidation into xml_validations.py and xml_validator.py
- Added 16 comprehensive model tests for ext_link.py
- All tests passing (26 validation + 16 model tests)

Co-authored-by: robertatakenaka <[email protected]>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 20, 2026

Complementar os seguintes arquivos para considerar a nova validação:

  • packtools/sps/validation/xml_validations.py
    ...

Done in commit 47ec6b7. Completed all requested integrations following the article_xref pattern:

  1. ✅ Added validate_ext_links() to xml_validations.py (imports ExtLinkValidation and calls all 6 validation methods)
  2. ✅ Added "ext-link" validation group to xml_validator.py
  3. ✅ Created ext_link_rules.json in validation_rules directory
  4. ✅ Added comprehensive model test suite: tests/sps/models/test_ext_link.py (16 tests covering all extraction scenarios)

All 42 tests passing (26 validation + 16 model tests). Integration verified working.

- Import gettext and define _ = gettext.gettext
- Wrap all 6 advice_text strings with _() for i18n support
- All 42 tests still passing (26 validation + 16 model)

Co-authored-by: robertatakenaka <[email protected]>
Copilot AI changed the title feat(validation): Implementar validações para elemento <ext-link> conforme SPS 1.10 feat(validation): Implementar validações para elemento <ext-link> conforme SPS 1.10 com i18n completo Feb 20, 2026
Rossi-Luciano
Rossi-Luciano previously approved these changes Feb 24, 2026
@robertatakenaka robertatakenaka marked this pull request as ready for review February 24, 2026 12:38
Copilot AI review requested due to automatic review settings February 24, 2026 12:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Implementa validações SPS 1.10 para o elemento <ext-link> e integra o novo conjunto de checagens ao pipeline de validação XML do Packtools, incluindo configuração de níveis por rules JSON e cobertura por testes unitários.

Changes:

  • Adiciona modelo para extração de dados de <ext-link> no artigo principal e sub-artigos.
  • Implementa 6 validações (atributos obrigatórios, formato, valores permitidos e regras de acessibilidade) e integra no xml_validator.
  • Inclui regras ext_link_rules.json e testes unitários para validação e extração do modelo.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packtools/sps/validation/ext_link.py Implementa validações de <ext-link> com suporte a advice_text/advice_params.
packtools/sps/models/ext_link.py Extrai <ext-link> (atributos, texto e contexto do parent) do artigo e sub-artigos.
packtools/sps/validation_rules/ext_link_rules.json Define níveis de severidade para as regras de <ext-link>.
packtools/sps/validation/xml_validations.py Adiciona validate_ext_links() para executar as 6 validações.
packtools/sps/validation/xml_validator.py Inclui o novo grupo "ext-link" no pipeline.
tests/sps/validation/test_ext_link.py Testes das validações (atributos, formato, valores e acessibilidade).
tests/sps/models/test_ext_link.py Testes de extração do modelo (atributos, texto, seções e sub-artigos).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packtools/sps/models/ext_link.py Outdated
Comment on lines +17 to +18
tostring,
remove_namespaces,
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

In ExtLink the imports tostring and remove_namespaces are never used in this module. Please remove them to avoid dead code and keep the module dependencies minimal.

Suggested change
tostring,
remove_namespaces,

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Concordo. Os imports foram removidos do módulo. Nenhuma função do arquivo
os utilizava, e nenhuma outra classe importa esses símbolos a partir daqui.

Comment thread packtools/sps/models/ext_link.py Outdated
Comment on lines +144 to +149
# Sub-articles ext-links (recursively)
for fulltext in self._ext_link.fulltexts:
ext_links.extend(list(fulltext.ext_links))
# Handle nested sub-articles
for nested_fulltext in fulltext.fulltexts:
ext_links.extend(list(nested_fulltext.ext_links))
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

ArticleExtLinks.ext_links only descends into sub-articles two levels deep (fulltext and nested_fulltext). This will miss <ext-link> elements if there are deeper nested <sub-article> structures. Consider iterating xmltree.xpath('.//sub-article') (like other extractors) or implementing a true recursive traversal so all depths are covered.

Suggested change
# Sub-articles ext-links (recursively)
for fulltext in self._ext_link.fulltexts:
ext_links.extend(list(fulltext.ext_links))
# Handle nested sub-articles
for nested_fulltext in fulltext.fulltexts:
ext_links.extend(list(nested_fulltext.ext_links))
# All sub-articles ext-links at any depth
for sub_article_node in self.xmltree.xpath(".//sub-article"):
sub_article_ext_link = ExtLink(sub_article_node)
ext_links.extend(list(sub_article_ext_link.ext_links))

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Concordo com o diagnóstico, mas não com a solução sugerida.

Usar xpath(".//sub-article") diretamente em ArticleExtLinks ignora o mecanismo
de fulltexts já existente em ExtLink, e mais importante: cada sub-article
instanciado isoladamente perde o parent_data correto (parent_id, parent_lang
etc.), pois esse contexto é derivado do nó raiz passado ao construtor.

A correção adotada foi um método recursivo _collect_ext_links() que desce
via fulltext.fulltexts, preservando o contexto em cada nível:

def _collect_ext_links(self, fulltext):
      yield from fulltext.ext_links
      for child in fulltext.fulltexts:
          yield from self._collect_ext_links(child)

Isso cobre qualquer profundidade de aninhamento e mantém a coerência do
modelo. Um teste de regressão com 3 níveis de profundidade foi adicionado
em test_ext_link.py (test_ext_links_deeply_nested_sub_articles).

Comment on lines +92 to +98
error_level = error_level or self.params.get("ext_link_type_error_level", "CRITICAL")

for ext_link in self.ext_links_model.ext_links:
ext_link_type = ext_link.get("ext_link_type")
text = ext_link.get("text", "")[:50] # First 50 chars for context

is_valid = bool(ext_link_type)
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

Each validation method iterates self.ext_links_model.ext_links, but ArticleExtLinks.ext_links builds a new list every time the property is accessed. Since validate_ext_links() calls 6 validations, this re-parses the XML repeatedly and can become expensive on large documents. Cache the extracted ext-links once (e.g., compute a list in __init__ and reuse it, or memoize ArticleExtLinks.ext_links).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Válido. ArticleExtLinks.ext_links foi convertido de @Property para
@cached_property (functools), resolvendo o problema na origem — no modelo —
em vez de adicionar cache local no validador.

Com isso, independentemente de quantas validações acessem ext_links_model.ext_links,
o XML é percorrido uma única vez. Um teste foi adicionado para garantir esse
comportamento (test_ext_links_cached_property_returns_same_object), que usa
assertIs para confirmar que as duas chamadas retornam o mesmo objeto em memória.

Comment thread packtools/sps/validation/ext_link.py Outdated
Comment on lines +397 to +401
reason = "generic" if is_generic else "URL"
advice_text = _('Add @xlink:title attribute to <ext-link> with {reason} text "{text}" to describe link destination')
advice_params = {
"reason": reason,
"text": text,
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

For i18n, reason is interpolated into a translated advice_text, but the values assigned are hard-coded English strings ("generic" / "URL"). This makes the final localized message partially untranslated. Prefer using separate advice_text messages per case, or pass a localized reason value (or a neutral key that translations can map without leaking English into the output).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Correto. O problema é que "generic" e "URL" eram strings em inglês passadas
como parâmetro {reason} dentro de uma mensagem traduzível, o que resultaria
em mensagens parcialmente em inglês em qualquer outro locale.

A correção foi separar em dois advice_text completamente distintos e
traduzíveis, um para cada caso, eliminando o parâmetro {reason}:

if is_generic:
    advice_text = _('Add @xlink:title ... with generic text "{text}" ...')
else:
    advice_text = _('Add @xlink:title ... where the text is the URL "{text}" ...')

Ambas as mensagens precisam apenas de {text} como parâmetro. O teste que
verificava assertIn("reason", adv_params) foi atualizado para
assertIn("text", adv_params) com comentário explicando a mudança.

Comment on lines +612 to +616
type_presence_results = filter_results(validator.validate_ext_link_type_presence())
href_presence_results = filter_results(validator.validate_xlink_href_presence())
href_format_results = filter_results(validator.validate_xlink_href_format())
type_value_results = filter_results(validator.validate_ext_link_type_value())
text_results = filter_results(validator.validate_descriptive_text())
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

In this multi-link test, href_presence_results is computed but never asserted, so the test doesn't actually verify validate_xlink_href_presence() behavior for the mixed cases. Add assertions for href_presence_results (e.g., total count and number of non-OK responses) to make this test cover the intended validation.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Correto. href_presence_results era calculado mas não tinha nenhum assert,
o que significa que a validação de presença do @xLink:href nunca era
de fato testada nesse cenário misto.

Foram adicionadas duas asserções:

self.assertEqual(len(href_presence_results), 3)
 self.assertEqual(len([r for r in href_presence_results if r["response"] != "OK"]), 0)

No XML do teste, todos os três ext-links possuem @xLink:href — portanto
3 resultados esperados e 0 falhas. Isso agora está explicitamente verificado.

@robertatakenaka robertatakenaka merged commit 6e1c969 into master Feb 24, 2026
2 checks passed
Rossi-Luciano added a commit to Rossi-Luciano/packtools that referenced this pull request Mar 19, 2026
…onforme SPS 1.10 com i18n completo (scieloorg#1091)

* Initial plan

* Implement ext-link validations with model and tests (all 26 tests passing)

Co-authored-by: robertatakenaka <[email protected]>

* Fix whitespace in test file (code review feedback)

Co-authored-by: robertatakenaka <[email protected]>

* Add ext-link validation integration and model tests

- Created ext_link_rules.json with validation error levels
- Integrated ExtLinkValidation into xml_validations.py and xml_validator.py
- Added 16 comprehensive model tests for ext_link.py
- All tests passing (26 validation + 16 model tests)

Co-authored-by: robertatakenaka <[email protected]>

* Add internationalization (_) to all advice_text strings in ext_link.py

- Import gettext and define _ = gettext.gettext
- Wrap all 6 advice_text strings with _() for i18n support
- All 42 tests still passing (26 validation + 16 model)

Co-authored-by: robertatakenaka <[email protected]>

* Correções aplicadas ao modelo e validação do elemento <ext-link>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: robertatakenaka <[email protected]>
Co-authored-by: Rossi-Luciano <[email protected]>
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.

4 participants