Error: "Router must be defined in href" stenciljs router-v2 testing
Error: "Router must be defined in href" stenciljs router-v2 testing
我正在尝试测试模板组件。
我使用“stencil-router-v2”。
我的组件的渲染方法中有一个 link 和“href”函数:
<a {...href(`/news/${this.page}`)} class="btn btn--primary btn--medium btn--view">View</a>
当我尝试测试它时,我看到下一个错误:“路由器必须在 href 中定义”。
你能给我解释一下如何正确测试“href”功能吗?我需要写什么测试代码才能通过测试?
我的组件代码:
import { Component, h, Prop, Event, EventEmitter } from '@stencil/core';
import { href } from 'stencil-router-v2';
import state from '../store/store';
@Component({
tag: 'my-news-page',
styleUrl: 'my-news-page.scss'
})
export class MyNewsPage {
@Prop() page: string;
@Prop() news;
@Event() newsDeleted: EventEmitter;
deleteNewsHandler = id => {
this.newsDeleted.emit(id);
}
componentWillRender() {
this.news = state.newsList.find(news => news.id === +this.page);
}
render() {
return (
<section>
<h3>{this.news.title}</h3>
<p>{this.news.body}</p>
<button class="btn btn--primary btn--medium btn--delete" onClick={() => this.deleteNewsHandler(this.news.id)}>Delete</button>
<a {...href(`/news/${this.page}`)} class="btn btn--primary btn--medium btn--view">View</a>
</section>
)
}
}
我的测试代码:
import { newSpecPage } from '@stencil/core/testing';
import { MyNewsPage } from '../my-news-page';
import state from '../../store/store';
state.newsList = [
{ id: 1, title: 'title1', body: 'content1' },
{ id: 2, title: 'title2', body: 'content2' },
{ id: 3, title: 'title3', body: 'content3' }
];
const ID = '1';
describe('my-news-page', () => {
it('should display remaining items', () => {
let page = new MyNewsPage();
page.news = state.newsList;
expect(page.news.length).toEqual(3);
});
it('renders', async () => {
const page = await newSpecPage({
components: [MyNewsPage],
html: '<div></div>'
});
let cmp = page.doc.createElement('my-news-page');
(cmp as any).page = ID;
(cmp as any).news = state.newsList.find(news => news.id === +cmp.page);
page.root.appendChild(cmp);
await page.waitForChanges();
expect(page.root).toMatchSnapshot();
});
});
航站楼:
my-news-page
✓ should display remaining items (7 ms)
✕ renders (37 ms)
● my-news-page › renders
Router must be defined in href
28 | <p>{this.news.body}</p>
29 | <button class="btn btn--primary btn--medium btn--delete" onClick={() => this.deleteNewsHandler(this.news.id)}>Delete</button>
> 30 | {<a {...href(`/news/${this.page}`)} class="btn btn--primary btn--medium btn--view">View</a>}
| ^
31 | </section>
32 | )
33 | }
at Object.href (node_modules/stencil-router-v2/dist/index.js:106:15)
at MyNewsPage.render (src/components/my-news-page/my-news-page.tsx:30:17)
at callRender (node_modules/@stencil/core/internal/testing/index.js:421:46)
at updateComponent (node_modules/@stencil/core/internal/testing/index.js:402:247)
at node_modules/@stencil/core/internal/testing/index.js:397:22
at then (node_modules/@stencil/core/internal/testing/index.js:459:47)
at dispatchHooks (node_modules/@stencil/core/internal/testing/index.js:397:7)
at a (node_modules/@stencil/core/internal/testing/index.js:387:18)
at a (node_modules/@stencil/core/internal/testing/index.js:25:17)```
我认为您可以创建一个路由器,然后使用规范页面的 template
选项(您还必须将测试文件的扩展名更改为 .tsx
并导入 h
):
import { Fragment, h, newSpecPage } from '@stencil/core/testing';
import { createRouter } from 'stencil-router-v2';
const Router = createRouter();
// ...
describe('my-news-page', () => {
it('renders', async () => {
const page = await newSpecPage({
components: [MyNewsPage],
template: () => (
<Fragment>
<Router>
{/* You might have to define routes here, so probably
best to import your app's router instead. */}
</Router>
<my-news-page
page={ID}
news={state.newsList.find(news +> news.id === ID)
/>
</Fragment>
),
});
await page.waitForChanges();
expect(page.root).toMatchSnapshot();
});
});
使用 template
还可以简化道具设置等。请注意,这需要是一个 函数 返回 JSX。 Fragment
仅适用于较新的 Stencil 版本 afaik。
我应该在此处将 const Router = createRouter();
添加到我的代码中:
import { createRouter } from 'stencil-router-v2';
import { MyNewsPage } from '../my-news-page';
import state from '../../store/store';
state.newsList = [
{ id: 1, title: 'title1', body: 'content1' },
{ id: 2, title: 'title2', body: 'content2' },
{ id: 3, title: 'title3', body: 'content3' }
];
const ID = '1';
describe('my-news-page', () => {
it('should display remaining items', () => {
let page = new MyNewsPage();
page.news = state.newsList;
expect(page.news.length).toEqual(3);
});
it('renders', async () => {
const page = await newSpecPage({
components: [MyNewsPage],
html: '<div></div>'
});
const Router = createRouter();
let cmp = page.doc.createElement('my-news-page');
(cmp as any).page = ID;
(cmp as any).news = state.newsList.find(news => news.id === +cmp.page);
page.root.appendChild(cmp);
await page.waitForChanges();
expect(page.root).toMatchSnapshot();
});
});
现在我的测试工作正常。
我正在尝试测试模板组件。
我使用“stencil-router-v2”。
我的组件的渲染方法中有一个 link 和“href”函数:
<a {...href(`/news/${this.page}`)} class="btn btn--primary btn--medium btn--view">View</a>
当我尝试测试它时,我看到下一个错误:“路由器必须在 href 中定义”。
你能给我解释一下如何正确测试“href”功能吗?我需要写什么测试代码才能通过测试?
我的组件代码:
import { Component, h, Prop, Event, EventEmitter } from '@stencil/core';
import { href } from 'stencil-router-v2';
import state from '../store/store';
@Component({
tag: 'my-news-page',
styleUrl: 'my-news-page.scss'
})
export class MyNewsPage {
@Prop() page: string;
@Prop() news;
@Event() newsDeleted: EventEmitter;
deleteNewsHandler = id => {
this.newsDeleted.emit(id);
}
componentWillRender() {
this.news = state.newsList.find(news => news.id === +this.page);
}
render() {
return (
<section>
<h3>{this.news.title}</h3>
<p>{this.news.body}</p>
<button class="btn btn--primary btn--medium btn--delete" onClick={() => this.deleteNewsHandler(this.news.id)}>Delete</button>
<a {...href(`/news/${this.page}`)} class="btn btn--primary btn--medium btn--view">View</a>
</section>
)
}
}
我的测试代码:
import { newSpecPage } from '@stencil/core/testing';
import { MyNewsPage } from '../my-news-page';
import state from '../../store/store';
state.newsList = [
{ id: 1, title: 'title1', body: 'content1' },
{ id: 2, title: 'title2', body: 'content2' },
{ id: 3, title: 'title3', body: 'content3' }
];
const ID = '1';
describe('my-news-page', () => {
it('should display remaining items', () => {
let page = new MyNewsPage();
page.news = state.newsList;
expect(page.news.length).toEqual(3);
});
it('renders', async () => {
const page = await newSpecPage({
components: [MyNewsPage],
html: '<div></div>'
});
let cmp = page.doc.createElement('my-news-page');
(cmp as any).page = ID;
(cmp as any).news = state.newsList.find(news => news.id === +cmp.page);
page.root.appendChild(cmp);
await page.waitForChanges();
expect(page.root).toMatchSnapshot();
});
});
航站楼:
my-news-page
✓ should display remaining items (7 ms)
✕ renders (37 ms)
● my-news-page › renders
Router must be defined in href
28 | <p>{this.news.body}</p>
29 | <button class="btn btn--primary btn--medium btn--delete" onClick={() => this.deleteNewsHandler(this.news.id)}>Delete</button>
> 30 | {<a {...href(`/news/${this.page}`)} class="btn btn--primary btn--medium btn--view">View</a>}
| ^
31 | </section>
32 | )
33 | }
at Object.href (node_modules/stencil-router-v2/dist/index.js:106:15)
at MyNewsPage.render (src/components/my-news-page/my-news-page.tsx:30:17)
at callRender (node_modules/@stencil/core/internal/testing/index.js:421:46)
at updateComponent (node_modules/@stencil/core/internal/testing/index.js:402:247)
at node_modules/@stencil/core/internal/testing/index.js:397:22
at then (node_modules/@stencil/core/internal/testing/index.js:459:47)
at dispatchHooks (node_modules/@stencil/core/internal/testing/index.js:397:7)
at a (node_modules/@stencil/core/internal/testing/index.js:387:18)
at a (node_modules/@stencil/core/internal/testing/index.js:25:17)```
我认为您可以创建一个路由器,然后使用规范页面的 template
选项(您还必须将测试文件的扩展名更改为 .tsx
并导入 h
):
import { Fragment, h, newSpecPage } from '@stencil/core/testing';
import { createRouter } from 'stencil-router-v2';
const Router = createRouter();
// ...
describe('my-news-page', () => {
it('renders', async () => {
const page = await newSpecPage({
components: [MyNewsPage],
template: () => (
<Fragment>
<Router>
{/* You might have to define routes here, so probably
best to import your app's router instead. */}
</Router>
<my-news-page
page={ID}
news={state.newsList.find(news +> news.id === ID)
/>
</Fragment>
),
});
await page.waitForChanges();
expect(page.root).toMatchSnapshot();
});
});
使用 template
还可以简化道具设置等。请注意,这需要是一个 函数 返回 JSX。 Fragment
仅适用于较新的 Stencil 版本 afaik。
我应该在此处将 const Router = createRouter();
添加到我的代码中:
import { createRouter } from 'stencil-router-v2';
import { MyNewsPage } from '../my-news-page';
import state from '../../store/store';
state.newsList = [
{ id: 1, title: 'title1', body: 'content1' },
{ id: 2, title: 'title2', body: 'content2' },
{ id: 3, title: 'title3', body: 'content3' }
];
const ID = '1';
describe('my-news-page', () => {
it('should display remaining items', () => {
let page = new MyNewsPage();
page.news = state.newsList;
expect(page.news.length).toEqual(3);
});
it('renders', async () => {
const page = await newSpecPage({
components: [MyNewsPage],
html: '<div></div>'
});
const Router = createRouter();
let cmp = page.doc.createElement('my-news-page');
(cmp as any).page = ID;
(cmp as any).news = state.newsList.find(news => news.id === +cmp.page);
page.root.appendChild(cmp);
await page.waitForChanges();
expect(page.root).toMatchSnapshot();
});
});
现在我的测试工作正常。