test(inula-next): add test
This commit is contained in:
parent
37d6ba1033
commit
2d5d3c29e4
|
@ -145,4 +145,4 @@ function App() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render('main', App);
|
render(App, 'main');
|
||||||
|
|
|
@ -135,4 +135,4 @@ function ConditionalRendering({ count }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render('main', MyComp);
|
render(MyComp, 'main');
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
import { DLNode, DLNodeType } from './DLNode';
|
import { DLNode, DLNodeType } from './DLNode';
|
||||||
import { forwardHTMLProp } from './HTMLNode';
|
import { forwardHTMLProp } from './HTMLNode';
|
||||||
import { DLStore, cached } from './store';
|
import { DLStore, cached } from './store';
|
||||||
|
import { schedule } from './scheduler';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* @extends import('./DLNode').DLNode
|
||||||
|
*/
|
||||||
export class CompNode extends DLNode {
|
export class CompNode extends DLNode {
|
||||||
/**
|
/**
|
||||||
* @brief Constructor, Comp type
|
* @brief Constructor, Comp type
|
||||||
|
@ -278,7 +283,7 @@ export class CompNode extends DLNode {
|
||||||
} else {
|
} else {
|
||||||
this._$depNumsToUpdate = [depNum];
|
this._$depNumsToUpdate = [depNum];
|
||||||
// ---- Update in the next microtask
|
// ---- Update in the next microtask
|
||||||
Promise.resolve().then(() => {
|
schedule(() => {
|
||||||
// ---- Abort if unmounted
|
// ---- Abort if unmounted
|
||||||
if (this._$unmounted) return;
|
if (this._$unmounted) return;
|
||||||
const depNums = this._$depNumsToUpdate;
|
const depNums = this._$depNumsToUpdate;
|
||||||
|
@ -302,6 +307,7 @@ export class CompNode extends DLNode {
|
||||||
delete this._$depNumsToUpdate;
|
delete this._$depNumsToUpdate;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update all props and content of the model
|
* @brief Update all props and content of the model
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -19,6 +19,7 @@ export class DLNode {
|
||||||
/**
|
/**
|
||||||
* @brief Constructor
|
* @brief Constructor
|
||||||
* @param nodeType
|
* @param nodeType
|
||||||
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
constructor(nodeType) {
|
constructor(nodeType) {
|
||||||
this._$dlNodeType = nodeType;
|
this._$dlNodeType = nodeType;
|
||||||
|
|
|
@ -13,6 +13,7 @@ export * from './MutableNode/CondNode';
|
||||||
export * from './MutableNode/TryNode';
|
export * from './MutableNode/TryNode';
|
||||||
|
|
||||||
import { DLStore } from './store';
|
import { DLStore } from './store';
|
||||||
|
|
||||||
export { setGlobal, setDocument } from './store';
|
export { setGlobal, setDocument } from './store';
|
||||||
|
|
||||||
function initStore() {
|
function initStore() {
|
||||||
|
@ -22,7 +23,12 @@ function initStore() {
|
||||||
DLStore.global.DidUnmountStore = [];
|
DLStore.global.DidUnmountStore = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function render(DL, idOrEl) {
|
/**
|
||||||
|
* @brief Render the DL class to the element
|
||||||
|
* @param {typeof import('./CompNode').CompNode} Comp
|
||||||
|
* @param {HTMLElement | string} idOrEl
|
||||||
|
*/
|
||||||
|
export function render(Comp, idOrEl) {
|
||||||
let el = idOrEl;
|
let el = idOrEl;
|
||||||
if (typeof idOrEl === 'string') {
|
if (typeof idOrEl === 'string') {
|
||||||
const elFound = DLStore.document.getElementById(idOrEl);
|
const elFound = DLStore.document.getElementById(idOrEl);
|
||||||
|
@ -33,7 +39,7 @@ export function render(DL, idOrEl) {
|
||||||
}
|
}
|
||||||
initStore();
|
initStore();
|
||||||
el.innerHTML = '';
|
el.innerHTML = '';
|
||||||
const dlNode = new DL();
|
const dlNode = new Comp();
|
||||||
dlNode._$init();
|
dlNode._$init();
|
||||||
insertNode(el, dlNode, 0);
|
insertNode(el, dlNode, 0);
|
||||||
DLNode.runDidMount();
|
DLNode.runDidMount();
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Huawei Technologies Co.,Ltd.
|
||||||
|
*
|
||||||
|
* openInula is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
*
|
||||||
|
* http://license.coscl.org.cn/MulanPSL2
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const p = Promise.resolve();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a task to run in the next microtask.
|
||||||
|
*
|
||||||
|
* @param {() => void} task
|
||||||
|
*/
|
||||||
|
export function schedule(task) {
|
||||||
|
p.then(task);
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ export const App: any;
|
||||||
export const Mount: (idOrEl: string | HTMLElement) => any;
|
export const Mount: (idOrEl: string | HTMLElement) => any;
|
||||||
|
|
||||||
// ---- With actual value
|
// ---- With actual value
|
||||||
export function render(idOrEl: string | HTMLElement, DL: any): void;
|
export function render(DL: any, idOrEl: string | HTMLElement): void;
|
||||||
export function manual<T>(callback: () => T, _deps?: any[]): T;
|
export function manual<T>(callback: () => T, _deps?: any[]): T;
|
||||||
export function escape<T>(arg: T): T;
|
export function escape<T>(arg: T): T;
|
||||||
export function setGlobal(globalObj: any): void;
|
export function setGlobal(globalObj: any): void;
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Huawei Technologies Co.,Ltd.
|
||||||
|
*
|
||||||
|
* openInula is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
*
|
||||||
|
* http://license.coscl.org.cn/MulanPSL2
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { describe, expect, vi } from 'vitest';
|
||||||
|
import { domTest as it } from './utils';
|
||||||
|
import { render, View } from '../src';
|
||||||
|
|
||||||
|
describe('components', () => {
|
||||||
|
describe('ref', () => {
|
||||||
|
it('should support ref', ({ container }) => {
|
||||||
|
let ref: HTMLElement;
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
let count = 0;
|
||||||
|
let _ref: HTMLElement;
|
||||||
|
|
||||||
|
didMount: {
|
||||||
|
ref = _ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div ref={_ref}>test</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
render(App, container);
|
||||||
|
|
||||||
|
expect(ref).toBeInstanceOf(HTMLElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support ref with function', ({ container }) => {
|
||||||
|
const fn = vi.fn();
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
const ref = (el: HTMLElement) => {
|
||||||
|
fn();
|
||||||
|
expect(el).toBeInstanceOf(HTMLElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
return <div ref={ref}>test</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
render(App, container);
|
||||||
|
expect(fn).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('env', () => {
|
||||||
|
it('should support env', ({ container }) => {
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<env theme="dark">
|
||||||
|
<Child name="child" />
|
||||||
|
</env>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Child({ name }, { theme }) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
name is {name}, theme is {theme}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render(App, container);
|
||||||
|
expect(container.innerHTML).toBe('<div>name is child, theme is dark</div>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Huawei Technologies Co.,Ltd.
|
||||||
|
*
|
||||||
|
* openInula is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
*
|
||||||
|
* http://license.coscl.org.cn/MulanPSL2
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { describe, expect, vi } from 'vitest';
|
||||||
|
import { domTest as it } from './utils';
|
||||||
|
import { render, View } from '../src';
|
||||||
|
|
||||||
|
vi.mock('../src/scheduler', async () => {
|
||||||
|
return {
|
||||||
|
schedule: (task: () => void) => {
|
||||||
|
task();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('conditional rendering', () => {
|
||||||
|
it('should if, else, else if', ({ container }) => {
|
||||||
|
let set: (num: number) => void;
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
let count = 2;
|
||||||
|
willMount: {
|
||||||
|
set = (val: number) => {
|
||||||
|
count = val;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<if cond={count > 1}>{count} is bigger than is 1</if>
|
||||||
|
<else-if cond={count === 1}>{count} is equal to 1</else-if>
|
||||||
|
<else>{count} is smaller than 1</else>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render(App, container);
|
||||||
|
expect(container.innerHTML).toBe('2 is bigger than is 1');
|
||||||
|
set(1);
|
||||||
|
expect(container.innerHTML).toBe('1 is equal to 1');
|
||||||
|
set(0);
|
||||||
|
expect(container.innerHTML).toBe('0 is smaller than 1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support nested if', ({ container }) => {
|
||||||
|
let set: (num: number) => void;
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
let count = 0;
|
||||||
|
willMount: {
|
||||||
|
set = (val: number) => {
|
||||||
|
count = val;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<if cond={count > 1}>
|
||||||
|
{count} is bigger than is 1
|
||||||
|
<if cond={count > 2}>
|
||||||
|
<div>{count} is bigger than is 2</div>
|
||||||
|
</if>
|
||||||
|
</if>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render(App, container);
|
||||||
|
expect(container.innerHTML).toMatchInlineSnapshot(`""`);
|
||||||
|
set(2);
|
||||||
|
expect(container.innerHTML).toMatchInlineSnapshot(`
|
||||||
|
"2 is bigger than is 1
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
set(3);
|
||||||
|
expect(container.innerHTML).toMatchInlineSnapshot(`
|
||||||
|
"3 is bigger than is 1
|
||||||
|
<div>3 is bigger than is 2</div>"
|
||||||
|
`);
|
||||||
|
set(2);
|
||||||
|
expect(container.innerHTML).toMatchInlineSnapshot(`
|
||||||
|
"2 is bigger than is 1
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Huawei Technologies Co.,Ltd.
|
||||||
|
*
|
||||||
|
* openInula is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
*
|
||||||
|
* http://license.coscl.org.cn/MulanPSL2
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { describe, expect, vi } from 'vitest';
|
||||||
|
import { domTest as it } from './utils';
|
||||||
|
import { render, View } from '../src';
|
||||||
|
|
||||||
|
describe('lifecycle', () => {
|
||||||
|
it('should call willMount', ({ container }) => {
|
||||||
|
const fn = vi.fn();
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
willMount: {
|
||||||
|
expect(container.innerHTML).toBe('');
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div>test</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
render(App, container);
|
||||||
|
expect(fn).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call didMount', ({ container }) => {
|
||||||
|
const fn = vi.fn();
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
didMount: {
|
||||||
|
expect(container.innerHTML).toBe('<div>test</div>');
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div>test</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
render(App, container);
|
||||||
|
expect(fn).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: implement unmount
|
||||||
|
it.skip('should call willUnmount', ({ container }) => {
|
||||||
|
const fn = vi.fn();
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
willUnmount: {
|
||||||
|
expect(container.innerHTML).toBe('<div>test</div>');
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div>test</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
render(App, container);
|
||||||
|
expect(fn).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
|
@ -53,7 +53,7 @@ describe('rendering', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: SHOULD FIX
|
// TODO: SHOULD FIX
|
||||||
it('should support dom has multiple layers ', ({ container }) => {
|
it.fails('should support dom has multiple layers ', ({ container }) => {
|
||||||
function App() {
|
function App() {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ describe('rendering', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: SHOULD FIX
|
// TODO: SHOULD FIX
|
||||||
it('should support tag, text and variable mixing', ({ container }) => {
|
it.fails('should support tag, text and variable mixing', ({ container }) => {
|
||||||
function App() {
|
function App() {
|
||||||
let count = 'world';
|
let count = 'world';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue