From 5bed0317be0e9374a5adb8e626e21cf5753da829 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AD=99=E4=B8=80=E5=86=B0?=
<14512567+sunyibing@user.noreply.gitee.com>
Date: Fri, 23 Aug 2024 11:55:19 +0800
Subject: [PATCH] test: add API-2.0 tests
---
packages/inula-next/test/conditional.test.tsx | 117 ++++
packages/inula-next/test/context.test.tsx | 126 ++++
packages/inula-next/test/customHook.test.tsx | 356 ++++++++++++
packages/inula-next/test/event.test.tsx | 543 ++++++++++++++++++
packages/inula-next/test/for.test.tsx | 73 ++-
packages/inula-next/test/jsxSlice.test.tsx | 274 +++++++++
packages/inula-next/test/props.test.tsx | 190 ++++++
packages/inula-next/test/rendering.test.tsx | 20 +
8 files changed, 1698 insertions(+), 1 deletion(-)
create mode 100644 packages/inula-next/test/event.test.tsx
diff --git a/packages/inula-next/test/conditional.test.tsx b/packages/inula-next/test/conditional.test.tsx
index ab2b4b41..0724ddf6 100644
--- a/packages/inula-next/test/conditional.test.tsx
+++ b/packages/inula-next/test/conditional.test.tsx
@@ -146,3 +146,120 @@ describe('conditional rendering', () => {
expect(container.innerHTML).toMatchInlineSnapshot(`"
hello world 2 "`);
});
});
+
+describe('additional conditional rendering tests', () => {
+ it('Should correctly render content based on a single if condition', ({ container }) => {
+ let set: (num: number) => void;
+
+ function App() {
+ let count = 0;
+ set = (val: number) => {
+ count = val;
+ };
+ return (
+
+ 5}>Count is greater than 5
+
+ );
+ }
+
+ render(App, container);
+ expect(container.innerHTML).toBe('
');
+ set(6);
+ expect(container.innerHTML).toBe('Count is greater than 5
');
+ });
+
+ it('Should correctly render content based on if-else conditions', ({ container }) => {
+ let set: (num: number) => void;
+
+ function App() {
+ let count = 0;
+ set = (val: number) => {
+ count = val;
+ };
+ return (
+
+ Count is even
+ Count is odd
+
+ );
+ }
+
+ render(App, container);
+ expect(container.innerHTML).toBe('Count is even
');
+ set(1);
+ expect(container.innerHTML).toBe('Count is odd
');
+ set(2);
+ expect(container.innerHTML).toBe('Count is even
');
+ });
+
+ it('Should correctly render content based on if-else-if-else conditions', ({ container }) => {
+ let set: (num: number) => void;
+
+ function App() {
+ let count = 0;
+ set = (val: number) => {
+ count = val;
+ };
+ return (
+
+ 10}>Count is greater than 10
+ 5}>Count is greater than 5 but not greater than 10
+ 0}>Count is greater than 0 but not greater than 5
+ Count is 0 or negative
+
+ );
+ }
+
+ render(App, container);
+ expect(container.innerHTML).toBe('Count is 0 or negative
');
+ set(3);
+ expect(container.innerHTML).toBe('Count is greater than 0 but not greater than 5
');
+ set(7);
+ expect(container.innerHTML).toBe('Count is greater than 5 but not greater than 10
');
+ set(11);
+ expect(container.innerHTML).toBe('Count is greater than 10
');
+ });
+
+ it('Should correctly handle nested conditional rendering', ({ container }) => {
+ let set: (obj: { x: number; y: number }) => void;
+
+ function App() {
+ let state = { x: 0, y: 0 };
+ set = (val: { x: number; y: number }) => {
+ state = val;
+ };
+ return (
+
+
0}>
+ X is positive
+ 0}>
+ Both X and Y are positive
+
+
+ X is positive but Y is not
+
+
+
+ X is not positive
+ 0}>
+ X is not positive but Y is
+
+
+ Neither X nor Y are positive
+
+
+
+ );
+ }
+
+ render(App, container);
+ expect(container.innerHTML).toBe('X is not positive
Neither X nor Y are positive
');
+ set({ x: 1, y: 0 });
+ expect(container.innerHTML).toBe('X is positive
X is positive but Y is not
');
+ set({ x: 1, y: 1 });
+ expect(container.innerHTML).toBe('X is positive
Both X and Y are positive
');
+ set({ x: 0, y: 1 });
+ expect(container.innerHTML).toBe('X is not positive
X is not positive but Y is
');
+ });
+});
diff --git a/packages/inula-next/test/context.test.tsx b/packages/inula-next/test/context.test.tsx
index 5b24c8ad..4541bbb8 100644
--- a/packages/inula-next/test/context.test.tsx
+++ b/packages/inula-next/test/context.test.tsx
@@ -219,4 +219,130 @@ describe('context', () => {
container.querySelector('button').click();
expect(container.querySelector('div').textContent).toBe('Count: 1');
});
+ it('Should correctly create and provide context', ({ container }) => {
+ const ThemeContext = createContext('light');
+
+ function App() {
+ return (
+
+
+
+ );
+ }
+
+ function Child() {
+ const { theme } = useContext(ThemeContext);
+ return Current theme: {theme}
;
+ }
+
+ render(App, container);
+ expect(container.innerHTML).toBe('Current theme: dark
');
+ });
+
+ it('Should correctly consume context in child components', ({ container }) => {
+ const UserContext = createContext({ name: '', age: 0 });
+
+ function App() {
+ return (
+
+
+
+ );
+ }
+
+ function Parent() {
+ return (
+
+
+
+
+ );
+ }
+
+ function Child1() {
+ const { name } = useContext(UserContext);
+ return Name: {name}
;
+ }
+
+ function Child2() {
+ const { age } = useContext(UserContext);
+ return Age: {age}
;
+ }
+
+ render(App, container);
+ expect(container.innerHTML).toBe('');
+ });
+
+ it('Should correctly update context and re-render consumers', ({ container }) => {
+ const CountContext = createContext(0);
+
+ function App() {
+ let count = 0;
+ const increment = () => {
+ count += 1;
+ };
+
+ return (
+
+
+ Increment
+
+ );
+ }
+
+ function Counter() {
+ const { count } = useContext(CountContext);
+ return Count: {count}
;
+ }
+
+ render(App, container);
+ expect(container.querySelector('div').textContent).toBe('Count: 0');
+
+ container.querySelector('button').click();
+ expect(container.querySelector('div').textContent).toBe('Count: 1');
+ });
+
+ it('Should handle nested contexts correctly', ({ container }) => {
+ const ThemeContext = createContext('light');
+ const LanguageContext = createContext('en');
+
+ function App() {
+ return (
+
+
+
+
+
+ );
+ }
+
+ function Child() {
+ const { theme } = useContext(ThemeContext);
+ const { language } = useContext(LanguageContext);
+ return (
+
+ Theme: {theme}, Language: {language}
+
+ );
+ }
+
+ render(App, container);
+ expect(container.innerHTML).toBe('Theme: dark, Language: fr
');
+ });
+
+ it('Should use default value when no provider is present', ({ container }) => {
+ const DefaultContext = createContext({ message: 'Default message' });
+
+ function App() {
+ return ;
+ }
+
+ function Child() {
+ const { message } = useContext(DefaultContext);
+ return {message}
;
+ }
+
+ render(App, container);
+ expect(container.innerHTML).toBe('Default message
');
+ });
});
diff --git a/packages/inula-next/test/customHook.test.tsx b/packages/inula-next/test/customHook.test.tsx
index 81cc46cf..b8a2e970 100644
--- a/packages/inula-next/test/customHook.test.tsx
+++ b/packages/inula-next/test/customHook.test.tsx
@@ -366,3 +366,359 @@ describe('Custom Hook Tests', () => {
});
});
});
+
+describe('Hook and Watch Combined Tests', () => {
+ it('should update watched value when hook state changes', ({ container }) => {
+ let setCount;
+ function useCounter(initial = 0) {
+ let count = initial;
+ setCount = n => {
+ count = n;
+ };
+ return { count };
+ }
+
+ function TestComponent() {
+ const { count } = useCounter(0);
+ let watchedCount = 0;
+
+ watch(() => {
+ watchedCount = count * 2;
+ });
+
+ return {watchedCount}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('0
');
+ setCount(5);
+ expect(container.innerHTML).toBe('10
');
+ });
+
+ it('should handle multiple watches in a custom hook', ({ container }) => {
+ let setX, setY;
+ function usePosition() {
+ let x = 0,
+ y = 0;
+ setX = newX => {
+ x = newX;
+ };
+ setY = newY => {
+ y = newY;
+ };
+
+ let position = '';
+ watch(() => {
+ position = `(${x},${y})`;
+ });
+
+ let quadrant = 0;
+ watch(() => {
+ quadrant = x >= 0 && y >= 0 ? 1 : x < 0 && y >= 0 ? 2 : x < 0 && y < 0 ? 3 : 4;
+ });
+
+ return { position, quadrant };
+ }
+
+ function TestComponent() {
+ const { position, quadrant } = usePosition();
+ return (
+
+ {position} Q{quadrant}
+
+ );
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('(0,0) Q1
');
+ setX(-5);
+ setY(10);
+ expect(container.innerHTML).toBe('(-5,10) Q2
');
+ });
+
+ it('should correctly handle watch dependencies in hooks', ({ container }) => {
+ let setItems;
+ function useFilteredList(initialItems = []) {
+ let items = initialItems;
+ setItems = newItems => {
+ items = newItems;
+ };
+
+ let evenItems = [];
+ let oddItems = [];
+
+ watch(() => {
+ evenItems = items.filter(item => item % 2 === 0);
+ });
+
+ watch(() => {
+ oddItems = items.filter(item => item % 2 !== 0);
+ });
+
+ return { evenItems, oddItems };
+ }
+
+ function TestComponent() {
+ const { evenItems, oddItems } = useFilteredList([1, 2, 3, 4, 5]);
+ return (
+
+ Even: {evenItems.join(',')} Odd: {oddItems.join(',')}
+
+ );
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('Even: 2,4 Odd: 1,3,5
');
+ setItems([2, 4, 6, 8, 10]);
+ expect(container.innerHTML).toBe('Even: 2,4,6,8,10 Odd:
');
+ });
+});
+
+describe('Advanced Hook Tests', () => {
+ // Hook return tests
+ describe('Hook Return Tests', () => {
+ it('should handle expression return', ({ container }) => {
+ function useExpression(a: number, b: number) {
+ return a + b * 2;
+ }
+
+ function TestComponent() {
+ const result = useExpression(3, 4);
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('11
');
+ });
+
+ it('should handle object spread return', ({ container }) => {
+ function useObjectSpread(obj: object) {
+ return { ...obj, newProp: 'added' };
+ }
+
+ function TestComponent() {
+ const result = useObjectSpread({ existingProp: 'original' });
+ return {JSON.stringify(result)}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('{"existingProp":"original","newProp":"added"}
');
+ });
+
+ it('should handle function call return', ({ container }) => {
+ function useFunction() {
+ const innerFunction = () => 42;
+ return innerFunction();
+ }
+
+ function TestComponent() {
+ const result = useFunction();
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('42
');
+ });
+
+ it('should handle conditional expression return', ({ container }) => {
+ function useConditional(condition: boolean) {
+ return condition ? 'True' : 'False';
+ }
+
+ function TestComponent() {
+ const result = useConditional(true);
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('True
');
+ });
+
+ it('should handle array computation return', ({ container }) => {
+ function useArrayComputation(arr: number[]) {
+ return arr.reduce((sum, num) => sum + num, 0);
+ }
+
+ function TestComponent() {
+ const result = useArrayComputation([1, 2, 3, 4, 5]);
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('15
');
+ });
+
+ it('should handle ternary expression return', ({ container }) => {
+ function useTernary(value: number) {
+ return value > 5 ? 'High' : value < 0 ? 'Low' : 'Medium';
+ }
+
+ function TestComponent() {
+ const result = useTernary(7);
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('High
');
+ });
+
+ it('should handle member expression return', ({ container }) => {
+ function useMemberExpression(obj: { prop: string }) {
+ return obj.prop;
+ }
+
+ function TestComponent() {
+ const result = useMemberExpression({ prop: 'test' });
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('test
');
+ });
+ });
+
+ // Hook input tests
+ describe('Hook Input Tests', () => {
+ it('should handle expression input', ({ container }) => {
+ function useExpression(value: number) {
+ return value * 2;
+ }
+
+ function TestComponent() {
+ const result = useExpression(3 + 4);
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('14
');
+ });
+
+ it('should handle object spread input', ({ container }) => {
+ function useObjectSpread(obj: { a: number; b: number }) {
+ return obj.a + obj.b;
+ }
+
+ function TestComponent() {
+ const baseObj = { a: 1, c: 3 };
+ const result = useObjectSpread({ ...baseObj, b: 2 });
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('3
');
+ });
+
+ it('should handle function call input', ({ container }) => {
+ function useFunction(value: number) {
+ return value * 2;
+ }
+
+ function getValue() {
+ return 21;
+ }
+
+ function TestComponent() {
+ const result = useFunction(getValue());
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('42
');
+ });
+
+ it('should handle conditional expression input', ({ container }) => {
+ function useConditional(value: string) {
+ return `Received: ${value}`;
+ }
+
+ function TestComponent() {
+ const condition = true;
+ const result = useConditional(condition ? 'Yes' : 'No');
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('Received: Yes
');
+ });
+
+ it('should handle array computation input', ({ container }) => {
+ function useArraySum(sum: number) {
+ return `Sum: ${sum}`;
+ }
+
+ function TestComponent() {
+ const numbers = [1, 2, 3, 4, 5];
+ const result = useArraySum(numbers.reduce((sum, num) => sum + num, 0));
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('Sum: 15
');
+ });
+
+ it('should handle ternary expression input', ({ container }) => {
+ function useStatus(status: string) {
+ return `Current status: ${status}`;
+ }
+
+ function TestComponent() {
+ const value = 7;
+ const result = useStatus(value > 5 ? 'High' : value < 0 ? 'Low' : 'Medium');
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('Current status: High
');
+ });
+
+ it('should handle member expression input', ({ container }) => {
+ function useName(name: string) {
+ return `Hello, ${name}!`;
+ }
+
+ function TestComponent() {
+ const user = { name: 'Alice' };
+ const result = useName(user.name);
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('Hello, Alice!
');
+ });
+ });
+
+ // Additional tests
+ describe('Additional Hook Tests', () => {
+ it('should handle input based on other variables', ({ container }) => {
+ function useComputed(value: number) {
+ return value * 2;
+ }
+
+ function TestComponent() {
+ let baseValue = 5;
+ let multiplier = 3;
+ const result = useComputed(baseValue * multiplier);
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('30
');
+ });
+
+ it('should handle function input and output', ({ container }) => {
+ function useFunction(fn: (x: number) => number) {
+ return (y: number) => fn(y) * 2;
+ }
+
+ function TestComponent() {
+ const inputFn = (x: number) => x + 1;
+ const resultFn = useFunction(inputFn);
+ const result = resultFn(5);
+ return {result}
;
+ }
+
+ render(TestComponent, container);
+ expect(container.innerHTML).toBe('12
');
+ });
+ });
+});
diff --git a/packages/inula-next/test/event.test.tsx b/packages/inula-next/test/event.test.tsx
new file mode 100644
index 00000000..1e7dddf5
--- /dev/null
+++ b/packages/inula-next/test/event.test.tsx
@@ -0,0 +1,543 @@
+/*
+ * 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 } from '../src';
+
+vi.mock('../src/scheduler', async () => {
+ return {
+ schedule: (task: () => void) => {
+ task();
+ },
+ };
+});
+
+describe('Event Handling', () => {
+ it('Should correctly handle onClick events', ({ container }) => {
+ let clicked = false;
+ function App() {
+ const handleClick = () => {
+ clicked = true;
+ };
+ return Click me ;
+ }
+
+ render(App, container);
+ const button = container.querySelector('button');
+ button.click();
+ expect(clicked).toBe(true);
+ });
+
+ it.fails('Should correctly handle onMouseOver events', ({ container }) => {
+ let hovered = false;
+ function App() {
+ const handleMouseOver = () => {
+ hovered = true;
+ };
+ return Hover me
;
+ }
+
+ render(App, container);
+ const div = container.querySelector('div');
+ div.dispatchEvent(new MouseEvent('mouseover'));
+ expect(hovered).toBe(true);
+ });
+
+ it('Should correctly handle onKeyPress events', ({ container }) => {
+ let keypressed = '';
+ function App() {
+ const handleKeyPress = event => {
+ keypressed = event.key;
+ };
+ return ;
+ }
+
+ render(App, container);
+ const input = container.querySelector('input');
+ const event = new KeyboardEvent('keypress', { key: 'A' });
+ input.dispatchEvent(event);
+ expect(keypressed).toBe('A');
+ });
+
+ it('Should correctly handle onSubmit events', ({ container }) => {
+ let submitted = false;
+ function App() {
+ const handleSubmit = event => {
+ event.preventDefault();
+ submitted = true;
+ };
+ return (
+
+ );
+ }
+
+ render(App, container);
+ const form = container.querySelector('form');
+ form.dispatchEvent(new Event('submit'));
+ expect(submitted).toBe(true);
+ });
+
+ it.fails('Should correctly handle custom events', ({ container }) => {
+ let customEventData = null;
+ function App() {
+ const handleCustomEvent = event => {
+ customEventData = event.detail;
+ };
+ return Custom event target
;
+ }
+
+ render(App, container);
+ const div = container.querySelector('div');
+ const customEvent = new CustomEvent('customEvent', { detail: { message: 'Hello, Custom Event!' } });
+ div.dispatchEvent(customEvent);
+ expect(customEventData).toEqual({ message: 'Hello, Custom Event!' });
+ });
+
+ it('Should correctly handle events when the handler is a variable', ({ container }) => {
+ let count = 0;
+ function App() {
+ const incrementCount = () => {
+ count++;
+ };
+ return Increment ;
+ }
+
+ render(App, container);
+ const button = container.querySelector('button');
+ button.click();
+ expect(count).toBe(1);
+ });
+
+ it('Should correctly handle events when the handler is an expression returning a function', ({ container }) => {
+ let lastClicked = '';
+ function App() {
+ const createHandler = buttonName => () => {
+ lastClicked = buttonName;
+ };
+ return (
+
+ createHandler('Button A')()}>A
+ createHandler('Button B')()}>B
+
+ );
+ }
+
+ render(App, container);
+ const buttons = container.querySelectorAll('button');
+ buttons[0].click();
+ expect(lastClicked).toBe('Button A');
+ buttons[1].click();
+ expect(lastClicked).toBe('Button B');
+ });
+});
+
+describe('event emission', () => {
+ it('should handle emit to parent', ({ container }) => {
+ function AnswerButton({ onYes, onNo }) {
+ return (
+ <>
+ YES
+
+ {/*NO */}
+ >
+ );
+ }
+ function App() {
+ let isHappy = false;
+
+ function onAnswerNo() {
+ isHappy = false;
+ }
+
+ function onAnswerYes() {
+ isHappy = true;
+ }
+
+ return (
+ <>
+ Are you happy?
+
+ {isHappy ? 'yes' : 'no'}
+ >
+ );
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+
+ Are you happy?
+
+
+ YES
+
+
+ no
+
+
+ `);
+ container.querySelector('button')?.click();
+ expect(container).toMatchInlineSnapshot(`
+
+
+ Are you happy?
+
+
+ YES
+
+
+ yes
+
+
+ `);
+ });
+ it('should correctly emit events to parent component', ({ container }) => {
+ function Child({ onEvent }) {
+ return onEvent('clicked')}>Click me ;
+ }
+
+ function App() {
+ let eventReceived = '1';
+
+ function handleEvent(event) {
+ eventReceived = event;
+ }
+
+ return (
+ <>
+
+ {eventReceived}
+ >
+ );
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+ `);
+
+ container.querySelector('button')?.click();
+ expect(container).toMatchInlineSnapshot(`
+
+
+ Click me
+
+
+ clicked
+
+
+ `);
+ });
+
+ it('should correctly update parent state based on emitted events', ({ container }) => {
+ function Counter({ onIncrement, onDecrement }) {
+ return (
+
+ +
+ -
+
+ );
+ }
+
+ function App() {
+ let count = 0;
+
+ function increment() {
+ count += 1;
+ }
+
+ function decrement() {
+ count -= 1;
+ }
+
+ return (
+ <>
+
+ Count:{count}
+ >
+ );
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+ +
+
+
+ -
+
+
+
+ Count:
+ 0
+
+
+ `);
+
+ container.querySelectorAll('button')[0]?.click();
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+ +
+
+
+ -
+
+
+
+ Count:
+ 1
+
+
+ `);
+
+ container.querySelectorAll('button')[1]?.click();
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+ +
+
+
+ -
+
+
+
+ Count:
+ 0
+
+
+ `);
+ });
+
+ it('should correctly handle multiple event emissions', ({ container }) => {
+ function MultiButton({ onClickA, onClickB, onClickC }) {
+ return (
+
+ A
+ B
+ C
+
+ );
+ }
+
+ function App() {
+ let lastClicked = 'A';
+
+ function handleClick(button) {
+ lastClicked = button;
+ }
+
+ return (
+ <>
+ handleClick('A')}
+ onClickB={() => handleClick('B')}
+ onClickC={() => handleClick('C')}
+ />
+ Last clicked:{lastClicked}
+ >
+ );
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+ A
+
+
+ B
+
+
+ C
+
+
+
+ Last clicked:
+ A
+
+
+ `);
+
+ container.querySelectorAll('button')[1]?.click();
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+ A
+
+
+ B
+
+
+ C
+
+
+
+ Last clicked:
+ B
+
+
+ `);
+ });
+
+ it('should handle both arrow functions and function variables', ({ container }) => {
+ function Child({ onEventA, onEventB }) {
+ return (
+
+ Event A
+ Event B
+
+ );
+ }
+
+ function App() {
+ let eventResult = '1';
+
+ const handleEventA = () => {
+ eventResult = 'Arrow function called';
+ };
+
+ function handleEventB() {
+ eventResult = 'Function variable called';
+ }
+
+ return (
+ <>
+
+ {eventResult}
+ >
+ );
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+ Event A
+
+
+ Event B
+
+
+
+ 1
+
+
+ `);
+
+ container.querySelectorAll('button')[0]?.click();
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+ Event A
+
+
+ Event B
+
+
+
+ Arrow function called
+
+
+ `);
+
+ container.querySelectorAll('button')[1]?.click();
+ expect(container).toMatchInlineSnapshot(`
+
+
+
+ Event A
+
+
+ Event B
+
+
+
+ Function variable called
+
+
+ `);
+ });
+
+ it('should handle multi-layer event functions', ({ container }) => {
+ function GrandChild({ onEvent }) {
+ return onEvent('GrandChild clicked')}>Click GrandChild ;
+ }
+
+ function Child({ onParentEvent }) {
+ function handleChildEvent(message) {
+ onParentEvent(`Child received: ${message}`);
+ }
+
+ return ;
+ }
+
+ function App() {
+ let message = '1';
+
+ function handleAppEvent(receivedMessage) {
+ message = `App received: ${receivedMessage}`;
+ }
+
+ return (
+ <>
+
+ {message}
+ >
+ );
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+
+ Click GrandChild
+
+
+ 1
+
+
+ `);
+
+ container.querySelector('button')?.click();
+ expect(container).toMatchInlineSnapshot(`
+
+
+ Click GrandChild
+
+
+ App received: Child received: GrandChild clicked
+
+
+ `);
+ });
+});
diff --git a/packages/inula-next/test/for.test.tsx b/packages/inula-next/test/for.test.tsx
index 577c4ad6..be988581 100644
--- a/packages/inula-next/test/for.test.tsx
+++ b/packages/inula-next/test/for.test.tsx
@@ -132,7 +132,7 @@ describe('for', () => {
render(MyComp, container);
expect(container.innerHTML).toBe('');
});
- // this test has error, need to be comment
+
// it.fails('should transform last map to for" ', ({ container }) => {
// function MyComp() {
// let arr = [1, 2, 3];
@@ -150,4 +150,75 @@ describe('for', () => {
// render(MyComp, container);
// expect(container.innerHTML).toBe('');
// });
+ it('Should correctly render a single-level loop of elements', ({ container }) => {
+ function App() {
+ const fruits = ['Apple', 'Banana', 'Cherry'];
+ return {fruit => {fruit} } ;
+ }
+
+ render(App, container);
+ expect(container.innerHTML).toMatchInlineSnapshot(`"Apple Banana Cherry "`);
+ });
+
+ it('Should correctly render nested loops of elements', ({ container }) => {
+ function App() {
+ const matrix = [
+ [1, 2],
+ [3, 4],
+ [5, 6],
+ ];
+ return (
+
+ {row => (
+
+ {cell => {cell} }
+
+ )}
+
+ );
+ }
+
+ render(App, container);
+ expect(container.innerHTML).toMatchInlineSnapshot(
+ `"1 2
3 4
5 6
"`
+ );
+ });
+
+ it('Should correctly render loops with complex data structures', ({ container }) => {
+ function App() {
+ const users = [
+ { id: 1, name: 'Alice', hobbies: ['reading', 'gaming'] },
+ { id: 2, name: 'Bob', hobbies: ['cycling', 'photography'] },
+ ];
+ return (
+
+ {user => (
+
+ )}
+
+ );
+ }
+
+ render(App, container);
+ expect(container.innerHTML).toMatchInlineSnapshot(
+ `""`
+ );
+ });
+
+ it('Should correctly render when for tag input is an array map', ({ container }) => {
+ function App() {
+ const numbers = [1, 2, 3, 4, 5];
+ return n * 2)}>{doubledNumber => {doubledNumber} } ;
+ }
+
+ render(App, container);
+ expect(container.innerHTML).toMatchInlineSnapshot(
+ `"2 4 6 8 10 "`
+ );
+ });
});
diff --git a/packages/inula-next/test/jsxSlice.test.tsx b/packages/inula-next/test/jsxSlice.test.tsx
index c5a6caee..bd0479ae 100644
--- a/packages/inula-next/test/jsxSlice.test.tsx
+++ b/packages/inula-next/test/jsxSlice.test.tsx
@@ -407,3 +407,277 @@ describe('JSX Element Usage in Various Contexts', () => {
});
});
});
+
+describe('JSX Element Attributes', () => {
+ it('should correctly initialize attributes', ({ container }) => {
+ function App() {
+ return (
+
+ Content
+
+ );
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Content
');
+ });
+
+ it('should correctly update attributes', ({ container }) => {
+ function App() {
+ let className = 'initial';
+
+ function updateClass() {
+ className = 'updated';
+ }
+
+ return (
+ <>
+ Content
+ Update
+ >
+ );
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Content
Update ');
+
+ container.querySelector('button')?.click();
+ expect(container.innerHTML).toBe('Content
Update ');
+ });
+
+ it('should correctly render attributes dependent on variables', ({ container }) => {
+ function App() {
+ let className = 'initial';
+ let b = className;
+ function updateClass() {
+ className = 'updated';
+ }
+
+ return (
+ <>
+ Content
+ Update
+ >
+ );
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Content
Update ');
+
+ container.querySelector('button')?.click();
+ expect(container.innerHTML).toBe('Content
Update ');
+ });
+
+ it('should correctly render attributes with expressions', ({ container }) => {
+ function App() {
+ const count = 5;
+ return Content
;
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Content
');
+ });
+
+ it('should correctly render boolean attributes', ({ container }) => {
+ function App() {
+ const disabled = true;
+ return Click me ;
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Click me ');
+ });
+
+ it.fails('should correctly render attributes without values', ({ container }) => {
+ function App() {
+ const checked = true;
+ return ;
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe(' ');
+ });
+
+ it.fails('should correctly spread multiple attributes', ({ container }) => {
+ function App() {
+ const props = {
+ id: 'test-id',
+ className: 'test-class',
+ 'data-test': 'test-data',
+ };
+ return Content
;
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Content
');
+ });
+
+ it.fails('should correctly handle attribute spreading and individual props', ({ container }) => {
+ function App() {
+ const props = {
+ id: 'base-id',
+ className: 'base-class',
+ };
+ return (
+
+ Content
+
+ );
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Content
');
+ });
+});
+
+describe('JSX Element Inline Styles', () => {
+ it('should correctly apply inline styles to an element', ({ container }) => {
+ function App() {
+ return Styled content
;
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Styled content
');
+ });
+
+ it('should correctly apply multiple inline styles to an element', ({ container }) => {
+ function App() {
+ return Multiple styles
;
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe(
+ 'Multiple styles
'
+ );
+ });
+
+ it('should correctly apply styles from a variable', ({ container }) => {
+ function App() {
+ const styleObj = { color: 'green', padding: '5px' };
+ return Variable style
;
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Variable style
');
+ });
+
+ it('should correctly update styles', ({ container }) => {
+ function App() {
+ let style = { color: 'purple' };
+
+ function updateStyle() {
+ style = { color: 'orange', fontSize: '24px' };
+ }
+
+ return (
+ <>
+ Updatable style
+ Update
+ >
+ );
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Updatable style
Update ');
+
+ container.querySelector('button')?.click();
+ expect(container.innerHTML).toBe(
+ 'Updatable style
Update '
+ );
+ });
+
+ it('should correctly apply styles from an expression', ({ container }) => {
+ function App() {
+ const size = 18;
+ return Expression style
;
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Expression style
');
+ });
+
+ it('should correctly merge style objects', ({ container }) => {
+ function App() {
+ const baseStyle = { color: 'red', fontSize: '16px' };
+ const additionalStyle = { fontSize: '20px', fontWeight: 'bold' };
+ return Merged styles
;
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe(
+ 'Merged styles
'
+ );
+ });
+
+ it('should correctly apply styles from a function call', ({ container }) => {
+ function getStyles(color: string) {
+ return { color, border: `1px solid ${color}` };
+ }
+ function App() {
+ return Function style
;
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Function style
');
+ });
+
+ it('should correctly apply styles based on a condition', ({ container }) => {
+ function App() {
+ const isActive = true;
+ const style = isActive
+ ? { backgroundColor: 'green', color: 'white' }
+ : { backgroundColor: 'gray', color: 'black' };
+ return Conditional style
;
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Conditional style
');
+ });
+
+ it('should correctly apply styles based on an array of conditions', ({ container }) => {
+ function App() {
+ const conditions = [true, false, true];
+ const style = {
+ color: conditions[0] ? 'red' : 'blue',
+ fontWeight: conditions[1] ? 'bold' : 'normal',
+ fontSize: conditions[2] ? '20px' : '16px',
+ };
+ return Array condition style
;
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe(
+ 'Array condition style
'
+ );
+ });
+
+ it('should correctly apply styles using ternary and binary expressions', ({ container }) => {
+ function App() {
+ const isPrimary = true;
+ const isLarge = true;
+ return (
+
+ Ternary and binary style
+
+ );
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Ternary and binary style
');
+ });
+
+ it('should correctly apply styles using member expressions', ({ container }) => {
+ const theme = {
+ colors: {
+ primary: 'blue',
+ secondary: 'green',
+ },
+ sizes: {
+ small: '12px',
+ medium: '16px',
+ large: '20px',
+ },
+ };
+ function App() {
+ return (
+
+ Member expression style
+
+ );
+ }
+ render(App, container);
+ expect(container.innerHTML).toBe('Member expression style
');
+ });
+});
diff --git a/packages/inula-next/test/props.test.tsx b/packages/inula-next/test/props.test.tsx
index dc59bb60..87923919 100644
--- a/packages/inula-next/test/props.test.tsx
+++ b/packages/inula-next/test/props.test.tsx
@@ -136,3 +136,193 @@ describe('props', () => {
});
});
});
+
+describe('extended prop tests', () => {
+ it('should correctly pass and render string props', ({ container }) => {
+ function Child({ text }) {
+ return {text}
;
+ }
+
+ function App() {
+ return ;
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+ `);
+ });
+
+ it('should correctly pass and render number props', ({ container }) => {
+ function Child({ number }) {
+ return {number} ;
+ }
+
+ function App() {
+ return ;
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+
+ 42
+
+
+ `);
+ });
+
+ it('should correctly pass and render boolean props', ({ container }) => {
+ function Child({ isActive }) {
+ return {isActive ? 'Active' : 'Inactive'}
;
+ }
+
+ function App() {
+ return ;
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+ `);
+ });
+
+ it.fails('should correctly pass and render array props', ({ container }) => {
+ function Child({ items }) {
+ return (
+
+ {items.map((item, index) => (
+ {item}
+ ))}
+
+ );
+ }
+
+ function App() {
+ return ;
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+
+ Apple
+ Banana
+ Cherry
+
+
+ `);
+ });
+
+ it.fails('should correctly pass and render object props', ({ container }) => {
+ function Child({ person }) {
+ return (
+
+ {person.name}, {person.age}
+
+ );
+ }
+
+ function App() {
+ return ;
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+ `);
+ });
+
+ it('should correctly handle default prop values', ({ container }) => {
+ function Child({ message = 'Default message' }) {
+ return {message} ;
+ }
+
+ function App() {
+ return ;
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+
+ Default message
+
+
+ `);
+ });
+
+ it.fails('should correctly spread props', ({ container }) => {
+ function Child(props) {
+ return (
+
+ {props.a} {props.b} {props.c}
+
+ );
+ }
+
+ function App() {
+ const extraProps = { b: 'World', c: '!' };
+ return ;
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+ `);
+ });
+
+ it.fails('should handle props without values', ({ container }) => {
+ function Child({ isDisabled }) {
+ return Click me ;
+ }
+
+ function App() {
+ return ;
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+
+ Click me
+
+
+ `);
+ });
+
+ it('should handle props with expressions', ({ container }) => {
+ function Child({ result }) {
+ return {result}
;
+ }
+
+ function App() {
+ return ;
+ }
+
+ render(App, container);
+ expect(container).toMatchInlineSnapshot(`
+
+ `);
+ });
+});
diff --git a/packages/inula-next/test/rendering.test.tsx b/packages/inula-next/test/rendering.test.tsx
index 68149c34..2dc50d42 100644
--- a/packages/inula-next/test/rendering.test.tsx
+++ b/packages/inula-next/test/rendering.test.tsx
@@ -116,6 +116,26 @@ describe('rendering', () => {
expect(h1.style.color).toBe('red');
});
+ it.fails('should apply styles number correctly', ({ container }) => {
+ function App() {
+ return hello world!!! ;
+ }
+
+ render(App, container);
+ const h1 = container.querySelector('h1');
+ expect(h1.style.fontSize).toBe('12px');
+ });
+
+ it('should apply styles empty correctly', ({ container }) => {
+ function App() {
+ return hello world!!! ;
+ }
+
+ render(App, container);
+ const h1 = container.querySelector('h1');
+ expect(h1.style.fontSize).toBe('');
+ });
+
it('should apply multiple styles correctly', ({ container }) => {
function App() {
return hello world!!! ;
--
Gitee