JSDOMは現在、HTML5フォームの検証、特にcheckValidityAPIを処理していません。
これは、HTML5フォームを利用する最新のアプリケーションを正確にテストするために必要です。
http://www.thecssninja.com/javascript/h5fを出発点として、このサポートを追加することは可能でしょうか。 H5Fは、HTML5フォームをサポートしていないブラウザーにHTML5フォームのサポートを追加するためのブラウザーシムです。 余談ですが、誰かが私にそれを行うための最良の方法を教えてくれるなら、私はこの振る舞いを自分で追加したいと思います。
私はこれが素晴らしいことであり、重要であることに同意します。 しかし、それはかなりの仕事になるでしょう。
これに必要な最大のものは、堅実なテストスイートです。 Contributing.mdガイドラインを見ると、それらを見つける場所、またはそれが失敗した場合、どのメーリングリストに尋ねるべきかについてのいくつかの指針があります。 それらを掘り下げることができれば、特にH5Fを出発点として使用して指摘しているように、これを実装するためのショットがあると思います。
実際の実装のその他の重要な部分は、DOMレベル3を超えるものを実装するための適切な「level4」または「html5」フォルダーがないことです。しかし、それはしばらくの間必要だったので、試してみます。すぐに乗ります。
:+1:それは素晴らしい機能でしょう。
現在、jsdomのセットアップ後に、 https: //github.com/hyperform/hyperformをポリフィルとして追加しています。 それは素晴らしい働きをします。
わーい! 私はHyperformの作者です。 そして運が良ければ、私はすでにJSDomを使用してテスト環境をセットアップしています。
JSDomのメンテナにとって興味深い部分:適切なWebプラットフォームテストをカバーするために、JSDom内でもHyperformを使用して遊んだ。
$ 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 = [];
test/web-platform-tests/index.js
"html/semantics/forms/constraints/*.html"
テストでコメントを外します。
残念ながら、環境に配慮するためのテストケースは2つしかありませんでした。 しかし、Hyperformの機能を(何らかの方法で)JSDomに追加することに興味がある場合は、さらに作業を追加します。
a)それらのテストに合格すること。
b)高レベルAPIを除外したバージョンまたは構成をHyperformに提供する
FWIW、私はこれに非常に興味があります。 JSONスキーマに基づいてフォームをレンダリングするVueコンポーネントに取り組んでおり、送信時に検証ステータスを生成するためにValidityAPIに依存しています。 私の単体テストはJest(内部でJSDOMを使用)で実行されていますが、現在のところ、この部分をテストすることはできません。
@Boldewyn私のケースに関して何か提案があれば、喜んで受け入れます。 開始するためのガイダンスが与えられれば、これを実装するのにも役立つかもしれません:)
編集:以下の@EricHenryのソリューションを使用しましたが、機能しました。 HTMLInputElement
、 HTMLSelectElement
、およびHTMLTextAreaElement
にもcheckValidity
を設定する必要がありました(実際にはHTMLFormElement
をいじる必要はありませんでした)
JestとEnzymeを使用してReactコンポーネントをテストするときにこの問題が発生した場合は、@ fernandopasikと@Boldewynによる上記のハイパーフォームパッケージを使用してJSDOMをポリフィルすることができました。
テストファイルでは、ハイパーフォームをインストールした後、次のことを実行できます。
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);
変更が必要な他のHTMLElementや、ポリフィルする必要のある他の属性についても、同じ方法に従うことができます。
PR#2142は、ポリフィルなしで完全な制約APIを実装します
Jestのドキュメントでは、JSDOMに実装されていないモックメソッドが提案されています。 これは、テストのために環境を汚染するよりもクリーンなソリューションだと思います。
私の特定のケースでは、フォームを検証してから、フォームのclassList
を調べて、特定のクラスが存在するかどうかを確認する必要がありました。クラスが存在すると、フォームの有効性がわかります。
私の解決策は、フォームのプロパティをモックすることでした。たとえば、内部のclassList
プロパティのDOMTokenList
のネイティブ実装をモックします。
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;
})
};
});
})
次に、それを使用してプロパティをイベントハンドラーに渡しました。 event.currentTarget.form
を使用して送信ボタンからreactコンポーネントのフォームにアクセスできます
let mockClassList = new DOMTokenList();
submitBtn.simulate('click', {
currentTarget: {
form: {
checkValidity: () => false,
classList: mockClassList
}
},
preventDefault: jest.fn(),
stopPropagation: jest.fn()
})
これにより、フォームの有効性をfalseとtrueに設定し、 mockClassList
にwas-validated
クラスが存在するかどうかを毎回検査できます。
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();
参考:私はこれに酵素の浅いレンダリングを使用していますが、マウントはこのソリューションでは機能しないようです。 ただし、JSDOMに実装されていないモックメソッドに関する他の提案は、メソッドがテストされたファイルステートメントで直接実行される場合、マウントレンダリングで機能する可能性があると考える傾向があります。
input.validity
に問題がありますが、 jsdom @ 11.12では利用できません。
// 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==
有効性インターフェイスを備えたPRがマージされた日にリリースされたため、これが修正されるべきであったバージョンは11.8.0であることがわかります。 私は何かが足りないのですか?
最も参考になるコメント
:+1:それは素晴らしい機能でしょう。