Jsdom: Validação de formulário HTML5

Criado em 14 dez. 2012  ·  9Comentários  ·  Fonte: jsdom/jsdom

Atualmente, o JSDOM não lida com validação de formulários HTML5 e, em particular, com a API checkValidity.

Isso é necessário para testar com precisão os aplicativos modernos que utilizam formulários HTML5.

Gostaria de saber se seria possível adicionar esse suporte, usando http://www.thecssninja.com/javascript/h5f como ponto de partida. H5F é um shim do navegador para adicionar suporte a formulários HTML5 a navegadores que não os suportam. Como um aparte, eu ficaria feliz em adicionar esse comportamento se alguém puder me indicar a melhor maneira de fazê-lo.

feature html living standard needs tests

Comentários muito úteis

:+1: Seria um ótimo recurso.

Todos 9 comentários

Concordo que isso seria bom e é importante. No entanto, vai ser um grande empreendimento.

A maior coisa que isso precisa é de um conjunto de testes sólido. Se você olhar nas diretrizes do Contributing.md, há alguns indicadores de onde encontrá-los, ou, na falta disso, quais listas de discussão perguntar. Se você puder desenterrá-los, acho que temos uma chance de implementar isso, especialmente como você aponta usando o H5F como ponto de partida.

A única outra parte importante da implementação real é que não temos uma pasta "level4" ou "html5" adequada para implementar coisas além do DOM Nível 3. Mas isso é algo que precisamos há algum tempo, então vou tentar para embarcar em breve.

:+1: Seria um ótimo recurso.

Agora estou adicionando https://github.com/hyperform/hyperform como um polyfill após a configuração do jsdom. Funciona muito bem.

Yay! Eu sou o autor do Hyperform. E por sorte, eu já uso o JSDom para configurar um ambiente de teste .

A parte que pode ser interessante para os mantenedores do JSDom: Eu brinquei com o uso do Hyperform dentro do JSDom também, para cobrir os testes apropriados da plataforma web:

$ git diff test/web-platform-tests/create-jsdom.js
diff --git a/test/web-platform-tests/create-jsdom.js b/test/web-platform-tests/create-jsdom.js
index 7009df7..9edcb16 100644
--- a/test/web-platform-tests/create-jsdom.js
+++ b/test/web-platform-tests/create-jsdom.js
@@ -1,5 +1,6 @@
 "use strict";
 const jsdom = require("../..");
+const hyperform = require("hyperform");
 const nodeResolverPromise = require("../util").nodeResolverPromise;

 const globalPool = { maxSockets: 6 };
@@ -35,6 +36,9 @@ module.exports = (urlPrefix, testPath) => {

   return created
   .then(window => {
+    global.window = window;
+    global.document = window.document;
+    hyperform(window);
     return new Promise((resolve, reject) => {
       const errors = [];

e descomentando em test/web-platform-tests/index.js os testes "html/semantics/forms/constraints/*.html" .

Infelizmente eu só tenho alguns casos de teste para ficar verde. Mas se você estiver interessado em adicionar (de qualquer maneira) os recursos do Hyperform ao JSDom, eu daria mais trabalho

a) fazer esses testes passarem, e
b) fornecer uma versão ou configuração do Hyperform, que exclua a API de alto nível

FWIW, estou bastante interessado nisso; Estou trabalhando em um componente Vue que renderiza um formulário baseado em um esquema JSON e conta com a API Validity para gerar um status de validação após o envio. Meus testes de unidade são executados com Jest (que usa JSDOM sob o capô) e, a partir de agora, não consigo testar essa parte.

@Boldewyn se você tiver alguma sugestão sobre o meu caso, eu aceitaria com prazer. Talvez eu possa fornecer alguma ajuda na implementação disso também, se receber alguma orientação para começar :)

Edit: usei a solução do @EricHenry abaixo e funcionou. Eu só tive que definir checkValidity para HTMLInputElement , HTMLSelectElement e HTMLTextAreaElement também (e na verdade não precisei mexer com HTMLFormElement ). Felicidades!

Para qualquer um que tenha esse problema ao testar componentes React usando Jest e Enzyme, consegui polyfill JSDOM usando o pacote hyperform mencionado acima por @fernandopasik e @Boldewyn

Em seu arquivo de teste, você pode fazer o seguinte após instalar o hyperform.

import * as hyperform from 'hyperform';

var global = global;

const defineValidity = {
  get() {
    return hyperform.ValidityState(this);
  },
  configurable: true
};

global.HTMLFormElement.prototype.checkValidity = function() {
  return hyperform.checkValidity(this);
};

Object.defineProperty(global.HTMLFormElement.prototype, 'validity', defineValidity);
Object.defineProperty(global.HTMLInputElement.prototype, 'validity', defineValidity);
Object.defineProperty(global.HTMLSelectElement.prototype, 'validity', defineValidity);
Object.defineProperty(global.HTMLTextAreaElement.prototype, 'validity', defineValidity);

você pode seguir o mesmo método para qualquer outro HTMLElements que precise modificar ou quaisquer outros atributos que precise polipreencher.

PR #2142 implementa a API de restrição completa sem polyfills

A documentação do Jest sugere métodos de simulação que não são implementados no JSDOM . Eu acho que esta é uma solução mais limpa do que poluir seu ambiente por causa de testes.

No meu caso específico, precisei validar um formulário e então inspecionar o classList do formulário quanto à presença de uma determinada classe, cuja presença me informaria sobre a validade do formulário.

Minha solução foi zombar das propriedades do formulário, por exemplo, zombar da implementação nativa de DOMTokenList para a propriedade classList dentro

beforeAll(() => {
    window.DOMTokenList = jest.fn().mockImplementation(() => {
        return {
            list: [],
            remove: jest.fn().mockImplementation(function (item) {
                const idx = this.list.indexOf(item);

                if (idx > -1) {
                    this.list.splice(idx, 1)
                }
            }),
            add: jest.fn().mockImplementation(function (item) {
                this.list.push(item);
            }),
            contains: jest.fn().mockImplementation(function (item) {
                return this.list.indexOf(item) > -1;
            })
        };
    });
})

Então eu usei isso para passar propriedades para o manipulador de eventos. Consigo acessar o formulário no meu componente reagir a partir do botão de envio com event.currentTarget.form

let mockClassList = new DOMTokenList();

submitBtn.simulate('click', {
        currentTarget: {
            form: {
                checkValidity: () => false,
                classList: mockClassList
            }
        },
        preventDefault: jest.fn(),
        stopPropagation: jest.fn()
    })

Isso me permite definir a validade do formulário como falso e verdadeiro e inspecionar o mockClassList quanto à presença da classe was-validated a cada vez

    submitBtn.simulate('click', {
        currentTarget: {
            form: {
                checkValidity: () => false,
                classList: mockClassList
            }
        },
        preventDefault: jest.fn(),
        stopPropagation: jest.fn()
    });

    expect(mockClassList.contains('was-validated')).toBeTruthy();

    submitBtn.simulate('click', {
        currentTarget: {
            form: {
                checkValidity: () => true,
                classList: mockClassList
            }
        },
        preventDefault: jest.fn(),
        stopPropagation: jest.fn()
    });

    expect(mockClassList.contains('was-validated')).toBeFalsy();

FYI: Estou usando a renderização superficial do Enzyme para isso, a montagem não parece funcionar com esta solução. No entanto, estou inclinado a pensar que a outra sugestão para métodos de simulação que não são implementados no JSDOM, quando o método é executado diretamente na instrução de arquivo testada, pode funcionar apenas com renderização de montagem

Eu tenho um problema com input.validity que não está disponível para mim em j [email protected] .

// EditableInput.js:
this.inputElement = React.createRef();
...
const input = this.inputElement.current;
console.error('input.validity: ', input.validity);
// EditableInput.test.js run outcome:
    console.error src/components/Form/Input/EditableInput.js:47
      input.validity:  undefined
// yarn.lock:
jsdom@^11.5.1:
  version "11.12.0"
  resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
  integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==

Vejo que a versão que deveria ter sido corrigida é a 11.8.0, pois foi lançada no dia em que o PR com a interface de validade foi mesclado. Estou esquecendo de algo?

Esta página foi útil?
0 / 5 - 0 avaliações