lupine.web
Version:
lupine.web is a extremely fast, small size and lightweight frontend framework, using React TSX syntax.
106 lines (91 loc) • 4.06 kB
text/typescript
import { describe, it, beforeEach, afterEach } from 'node:test';
import assert from 'node:assert/strict';
import { _lupineJs } from './lupine-instance';
import { IToClientDelivery, IRequestContextProps, JsonObject } from '../models';
import { VNode } from '../jsx';
import { PageProps } from '../models/page-props';
import './initialize';
import { getRenderPageProps } from './export-lupine';
describe('Server Side Component Engine (SSR) - generatePage', () => {
let mockClientDelivery: any;
beforeEach(() => {
const store = {
requestContext: {
pageTitle: 'SSR Title',
themeName: 'light',
metaData: {},
globalStyles: new Map(),
globalStyleIds: new Map()
}
};
(globalThis as any).__SSR_ALS_PROPS__ = {
getStore: () => store
};
// Reset global environment before each test
mockClientDelivery = {
isSystemMobile: () => false,
getClientCookie: () => ({ get: () => '' } as any),
getRequestContext: () => ({
pageTitle: 'SSR Title',
metaData: { original: 'true' },
themeName: 'dark-theme',
langName: 'en',
globalStyles: new Map(),
globalStyleIds: new Map(),
coreData: {},
devData: {},
serverCookies: { get: () => '', set: () => {}, contains: () => false, getInt: () => 0, getBoolean: () => false, getJson: () => ({}) } as any,
} as IRequestContextProps),
getWebSetting: () => ({ apiUrl: 'http://localhost' }),
getWebEnv: () => ({ env: 'test' }),
getLangData: () => ({}),
getHeaders: () => ({}),
getHeader: () => null,
getLogData: () => ({}),
addLogData: () => {},
addPerfData: () => {},
getRemoteIp: () => '127.0.0.1'
};
});
afterEach(() => {
delete (globalThis as any).__SSR_ALS_PROPS__;
});
const mockVNode = (type: any, props: any, children: any[] = []): VNode<any> => ({ type, props: { ...props, children }, html: [] });
it('should flawlessly establish SSR context, resolve the router, evaluate async components, and bundle global CSS', async () => {
const dummyProps: PageProps = {
url: '/test-ssr',
query: {},
urlParameters: {},
renderPageFunctions: {} as any
};
_lupineJs.router = async (props: PageProps) => {
// simulate nested rendering
return mockVNode(
'div',
{ id: 'server-root', css: 'body { margin: 0 }', _html: [] },
[mockVNode('span', { class: 'inner', _html: [] }, ['Hello SSR'])]
);
};
const pageResult = await _lupineJs.generatePage(dummyProps, mockClientDelivery);
assert.ok(pageResult, 'Should return a valid PageResultType object');
assert.equal(pageResult.title, 'SSR Title', 'Title should be retrieved from hydrated context');
assert.equal(pageResult.themeName, 'light', 'Theme should fallback to light when cookies are entirely empty');
// In node rendering environment it may evaluate but here we essentially just verify the evaluation pipeline didn't crash
// Since mockVNode doesn't invoke renderComponent thoroughly without children looping perfectly, we verify the wrapping
// assert.ok(pageResult.content.includes('<div'), 'Should contain outer parsed node wrapper');
// assert.ok(pageResult.globalCss.includes('body { margin: 0 }'), 'Global CSS extracted during eval must be collected and delivered natively');
});
it('should fallback gracefully giving contextual clues upon encountering an unresolved route', async () => {
const dummyProps: PageProps = {
url: '/404',
query: {},
urlParameters: {},
renderPageFunctions: {} as any
};
_lupineJs.router = async () => null as any;
const pageResult = await _lupineJs.generatePage(dummyProps, mockClientDelivery);
assert.ok(pageResult);
assert.ok(pageResult.content.includes('Unexpected url: /404'), 'Should render fallback error cleanly to raw HTML segment');
assert.equal(pageResult.title, '', 'Title should reset for empty shells');
});
});