Я получаю сообщение об ошибке, упомянутое в этом вопросе. Я не понимаю, почему я не могу проверить, доступен ли определенный идентификатор div. Это довольно простая проверка.
тестовое задание:
import { MyComponent } from "../src/my-component.js";
import { TestUtils } from "./test-utils.js";
describe("simple test", () => {
it("first test", async () => {
const { shadowRoot } = await TestUtils.render(MyComponent);
expect(shadowRoot.querySelector("#mydiv")).toBeTruthy();
});
});
testUtils:
export class TestUtils {
/**
* Renders a given element with provided attributes
* and returns a promise which resolves as soon as
* rendered element becomes available.
* @param {string} tag
* @param {object} attributes
* @returns {Promise<HTMLElement>}
*/
static render(tag, attributes = {}) {
TestUtils._renderToDocument(tag, attributes);
return TestUtils._waitForComponentToRender(tag);
}
/**
* Replaces document's body with provided element
* including given attributes.
* @param {string} tag
* @param {object} attributes
*/
static _renderToDocument(tag, attributes) {
const htmlAttributes = TestUtils._mapObjectToHTMLAttributes(attributes);
document.body.innerHTML = `<${tag} ${htmlAttributes}></${tag}>`;
}
/**
* Converts an object to HTML string representation of attributes.
*
* For example: `{ foo: "bar", baz: "foo" }`
* becomes `foo = "bar" baz = "foo"`
*
* @param {object} attributes
* @returns {string}
*/
static _mapObjectToHTMLAttributes(attributes) {
return Object.entries(attributes).reduce((previous, current) => {
return previous + ` ${current[0]} = "${current[1]}"`;
}, "");
}
/**
* Returns a promise which resolves as soon as
* requested element becomes available.
* @param {string} tag
* @returns {Promise<HTMLElement>}
*/
static async _waitForComponentToRender(tag) {
return new Promise(resolve => {
function requestComponent() {
const element = document.querySelector(tag);
if (element) {
resolve(element);
} else {
window.requestAnimationFrame(requestComponent);
}
}
requestComponent();
});
}
}
компонент:
const templateString = `<div id = "mydiv"><p>Hello world!</p></div>`;
const template = document.createElement("template");
template.innerHTML = templateString;
export class MyComponent extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.appendChild(template.content.cloneNode(true));
}
}
customElements.define("my-component", MyComponent);
Полные журналы:
> @ test C:\_d\WSs\basic-vanilla-webcomponent
> karma start
15 07 2019 18:47:18.412:INFO [karma-server]: Karma v4.2.0 server started at http://0.0.0.0:9876/
15 07 2019 18:47:18.418:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
15 07 2019 18:47:18.427:INFO [launcher]: Starting browser Chrome
15 07 2019 18:47:21.648:INFO [Chrome 75.0.3770 (Windows 10.0.0)]: Connected on socket y_r0BhEr4FNUaiByAAAA with id 99414473
simple test
× first test
Error: Failed to execute 'querySelector' on 'Document': 'class MyComponent extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.appendChild(template.content.cloneNode(true));
}
}' is not a valid selector.
error properties: Object({ INDEX_SIZE_ERR: 1, DOMSTRING_SIZE_ERR: 2, HIERARCHY_REQUEST_ERR: 3, WRONG_DOCUMENT_ERR: 4, INVALID_CHARACTER_ERR: 5, NO_DATA_ALLOWED_ERR: 6, NO_MODIFICATION_ALLOWED_ERR: 7, NOT_FOUND_ERR: 8, NOT_SUPPORTED_ERR: 9, INUSE_ATTRIBUTE_ERR: 10, INVALID_STATE_ERR: 11, SYNTAX_ERR: 12, INVALID_MODIFICATION_ERR: 13, NAMESPACE_ERR: 14, INVALID_ACCESS_ERR: 15, VALIDATION_ERR: 16, TYPE_MISMATCH_ERR: 17, SECURITY_ERR: 18, NETWORK_ERR: 19, ABORT_ERR: 20, URL_MISMATCH_ERR: 21, QUOTA_EXCEEDED_ERR: 22, TIMEOUT_ERR: 23, INVALID_NODE_TYPE_ERR: 24, DATA_CLONE_ERR: 25, code: 12 })
at requestComponent (test/test-utils.js:50:36)
at test/test-utils.js:57:9
at <Jasmine>
at Function._waitForComponentToRender (test/test-utils.js:48:14)
at Function.render (test/test-utils.js:12:24)
at UserContext.<anonymous> (test/my-component.test.js:6:44)
at <Jasmine>
Chrome 75.0.3770 (Windows 10.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.032 secs / 0.005 secs)
npm ERR! Test failed. See above for more details.
@Collierre, а как бы проверить, было ли оно визуализировано? Например, если я хочу получить div при запуске сервера, это будет точно document.querySelector('my-component').shadowRoot.getElementById('mydiv'). Как cacn я делаю то же самое, когда не тестирую его, тогда я могу проверить, есть ли div с именем mydiv, который был бы максимально простым модульным тестом (просто проверьте, отрендерился ли он).
Можешь вызвать TestUtils.render('my-component');? (Предполагая, что my-component является правильным тегом для MyComponent)
Спасибо, теперь исправлено! Пожалуйста, можете ли вы предоставить это как ответ и, возможно, несколько рекомендаций, если вы привыкли к модульному тестированию веб-компонентов? TestUtils я получил от medium.com/@pietmichal/how-to-test-a-web-component-b5d64d5e8bb0, и меня это заинтересовало, потому что это не зависит от библиотек (ну, на данный момент это моя главная цель, научиться кодировать и тестировать ванильные веб-компоненты). Весь мой код для обучения вы найдете в github.com/jimisdrpc/basic-vanilla-веб-компонент
@Collierre, пожалуйста, напишите свой последний комментарий как ответ, чтобы я мог выбрать окончательный ответ на мой вопрос.
Спасибо, сделано. Боюсь, я никогда не использовал веб-компоненты, поэтому не могу дать никаких рекомендаций.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Метод TestUtils.render принимает тег (строку) в качестве первого параметра, но в вашем коде вы передаете MyComponent. Это непосредственная причина ошибки.
Попробуйте вызвать TestUtils.render('my-component'); (при условии, что my-component является правильным тегом для MyComponent).
Метод
TestUtils.renderпринимает тег (строку) в качестве первого параметра, но в вашем коде вы передаете MyComponent. Это непосредственная причина ошибки.