@v4fire/client
Version:
V4Fire client core library
160 lines (130 loc) • 4.54 kB
text/typescript
/*!
* V4Fire Client Core
* https://github.com/V4Fire/Client
*
* Released under the MIT license
* https://github.com/V4Fire/Client/blob/master/LICENSE
*/
import type { JSHandle, Page } from 'playwright';
import type bDynamicPage from 'base/b-dynamic-page/b-dynamic-page';
import test from 'tests/config/unit/test';
import { Component } from 'tests/helpers';
test.describe('<b-dynamic-page>', () => {
test.beforeEach(({demoPage}) => demoPage.goto());
test('should reuse the page component instance if the page does not change and the page key is not specified', async ({page}) => {
const target = await renderDynamicPage(
page,
{
keepAlive: true,
include: (_, route) => Object.fastHash(route.params)
},
{
page1: {
path: '/page-1/:id',
component: 'p-v4-dynamic-page1'
}
}
);
const isSamePageComponent = await target.evaluate(async (ctx) => {
await ctx.router?.push('page1', {params: {id: 1}});
const page1Component = ctx.unsafe.$refs.component?.[0];
const routeTransition = ctx.unsafe.async.promisifyOnce(ctx.r, 'transition');
await ctx.router?.push('page1', {params: {id: 2}});
await routeTransition;
const page2Component = ctx.unsafe.$refs.component?.[0];
return page1Component === page2Component;
});
test.expect(isSamePageComponent).toBe(true);
});
test('should create a new page component if the page does not change but the page key changes', async ({page}) => {
const target = await renderDynamicPage(
page,
{
keepAlive: true,
eventConverter: (route) => ([route?.meta?.component ?? null, Object.fastHash(route?.params)]),
include: (_, route) => Object.fastHash(route.params)
},
{
page1: {
path: '/page-1/:id',
component: 'p-v4-dynamic-page1'
}
}
);
const isSamePageComponent = await target.evaluate(async (ctx) => {
await ctx.router?.push('page1', {params: {id: 1}});
const page1Component = ctx.unsafe.$refs.component?.[0];
const routeTransition = ctx.unsafe.async.promisifyOnce(ctx.r, 'transition');
await ctx.router?.push('page1', {params: {id: 2}});
await routeTransition;
const page2Component = ctx.unsafe.$refs.component?.[0];
return page1Component === page2Component;
});
test.expect(isSamePageComponent).toBe(false);
});
test('should emit the `beforeSwitchPage` event before removing the page element', async ({page}) => {
const target = await renderDynamicPage(page, {keepAlive: true});
const count = await page.evaluateHandle(() => ({value: 0}));
await target.evaluate((ctx, count) => {
ctx.watch('rootEmitter:onBeforeSwitchPage', () => {
count.value++;
});
}, count);
await target.evaluate(async (ctx) => {
await ctx.router?.push('page1');
await ctx.router?.push('page2');
});
const calls = await count.evaluate(({value}) => value);
test.expect(calls).toBe(1);
});
test('should save and apply scroll to the cached page element for the children', async ({page}) => {
const
scrollOptions = {left: 200, top: 200},
target = await renderDynamicPage(page, {keepAlive: true});
await target.evaluate((ctx) => ctx.router?.push('page1'));
const scroll = await page.getByTestId('scrollable');
await scroll.evaluate((el, [{top, left}]) => el.scrollTo({top, left}), [scrollOptions]);
await target.evaluate((ctx) => ctx.router?.push('page2'));
await test.expect(scroll).toBeHidden();
await target.evaluate((ctx) => ctx.router?.push('page1'));
await test.expect(scroll.evaluate(scrollAfterRequestAnimationFrame)).resolves.toEqual(scrollOptions);
function scrollAfterRequestAnimationFrame(el: Element): Promise<{top: number; left: number}> {
return new Promise((resolve) => {
requestAnimationFrame(() => resolve({top: el.scrollTop, left: el.scrollLeft}));
});
}
});
});
/**
* Creates the `bRouter`, renders the `bDynamicPage` component and returns Promise<JSHandle>
*
* @param page
* @param attrs
* @param routesConfig
*/
export async function renderDynamicPage(
page: Page,
attrs: RenderComponentsVnodeParams['attrs'] = {},
routesConfig?: Dictionary
): Promise<JSHandle<bDynamicPage>> {
await Component.createComponent(page, 'b-router', {
attrs: {
routes: routesConfig ?? {
page1: {
path: '/page-1',
component: 'p-v4-dynamic-page1'
},
page2: {
path: '/page-2',
component: 'p-v4-dynamic-page2'
}
}
}
});
return Object.cast(Component.createComponent(page, 'b-dynamic-page', {
attrs: {
id: 'target',
...attrs
}
}));
}