From f22a6d12855dc8c20ef5f52f74365b2618d22ab4 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, 16 Aug 2024 11:23:07 +0800 Subject: [PATCH] test: add watch and jsx test cases --- packages/inula-next/test/jsxSlice.test.tsx | 161 ++++++++++ packages/inula-next/test/watch.test.tsx | 325 +++++++++++++++++++++ 2 files changed, 486 insertions(+) create mode 100644 packages/inula-next/test/watch.test.tsx diff --git a/packages/inula-next/test/jsxSlice.test.tsx b/packages/inula-next/test/jsxSlice.test.tsx index bdb70434..c5a6caee 100644 --- a/packages/inula-next/test/jsxSlice.test.tsx +++ b/packages/inula-next/test/jsxSlice.test.tsx @@ -111,6 +111,167 @@ describe('JSX Element Usage in Various Contexts', () => { render(App, container); expect(container.innerHTML).toBe('
Dark Theme
'); }); + it('should render string literals', ({ container }) => { + function App() { + return
{'Hello, World!'}
; + } + render(App, container); + expect(container.innerHTML).toBe('
Hello, World!
'); + }); + + it('should render numbers', ({ container }) => { + function App() { + return
{42}
; + } + render(App, container); + expect(container.innerHTML).toBe('
42
'); + }); + + it.fails('should render booleans (as empty string)', ({ container }) => { + function App() { + return
{true}
; + } + render(App, container); + expect(container.innerHTML).toBe('
'); + }); + + it.fails('should render null and undefined (as empty string)', ({ container }) => { + function App() { + return ( +
+ {null} + {undefined} +
+ ); + } + render(App, container); + expect(container.innerHTML).toBe('
'); + }); + + it.fails('should render arrays of elements', ({ container }) => { + function App() { + return
{[One, Two]}
; + } + render(App, container); + expect(container.innerHTML).toBe('
OneTwo
'); + }); + + it('should render function components', ({ container }) => { + function Child() { + return Child Component; + } + function App() { + return ( +
+ +
+ ); + } + render(App, container); + expect(container.innerHTML).toBe('
Child Component
'); + }); + + it('should render fragments', ({ container }) => { + function App() { + return ( + <> + First + Second + + ); + } + render(App, container); + expect(container.innerHTML).toBe('FirstSecond'); + }); + + it('should render elements with props', ({ container }) => { + function App() { + return ( +
+ Content +
+ ); + } + render(App, container); + expect(container.innerHTML).toBe('
Content
'); + }); + + it('should render elements with children prop', ({ container }) => { + function Wrapper({ children }: { children: React.ReactNode }) { + return
{children}
; + } + function App() { + return ( + + Child Content + + ); + } + render(App, container); + expect(container.innerHTML).toBe('
Child Content
'); + }); + + it('should correctly render nested HTML elements', ({ container }) => { + function App() { + return ( +
+

+ Nested content +

+
+ ); + } + render(App, container); + expect(container.innerHTML).toBe('

Nested content

'); + }); + + it.fails('should correctly render a mix of HTML elements and text', ({ container }) => { + function App() { + return ( +
+ Text before Element Text after +
+ ); + } + render(App, container); + expect(container.innerHTML).toBe('
Text before Element Text after
'); + }); + + it.fails('should correctly render text on both sides of an element', ({ container }) => { + function App() { + return ( +
+ Left side text Bold text Right side text +
+ ); + } + render(App, container); + expect(container.innerHTML).toBe('
Left side text Bold text Right side text
'); + }); + + it.fails( + 'should correctly render a mix of curly braces, text, and elements in different orders', + ({ container }) => { + function App() { + const name = 'World'; + return ( +
+ {/* Curly braces, then text, then element */} + {name}, Hello ! + {/* Element, then curly braces, then text */} + Greetings {name} to you + {/* Text, then element, then curly braces */} + Welcome dear {name} +
+ ); + } + render(App, container); + expect(container.innerHTML).toBe( + '
World, Hello !Greetings World to you' + + 'Welcome dear World
' + ); + } + ); }); describe('update', () => { it('should support variable assignment of JSX elements and updates', ({ container }) => { diff --git a/packages/inula-next/test/watch.test.tsx b/packages/inula-next/test/watch.test.tsx new file mode 100644 index 00000000..0a87a38e --- /dev/null +++ b/packages/inula-next/test/watch.test.tsx @@ -0,0 +1,325 @@ +/* + * 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('Watch', () => { + it('Should correctly watch variable', ({ container }) => { + let increment: () => void; + function TrafficLight() { + let lightIndex = 0; + let index = 0; + increment = () => { + lightIndex = lightIndex + 1; + }; + + watch(() => { + index = lightIndex; + }); + return
{index}
; + } + render(TrafficLight, container); + expect(container.innerHTML).toBe('
0
'); + increment(); + expect(container.innerHTML).toBe('
1
'); + }); + it('Should correctly watch and update based on string state changes', ({ container }) => { + let updateState: (newState: string) => void; + function StringComponent() { + let state = 'initial'; + let watchedState = ''; + updateState = (newState: string) => { + state = newState; + }; + watch(() => { + watchedState = state; + }); + return
{watchedState}
; + } + render(StringComponent, container); + expect(container.innerHTML).toBe('
initial
'); + updateState('updated'); + expect(container.innerHTML).toBe('
updated
'); + }); + + it('Should correctly watch and update based on number state changes', ({ container }) => { + let updateState: (newState: number) => void; + function NumberComponent() { + let state = 0; + let watchedState = 0; + updateState = (newState: number) => { + state = newState; + }; + watch(() => { + watchedState = state; + }); + return
{watchedState}
; + } + render(NumberComponent, container); + expect(container.innerHTML).toBe('
0
'); + updateState(42); + expect(container.innerHTML).toBe('
42
'); + }); + + it('Should correctly watch and update based on boolean state changes', ({ container }) => { + let updateState: (newState: boolean) => void; + function BooleanComponent() { + let state = false; + let watchedState = false; + updateState = (newState: boolean) => { + state = newState; + }; + watch(() => { + watchedState = state; + }); + return
{watchedState.toString()}
; + } + render(BooleanComponent, container); + expect(container.innerHTML).toBe('
false
'); + updateState(true); + expect(container.innerHTML).toBe('
true
'); + }); + + it('Should correctly watch and update based on array state changes', ({ container }) => { + let updateState: (newState: number[]) => void; + function ArrayComponent() { + let state: number[] = []; + let watchedState: number[] = []; + updateState = (newState: number[]) => { + state = newState; + }; + watch(() => { + watchedState = [...state]; + }); + return
{watchedState.join(',')}
; + } + render(ArrayComponent, container); + expect(container.innerHTML).toBe('
'); + updateState([1, 2, 3]); + expect(container.innerHTML).toBe('
1,2,3
'); + }); + + it('Should correctly watch and update based on object state changes', ({ container }) => { + let updateState: (newState: { [key: string]: any }) => void; + function ObjectComponent() { + let state = {}; + let watchedState = {}; + updateState = (newState: { [key: string]: any }) => { + state = newState; + }; + watch(() => { + watchedState = { ...state }; + }); + return
{JSON.stringify(watchedState)}
; + } + render(ObjectComponent, container); + expect(container.innerHTML).toBe('
{}
'); + updateState({ key: 'value' }); + expect(container.innerHTML).toBe('
{"key":"value"}
'); + }); + + it('Should correctly watch conditional expressions', ({ container }) => { + let updateX: (value: number) => void; + function ConditionalComponent() { + let x = 5; + let result = ''; + updateX = (value: number) => { + x = value; + }; + watch(() => { + result = x > 10 ? 'Greater than 10' : 'Less than or equal to 10'; + }); + return
{result}
; + } + render(ConditionalComponent, container); + expect(container.innerHTML).toBe('
Less than or equal to 10
'); + updateX(15); + expect(container.innerHTML).toBe('
Greater than 10
'); + }); + + it('Should correctly watch template strings', ({ container }) => { + let updateName: (value: string) => void; + let updateAge: (value: number) => void; + function TemplateStringComponent() { + let name = 'John'; + let age = 30; + let message = ''; + updateName = (value: string) => { + name = value; + }; + updateAge = (value: number) => { + age = value; + }; + watch(() => { + message = `${name} is ${age} years old`; + }); + return
{message}
; + } + render(TemplateStringComponent, container); + expect(container.innerHTML).toBe('
John is 30 years old
'); + updateName('Jane'); + updateAge(25); + expect(container.innerHTML).toBe('
Jane is 25 years old
'); + }); + + it('Should correctly watch arithmetic operations', ({ container }) => { + let updateX: (value: number) => void; + let updateY: (value: number) => void; + function ArithmeticComponent() { + let x = 5; + let y = 3; + let result = 0; + updateX = (value: number) => { + x = value; + }; + updateY = (value: number) => { + y = value; + }; + watch(() => { + result = x + y * 2 - x / y; + }); + return
{result}
; + } + render(ArithmeticComponent, container); + expect(container.innerHTML).toBe('
9.333333333333334
'); + updateX(10); + updateY(5); + expect(container.innerHTML).toBe('
18
'); + }); + + it('Should correctly watch property access and indexing', ({ container }) => { + let updateObj: (value: { [key: string]: any }) => void; + let updateArr: (value: number[]) => void; + function AccessComponent() { + let obj = { a: 1, b: 2 }; + let arr = [1, 2, 3]; + let result = 0; + updateObj = (value: { [key: string]: any }) => { + obj = value; + }; + updateArr = (value: number[]) => { + arr = value; + }; + watch(() => { + result = obj.a + arr[1]; + }); + return
{result}
; + } + render(AccessComponent, container); + expect(container.innerHTML).toBe('
3
'); + updateObj({ a: 5, b: 6 }); + updateArr([0, 10, 20]); + expect(container.innerHTML).toBe('
15
'); + }); + + it('Should correctly watch function calls', ({ container }) => { + let updateX: (value: number) => void; + function FunctionCallComponent() { + let x = 5; + let result = 0; + const square = (n: number) => n * n; + updateX = (value: number) => { + x = value; + }; + watch(() => { + result = square(x); + }); + return
{result}
; + } + render(FunctionCallComponent, container); + expect(container.innerHTML).toBe('
25
'); + updateX(10); + expect(container.innerHTML).toBe('
100
'); + }); + + it('Should correctly watch various number operations', ({ container }) => { + let updateX: (value: number) => void; + function NumberOpsComponent() { + let x = 16; + let result = ''; + updateX = (value: number) => { + x = value; + }; + watch(() => { + result = `sqrt: ${Math.sqrt(x)}, floor: ${Math.floor(x / 3)}, pow: ${Math.pow(x, 2)}`; + }); + return
{result}
; + } + render(NumberOpsComponent, container); + expect(container.innerHTML).toBe('
sqrt: 4, floor: 5, pow: 256
'); + updateX(25); + expect(container.innerHTML).toBe('
sqrt: 5, floor: 8, pow: 625
'); + }); + + it('Should correctly watch map operations', ({ container }) => { + let updateArr: (value: number[]) => void; + function MapComponent() { + let arr = [1, 2, 3, 4, 5]; + let result: number[] = []; + updateArr = (value: number[]) => { + arr = value; + }; + watch(() => { + result = arr.map(x => x * 2); + }); + return
{result.join(', ')}
; + } + render(MapComponent, container); + expect(container.innerHTML).toBe('
2, 4, 6, 8, 10
'); + updateArr([10, 20, 30]); + expect(container.innerHTML).toBe('
20, 40, 60
'); + }); + + it('Should correctly watch multiple variables', ({ container }) => { + let updateX: (value: number) => void; + let updateY: (value: string) => void; + let updateZ: (value: boolean) => void; + function MultiWatchComponent() { + let x = 5; + let y = 'hello'; + let z = true; + let result = ''; + updateX = (value: number) => { + x = value; + }; + updateY = (value: string) => { + y = value; + }; + updateZ = (value: boolean) => { + z = value; + }; + watch(() => { + result = `x: ${x}, y: ${y}, z: ${z}`; + }); + return
{result}
; + } + render(MultiWatchComponent, container); + expect(container.innerHTML).toBe('
x: 5, y: hello, z: true
'); + updateX(10); + updateY('world'); + updateZ(false); + expect(container.innerHTML).toBe('
x: 10, y: world, z: false
'); + }); +}); -- Gitee