fix(ct): render attributes (#17991)
This commit is contained in:
		
							parent
							
								
									689c3eb5fe
								
							
						
					
					
						commit
						ced3efb688
					
				| 
						 | 
				
			
			@ -42,6 +42,20 @@ function createChild(child, h) {
 | 
			
		|||
  return typeof child === 'string' ? child : createWrapper(child, h);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Exists to support fallthrough attributes:
 | 
			
		||||
 * https://vuejs.org/guide/components/attrs.html#fallthrough-attributes
 | 
			
		||||
 * @param {any} Component
 | 
			
		||||
 * @param {string} key
 | 
			
		||||
 * @return {boolean}
 | 
			
		||||
 */
 | 
			
		||||
function componentHasKeyInProps(Component, key) {
 | 
			
		||||
  if (Array.isArray(Component.props))
 | 
			
		||||
    return Component.props.includes(key);
 | 
			
		||||
 | 
			
		||||
  return Object.entries(Component.props).flat().includes(key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {Component} component
 | 
			
		||||
 * @param {import('vue').CreateElement} h
 | 
			
		||||
| 
						 | 
				
			
			@ -96,7 +110,7 @@ function createComponent(component, h) {
 | 
			
		|||
        const event = key.substring('v-on:'.length);
 | 
			
		||||
        nodeData.on[event] = value;
 | 
			
		||||
      } else {
 | 
			
		||||
        if (isVueComponent)
 | 
			
		||||
        if (isVueComponent && componentHasKeyInProps(componentFunc, key))
 | 
			
		||||
          nodeData.props[key] = value;
 | 
			
		||||
        else
 | 
			
		||||
          nodeData.attrs[key] = value;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
<html lang="en">
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="UTF-8" />
 | 
			
		||||
    <link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
 | 
			
		||||
    <link rel="icon" type="image/svg+xml" href="/src/assets/favicon.svg" />
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
			
		||||
    <title>Vite App</title>
 | 
			
		||||
  </head>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
import { useState } from 'react'
 | 
			
		||||
import logo from './components/logo.svg'
 | 
			
		||||
import logo from './assets/logo.svg'
 | 
			
		||||
import './App.css'
 | 
			
		||||
 | 
			
		||||
function App() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,13 @@
 | 
			
		|||
import { ButtonHTMLAttributes } from "react";
 | 
			
		||||
 | 
			
		||||
type ButtonProps = {
 | 
			
		||||
  title: string;
 | 
			
		||||
  onClick?(props: string): void;
 | 
			
		||||
}
 | 
			
		||||
export default function Button(props: ButtonProps) {
 | 
			
		||||
  return <button onClick={() => props.onClick?.('hello')}>{props.title}</button>
 | 
			
		||||
  className?: string;
 | 
			
		||||
} & ButtonHTMLAttributes<HTMLButtonElement>;
 | 
			
		||||
 | 
			
		||||
export default function Button({ onClick, title, ...attributes }: ButtonProps) {
 | 
			
		||||
  return <button {...attributes} onClick={() => onClick?.('hello')}>
 | 
			
		||||
    {title}
 | 
			
		||||
  </button>
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,11 @@ test('render props', async ({ mount }) => {
 | 
			
		|||
  await expect(component).toContainText('Submit');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('render attributes', async ({ mount }) => {
 | 
			
		||||
  const component = await mount(<Button className="primary" title="Submit" />)
 | 
			
		||||
  await expect(component).toHaveClass('primary');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('renderer updates props without remounting', async ({ mount }) => {
 | 
			
		||||
  const component = await mount(<Counter count={9001} />)
 | 
			
		||||
  await expect(component.locator('#props')).toContainText('9001')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,13 @@
 | 
			
		|||
import { ButtonHTMLAttributes } from "react";
 | 
			
		||||
 | 
			
		||||
type ButtonProps = {
 | 
			
		||||
  title: string;
 | 
			
		||||
  onClick?(props: string): void;
 | 
			
		||||
}
 | 
			
		||||
export default function Button(props: ButtonProps) {
 | 
			
		||||
  return <button onClick={() => props.onClick?.('hello')}>{props.title}</button>
 | 
			
		||||
  className?: string;
 | 
			
		||||
} & ButtonHTMLAttributes<HTMLButtonElement>;
 | 
			
		||||
 | 
			
		||||
export default function Button({ onClick, title, ...attributes }: ButtonProps) {
 | 
			
		||||
  return <button {...attributes} onClick={() => onClick?.('hello')}>
 | 
			
		||||
    {title}
 | 
			
		||||
  </button>
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,11 @@ test('render props', async ({ mount }) => {
 | 
			
		|||
  await expect(component).toContainText('Submit');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('render attributes', async ({ mount }) => {
 | 
			
		||||
  const component = await mount(<Button className="primary" title="Submit" />)
 | 
			
		||||
  await expect(component).toHaveClass('primary');
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('renderer updates props without remounting', async ({ mount }) => {
 | 
			
		||||
  const component = await mount(<Counter count={9001} />)
 | 
			
		||||
  await expect(component.locator('#props')).toContainText('9001')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,13 @@
 | 
			
		|||
import type { JSX } from "solid-js";
 | 
			
		||||
 | 
			
		||||
type ButtonProps = {
 | 
			
		||||
  title: string;
 | 
			
		||||
  onClick?(props: string): void;
 | 
			
		||||
}
 | 
			
		||||
export default function Button(props: ButtonProps) {
 | 
			
		||||
  return <button onClick={() => props.onClick?.('hello')}>{props.title}</button>
 | 
			
		||||
  className?: string;
 | 
			
		||||
} & JSX.ButtonHTMLAttributes<HTMLButtonElement>;
 | 
			
		||||
 | 
			
		||||
export default function Button({ onClick, title, ...attributes }: ButtonProps) {
 | 
			
		||||
  return <button {...attributes} onClick={() => onClick?.('hello')}>
 | 
			
		||||
    {title}
 | 
			
		||||
  </button>
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,11 @@ test('render props', async ({ mount }) => {
 | 
			
		|||
  await expect(component).toContainText('Submit');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('render attributes', async ({ mount }) => {
 | 
			
		||||
  const component = await mount(<Button className="primary" title="Submit" />)
 | 
			
		||||
  await expect(component).toHaveClass('primary');
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('execute callback when the button is clicked', async ({ mount }) => {
 | 
			
		||||
  const messages: string[] = [];
 | 
			
		||||
  const component = await mount(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,11 @@ test('render props', async ({ mount }) => {
 | 
			
		|||
  await expect(component).toContainText('Submit')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('render attributes', async ({ mount }) => {
 | 
			
		||||
  const component = await mount(<Button class="primary" title="Submit" />)
 | 
			
		||||
  await expect(component).toHaveClass('primary');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('renderer updates props without remounting', async ({ mount }) => {
 | 
			
		||||
  const component = await mount(<Counter count={9001} />)
 | 
			
		||||
  await expect(component.locator('#props')).toContainText('9001')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,11 @@ test('render props', async ({ mount }) => {
 | 
			
		|||
  await expect(component).toContainText('Submit')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('render attributes', async ({ mount }) => {
 | 
			
		||||
  const component = await mount(<Button class="primary" title="Submit" />)
 | 
			
		||||
  await expect(component).toHaveClass('primary');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('renderer updates props without remounting', async ({ mount }) => {
 | 
			
		||||
  const component = await mount(<Counter count={9001} />)
 | 
			
		||||
  await expect(component.locator('#props')).toContainText('9001')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue