Jsdom: Validation de formulaire HTML5

Créé le 14 déc. 2012  ·  9Commentaires  ·  Source: jsdom/jsdom

JSDOM ne gère pas actuellement la validation des formulaires HTML5, et en particulier l'API checkValidity.

Cela est nécessaire pour tester avec précision les applications modernes qui utilisent des formulaires HTML5.

Je me demande s'il serait possible d'ajouter ce support, en utilisant http://www.thecssninja.com/javascript/h5f comme point de départ. H5F est un shim de navigateur pour ajouter la prise en charge des formulaires HTML5 aux navigateurs qui ne les prennent pas en charge. En aparté, je serais heureux d'ajouter moi-même ce comportement si quelqu'un peut m'indiquer la meilleure façon de le faire.

feature html living standard needs tests

Commentaire le plus utile

:+1: Ce serait une excellente fonctionnalité.

Tous les 9 commentaires

Je suis d'accord que ce serait bien et que c'est important. Cependant, ça va être tout à fait l'entreprise.

La plus grande chose dont cela a besoin est une suite de tests solide. Si vous regardez dans les lignes directrices de Contributing.md, vous trouverez des indications sur l'endroit où les trouver ou, à défaut, sur les listes de diffusion à demander. Si vous pouvez les déterrer, je pense que nous avons une chance de mettre cela en œuvre, d'autant plus que vous le soulignez en utilisant H5F comme point de départ.

La seule autre partie importante de l'implémentation réelle est que nous n'avons pas de dossier "level4" ou "html5" approprié pour implémenter des choses au-delà du niveau 3 de DOM. Mais c'est quelque chose dont nous avons besoin depuis un moment, donc je vais essayer pour s'y mettre bientôt.

:+1: Ce serait une excellente fonctionnalité.

En ce moment, j'ajoute https://github.com/hyperform/hyperform en tant que polyfill après la configuration de jsdom. Cela fonctionne très bien.

Yay! Je suis l'auteur d'Hyperform. Et comme par hasard, j'utilise déjà JSDom pour mettre en place un environnement de test .

La partie qui pourrait être intéressante pour les mainteneurs de JSDom : j'ai également essayé d'utiliser Hyperform dans JSDom pour couvrir les tests de plate-forme Web appropriés :

$ 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 = [];

et décommenter dans test/web-platform-tests/index.js les tests "html/semantics/forms/constraints/*.html" .

Malheureusement, je n'ai eu que quelques cas de test pour passer au vert. Mais si vous souhaitez ajouter (de quelque manière que ce soit) les fonctionnalités d'Hyperform à JSDom, je mettrais un peu plus de travail dans

a) faire réussir ces tests, et
b) fournir une version ou une configuration d'Hyperform, qui exclut l' API de haut niveau

FWIW, ça m'intéresse beaucoup; Je travaille sur un composant Vue qui rend un formulaire basé sur un schéma JSON et s'appuie sur l'API Validity pour générer un statut de validation lors de la soumission. Mes tests unitaires sont exécutés avec Jest (qui utilise JSDOM sous le capot), et pour l'instant je ne peux pas tester cette partie.

@Boldewyn si vous avez des suggestions concernant mon cas, je les prendrai avec plaisir. Peut-être que je pourrais également aider à mettre en œuvre cela, si on me donnait des conseils pour commencer :)

Edit : j'ai utilisé la solution de @EricHenry ci-dessous, et cela a fonctionné. Je devais juste définir checkValidity pour HTMLInputElement , HTMLSelectElement et HTMLTextAreaElement également (et en fait je n'avais pas besoin de jouer avec HTMLFormElement ). Acclamations!

Pour toute personne ayant ce problème lors du test des composants React à l'aide de Jest et Enzyme, j'ai pu polyfill JSDOM en utilisant le package hyperform mentionné ci-dessus par @fernandopasik et @Boldewyn

Dans votre fichier de test, vous pouvez effectuer les opérations suivantes après avoir installé 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);

vous pouvez suivre la même méthode pour tout autre HTMLElements que vous devrez peut-être modifier ou tout autre attribut dont vous avez besoin pour polyfill.

PR #2142 implémente l'API de contrainte complète sans aucun polyfill

La documentation Jest suggère des méthodes moqueuses qui ne sont pas implémentées dans JSDOM . Je pense que c'est une solution plus propre que de polluer votre environnement à cause des tests.

Dans mon cas spécifique, j'avais besoin de valider un formulaire, puis d'inspecter le classList du formulaire pour la présence d'une certaine classe, dont la présence m'informerait de la validité du formulaire.

Ma solution était de se moquer des propriétés du formulaire, par exemple, de se moquer de l'implémentation native de DOMTokenList pour la propriété classList à l'intérieur

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;
            })
        };
    });
})

Ensuite, j'ai utilisé cela pour transmettre des propriétés au gestionnaire d'événements. Je peux accéder au formulaire dans mon composant de réaction à partir du bouton Soumettre avec event.currentTarget.form

let mockClassList = new DOMTokenList();

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

Cela me permet de définir la validité du formulaire sur faux et vrai, et d'inspecter le mockClassList pour la présence de la classe was-validated chaque fois

    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: J'utilise le rendu superficiel d'Enzyme pour cela, le montage ne semble pas fonctionner avec cette solution. Cependant, je suis enclin à penser que l'autre suggestion de méthodes moqueuses qui ne sont pas implémentées dans JSDOM, lorsque la méthode est exécutée directement dans l'instruction de fichier testée, pourrait simplement fonctionner avec le rendu de montage

J'ai un problème avec input.validity qui n'est pas disponible pour moi dans 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==

Je vois que la version qui aurait dû être corrigée est la 11.8.0, car elle a été publiée le jour où PR avec l'interface de validité a été fusionnée. Est-ce que je manque quelque chose?

Cette page vous a été utile?
0 / 5 - 0 notes