Jsdom: Validierung von HTML5-Formularen

Erstellt am 14. Dez. 2012  ·  9Kommentare  ·  Quelle: jsdom/jsdom

JSDOM verarbeitet derzeit keine HTML5-Formularvalidierung und insbesondere nicht die checkValidity-API.

Dies ist erforderlich, um moderne Anwendungen, die HTML5-Formulare verwenden, genau zu testen.

Ich frage mich, ob es möglich wäre, diese Unterstützung hinzuzufügen, indem ich http://www.thecssninja.com/javascript/h5f als Ausgangspunkt verwende. H5F ist ein Browser-Shim, um Browsern, die diese nicht unterstützen, Unterstützung für HTML5-Formulare hinzuzufügen. Abgesehen davon würde ich dieses Verhalten gerne selbst hinzufügen, wenn mich jemand auf den besten Weg hinweisen kann.

feature html living standard needs tests

Hilfreichster Kommentar

:+1: Es wäre ein tolles Feature.

Alle 9 Kommentare

Ich stimme zu, das wäre schön und wichtig. Es wird jedoch ein ziemliches Unterfangen.

Das Wichtigste, was dies braucht, ist eine solide Testsuite. Wenn Sie in den Contributing.md-Richtlinien nachsehen, finden Sie dort einige Hinweise, wo Sie sie finden können, oder, falls dies nicht möglich ist, welche Mailinglisten zu fragen sind. Wenn Sie sie ausgraben können, denke ich, dass wir eine Chance haben, dies zu implementieren, insbesondere wie Sie darauf hinweisen, indem wir H5F als Ausgangspunkt verwenden.

Der einzige andere wichtige Teil der eigentlichen Implementierung ist, dass wir keinen richtigen „level4“- oder „html5“-Ordner haben, um Dinge über DOM Level 3 hinaus zu implementieren. Aber das brauchen wir schon seit einiger Zeit, also werde ich es versuchen um es bald anzugehen.

:+1: Es wäre ein tolles Feature.

Im Moment füge ich https://github.com/hyperform/hyperform als Polyfill nach dem jsdom-Setup hinzu. Es funktioniert großartig.

Yay! Ich bin der Autor von Hyperform. Und wie es der Zufall will, nutze ich JSDom bereits , um eine Testumgebung einzurichten .

Der Teil, der für die JSDom-Betreuer interessant sein könnte: Ich habe auch mit der Verwendung von Hyperform innerhalb von JSDom herumgespielt, um die entsprechenden Webplattformtests abzudecken:

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

und kommentieren Sie in test/web-platform-tests/index.js die "html/semantics/forms/constraints/*.html" -Tests aus.

Leider habe ich nur ein paar Testfälle bekommen, um grün zu werden. Aber wenn Sie daran interessiert sind, die Funktionen von Hyperform (auf welche Weise auch immer) zu JSDom hinzuzufügen, würde ich etwas mehr Arbeit investieren

a) diese Tests zu bestehen, und
b) Bereitstellen einer Version oder Konfiguration für Hyperform, die die High-Level-API ausschließt

FWIW, das interessiert mich sehr; Ich arbeite an einer Vue-Komponente, die ein Formular basierend auf einem JSON-Schema rendert und sich auf die Validity-API verlässt, um bei der Übermittlung einen Validierungsstatus zu erhalten. Meine Komponententests werden mit Jest (das JSDOM unter der Haube verwendet) durchgeführt, und ab sofort kann ich diesen Teil nicht testen.

@Boldewyn Wenn Sie einen Vorschlag zu meinem Fall haben, würde ich ihn gerne annehmen. Vielleicht könnte ich auch bei der Implementierung helfen, wenn ich eine Anleitung zum Starten bekomme :)

Bearbeiten: Ich habe die Lösung von @EricHenry unten verwendet, und es hat funktioniert. Ich musste nur checkValidity für HTMLInputElement , HTMLSelectElement und HTMLTextAreaElement setzen (und musste eigentlich nicht mit HTMLFormElement ). Beifall!

Für alle, die dieses Problem beim Testen von React-Komponenten mit Jest und Enzyme hatten, konnte ich JSDOM mithilfe des oben erwähnten Hyperform-Pakets von @fernandopasik und @Boldewyn polyfillen

In Ihrer Testdatei können Sie nach der Installation von hyperform Folgendes tun.

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

Sie können die gleiche Methode für alle anderen HTML-Elemente verwenden, die Sie möglicherweise ändern müssen, oder für alle anderen Attribute, die Sie polyfill benötigen.

PR #2142 implementiert die vollständige Constraint-API ohne Polyfills

Die Jest-Dokumentation schlägt Mocking-Methoden vor, die nicht in JSDOM implementiert sind . Ich denke, das ist eine sauberere Lösung, als die Umwelt durch Tests zu verschmutzen.

In meinem speziellen Fall musste ich ein Formular validieren und dann das classList des Formulars auf das Vorhandensein einer bestimmten Klasse untersuchen, deren Vorhandensein mich über die Gültigkeit des Formulars informieren würde.

Meine Lösung bestand darin, die Eigenschaften des Formulars zu verspotten, z. B. die native Implementierung von DOMTokenList für die darin enthaltene Eigenschaft classList zu verspotten

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

Dann habe ich das verwendet, um Eigenschaften an den Event-Handler zu übergeben. Ich kann auf das Formular in meiner Reaktionskomponente über die Schaltfläche „Senden“ mit event.currentTarget.form zugreifen

let mockClassList = new DOMTokenList();

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

Dadurch kann ich die Gültigkeit des Formulars auf „false“ und „true“ setzen und die Klasse „$#$ mockClassList $#$“ jedes Mal auf das Vorhandensein der Klasse „ was-validated “ untersuchen

    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: Ich verwende dafür das flache Rendering von Enzyme, Mount scheint mit dieser Lösung nicht zu funktionieren. Ich neige jedoch zu der Annahme, dass der andere Vorschlag zum Spotten von Methoden, die nicht in JSDOM implementiert sind, wenn die Methode direkt in der getesteten Dateianweisung ausgeführt wird, möglicherweise nur mit Mount-Rendering funktioniert

Ich habe ein Problem mit input.validity , das für mich in j [email protected] nicht verfügbar ist.

// 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==

Ich sehe, dass die Version, die behoben werden sollte, 11.8.0 ist, da sie an dem Tag veröffentlicht wurde, an dem PR mit der Gültigkeitsschnittstelle zusammengeführt wurde. Übersehe ich etwas?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen