是否可以创建 DOM 以供 Knockout 绑定?
Is it possible to create DOM for Knockout to bind to?
我们正在尝试找出如何将 Jest.js
与 Knockout.js
结合使用。本质上我们想创建一个 DOM 的小片段,例如:
<div class="card" data-bind="component: myCustomComponent"/>
然后可以使用自定义视图模型调用 ko.applyBindings()
,然后 DOM 片段和 Knockout 将组件加载到视图模型上,这样我们就可以做一个 Jest 快照测试。
我们正在努力解决的问题是,我如何有效地创建一个适合 ko.applyBindings()
的 DOM 片段,因为它需要一个 DOM 节点,我们'我不确定如何 create/select.
编辑
我仔细研究了@user3297291 的答案并整理了以下示例,不幸的是我无法开始工作。这是我放在一起的示例:
const jsdom = require("jsdom");
const ko = require("knockout");
describe("Knockout Test", () => {
beforeAll(() => {
ko.components.register("greeting", {
viewModel: function(params) {
//params.name = "test";
//this.message = ko.observable(`Hello ${params.name}`);
this.message = ko.observable("Hello World!");
},
template: '<span data-bind="text: message"/>'
});
});
it("test pass", (done) => {
jsdom.env(`<div class="wrapper"></div>`, [], (err, window) => {
var wrapper = window.document.querySelector(".wrapper");
var element = window.document.createElement("div");
element.setAttribute("data-bind", 'component: "greeting"');
wrapper.appendChild(element);
ko.applyBindings({ name: 'Ian' }, wrapper);
setTimeout(() => {
console.log(element.innerHTML);
expect(element.innerHTML).toMatchSnapshot();
done();
}, 10);
}
);
});
});
如果我将 element.setAttribute("data-bind", 'component: "greeting"');
修改为 element.setAttribute("data-bind", 'text: name');
那么它可以正常工作,但是加载一个组件(这是我真正想要做的)似乎总是导致空 element.innerHTML
.
这里有一个package.json要复现,我是运行 npm run jest
:
{
"name": "kotest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"jest": "jest"
},
"author": "",
"license": "ISC",
"dependencies": {
"jasmine": "^2.5.3",
"jest": "^18.1.0",
"jsdom": "^9.9.1",
"knockout": "^3.4.1"
}
}
在浏览器的 javascript 环境中,您可以通过代码创建 DOM 元素来虚拟测试敲除。例如,您可以这样做:
ko.applyBindings({}, document.createElement("div"));
这意味着您可以通过将组件绑定应用到虚拟 <div>
并检查其内容来编写任何 UI 测试。下面的示例显示了一些基础知识。
function testComponent(options, test) {
var wrapper = document.createElement("div");
// If you have a HTML string, you can do this by setting
// wrapper.innerHTML = "<div ... ></div>";
var binding = "component: { name: name, params: params }"
wrapper.setAttribute("data-bind", binding);
// Apply bindings to virtual element
ko.applyBindings(options, wrapper);
// Once done, call test with wrapper
setTimeout(test.bind(wrapper));
};
var messageEditorTest = function() {
var opts = { name: "message-editor", params: {} };
testComponent(opts, function() {
var input = this.querySelector("input"),
display = this.querySelector("span"),
vm = ko.dataFor(this.firstElementChild);
console.log("MESSAGE EDITOR TESTS:");
console.log("Has an input field:",
input !== null);
console.log("Has a display field:",
display !== null);
console.log("Length is initially zero:",
display.innerText === "0");
vm.text("Four");
console.log("Length reflects value input:",
display.innerText === "4");
});
};
// Component
ko.components.register('message-editor', {
viewModel: function(params) {
this.text = ko.observable(params && params.initialText || '');
},
template: 'Message: <input data-bind="value: text" /> '
+ '(length: <span data-bind="text: text().length"></span>)'
});
messageEditorTest();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
现在,我不确定如果您想在 Node.js 中进行测试而不借助浏览器,它是如何工作的...我 认为 您可以使用 javascript DOM 实现,例如 jsdom, or you could try firing up a "test-browser" like PhantomJS.
编辑:我 运行 使用 jsdom 进行了快速测试,一切似乎都正常
- 运行
npm install jsdom
- 运行
npm install knockout
创建一个名为 test.js
:
的文件
var jsdom = require("jsdom");
var ko = require("knockout");
jsdom.env(
'<div class="wrapper"></div>',
[],
function (err, window) {
var wrapper = window.document.querySelector(".wrapper");
var element = window.document.createElement("div");
element.setAttribute("data-bind", "text: test");
wrapper.appendChild(element);
ko.applyBindings({ test: 'My Test' }, wrapper);
console.log(element.innerHTML); // Logs "My Test"
}
);
- 运行
node test.js
- 日志
My Test
我们正在尝试找出如何将 Jest.js
与 Knockout.js
结合使用。本质上我们想创建一个 DOM 的小片段,例如:
<div class="card" data-bind="component: myCustomComponent"/>
然后可以使用自定义视图模型调用 ko.applyBindings()
,然后 DOM 片段和 Knockout 将组件加载到视图模型上,这样我们就可以做一个 Jest 快照测试。
我们正在努力解决的问题是,我如何有效地创建一个适合 ko.applyBindings()
的 DOM 片段,因为它需要一个 DOM 节点,我们'我不确定如何 create/select.
编辑
我仔细研究了@user3297291 的答案并整理了以下示例,不幸的是我无法开始工作。这是我放在一起的示例:
const jsdom = require("jsdom");
const ko = require("knockout");
describe("Knockout Test", () => {
beforeAll(() => {
ko.components.register("greeting", {
viewModel: function(params) {
//params.name = "test";
//this.message = ko.observable(`Hello ${params.name}`);
this.message = ko.observable("Hello World!");
},
template: '<span data-bind="text: message"/>'
});
});
it("test pass", (done) => {
jsdom.env(`<div class="wrapper"></div>`, [], (err, window) => {
var wrapper = window.document.querySelector(".wrapper");
var element = window.document.createElement("div");
element.setAttribute("data-bind", 'component: "greeting"');
wrapper.appendChild(element);
ko.applyBindings({ name: 'Ian' }, wrapper);
setTimeout(() => {
console.log(element.innerHTML);
expect(element.innerHTML).toMatchSnapshot();
done();
}, 10);
}
);
});
});
如果我将 element.setAttribute("data-bind", 'component: "greeting"');
修改为 element.setAttribute("data-bind", 'text: name');
那么它可以正常工作,但是加载一个组件(这是我真正想要做的)似乎总是导致空 element.innerHTML
.
这里有一个package.json要复现,我是运行 npm run jest
:
{
"name": "kotest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"jest": "jest"
},
"author": "",
"license": "ISC",
"dependencies": {
"jasmine": "^2.5.3",
"jest": "^18.1.0",
"jsdom": "^9.9.1",
"knockout": "^3.4.1"
}
}
在浏览器的 javascript 环境中,您可以通过代码创建 DOM 元素来虚拟测试敲除。例如,您可以这样做:
ko.applyBindings({}, document.createElement("div"));
这意味着您可以通过将组件绑定应用到虚拟 <div>
并检查其内容来编写任何 UI 测试。下面的示例显示了一些基础知识。
function testComponent(options, test) {
var wrapper = document.createElement("div");
// If you have a HTML string, you can do this by setting
// wrapper.innerHTML = "<div ... ></div>";
var binding = "component: { name: name, params: params }"
wrapper.setAttribute("data-bind", binding);
// Apply bindings to virtual element
ko.applyBindings(options, wrapper);
// Once done, call test with wrapper
setTimeout(test.bind(wrapper));
};
var messageEditorTest = function() {
var opts = { name: "message-editor", params: {} };
testComponent(opts, function() {
var input = this.querySelector("input"),
display = this.querySelector("span"),
vm = ko.dataFor(this.firstElementChild);
console.log("MESSAGE EDITOR TESTS:");
console.log("Has an input field:",
input !== null);
console.log("Has a display field:",
display !== null);
console.log("Length is initially zero:",
display.innerText === "0");
vm.text("Four");
console.log("Length reflects value input:",
display.innerText === "4");
});
};
// Component
ko.components.register('message-editor', {
viewModel: function(params) {
this.text = ko.observable(params && params.initialText || '');
},
template: 'Message: <input data-bind="value: text" /> '
+ '(length: <span data-bind="text: text().length"></span>)'
});
messageEditorTest();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
现在,我不确定如果您想在 Node.js 中进行测试而不借助浏览器,它是如何工作的...我 认为 您可以使用 javascript DOM 实现,例如 jsdom, or you could try firing up a "test-browser" like PhantomJS.
编辑:我 运行 使用 jsdom 进行了快速测试,一切似乎都正常
- 运行
npm install jsdom
- 运行
npm install knockout
创建一个名为
的文件test.js
:var jsdom = require("jsdom"); var ko = require("knockout"); jsdom.env( '<div class="wrapper"></div>', [], function (err, window) { var wrapper = window.document.querySelector(".wrapper"); var element = window.document.createElement("div"); element.setAttribute("data-bind", "text: test"); wrapper.appendChild(element); ko.applyBindings({ test: 'My Test' }, wrapper); console.log(element.innerHTML); // Logs "My Test" } );
- 运行
node test.js
- 日志
My Test