Skip to content

Commit

Permalink
Refactor Link to add more cheap unit tests (#4553)
Browse files Browse the repository at this point in the history
* Refactor Link to add more cheap unit tests

* Add few more props

* Remove redundant comments

* Remove should from tests

* Refactor tests to meet guidelines

* Update snapshots

* Clarify 'when href, target, rel and onClick' test

* Fix tests after fixing merge conflicts
  • Loading branch information
OleksandrNechai authored Oct 25, 2024
1 parent 6de8693 commit a3e5437
Show file tree
Hide file tree
Showing 3 changed files with 398 additions and 119 deletions.
100 changes: 67 additions & 33 deletions packages/base/Link/src/Link/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,30 @@ export type Props = BaseProps &
const defaultColor = 'blue'
const defaultVariant = 'anchor'

export const Link: OverridableComponent<Props> = forwardRef<
HTMLAnchorElement,
Props
>(function Link(props, ref) {
type ViewModel = {
className: string
href?: string
target?: string
color?: 'inherit'
rel?: string
onClick?: (event: React.MouseEvent<HTMLAnchorElement>) => void
weight: 'inherit' | 'semibold'
style?: React.CSSProperties
tabIndex?: number
as: Props['as']
ariaDisabled?: boolean
nativeHTMLAttributes: Omit<Props, keyof BaseProps>
}

/* eslint-disable complexity */
export const calculateViewModel = (props: Props): ViewModel => {
const {
href,
onClick,
children,
className,
as = 'a',
color: inputColor = 'blue',
style,
as = 'a',
variant: inputVariant = 'anchor',
tabIndex,
target,
Expand All @@ -103,9 +115,9 @@ export const Link: OverridableComponent<Props> = forwardRef<
visited = false,
noUnderline,
'aria-disabled': ariaDisabled,
...rest
...nativeHTMLAttributes
} = props
const nativeHTMLAttributes = rest

const sanitizedRel = sanitizeRel(rel, target)

// When Link is used as={Link}, TypeScript can't ensure the input to the Link is compatible with its Props type.
Expand All @@ -114,36 +126,58 @@ export const Link: OverridableComponent<Props> = forwardRef<
? inputVariant
: defaultVariant

return {
className: twMerge(
'focus:outline-none hover:underline leading-[inherit]',
COLOR_DISABLED_MAP[color][variant][disabled ? 'disabled' : 'normal'],
disabled ? 'cursor-not-allowed' : '',
noUnderline ? '!no-underline' : '',
visited
? color === 'blue'
? 'visited text-purple-500'
: 'visited text-gray-500'
: '',
onClick || href ? 'cursor-pointer' : '',
className
),
href: disabled ? undefined : href,
target: disabled ? undefined : target,
rel: sanitizedRel,
onClick: disabled ? undefined : onClick,
weight: variant === 'action' ? 'semibold' : 'inherit',
color: 'inherit',
style,
tabIndex,
as,
ariaDisabled: disabled || ariaDisabled,
nativeHTMLAttributes,
}
}

export const Link: OverridableComponent<Props> = forwardRef<
HTMLAnchorElement,
Props
>(function Link(props, ref) {
const viewModel = calculateViewModel(props)

return (
<Typography
{...nativeHTMLAttributes}
{...viewModel.nativeHTMLAttributes}
ref={ref}
as={as}
as={viewModel.as}
// @ts-expect-error Typography is incompatible with href prop
href={disabled ? undefined : href}
target={disabled ? undefined : target}
rel={sanitizedRel}
onClick={disabled ? undefined : onClick}
color='inherit'
weight={variant === 'action' ? 'semibold' : 'inherit'}
className={twMerge(
'focus:outline-none hover:underline leading-[inherit]',
COLOR_DISABLED_MAP[color][variant][disabled ? 'disabled' : 'normal'],
disabled ? 'cursor-not-allowed' : '',
noUnderline ? '!no-underline' : '',
visited
? color === 'blue'
? 'visited text-purple-500'
: 'visited text-gray-500'
: '',
onClick || href ? 'cursor-pointer' : '',
className
)}
style={style}
tabIndex={tabIndex}
aria-disabled={disabled || ariaDisabled}
href={viewModel.href}
target={viewModel.target}
rel={viewModel.rel}
onClick={viewModel.onClick}
color={viewModel.color}
weight={viewModel.weight}
className={viewModel.className}
style={viewModel.style}
tabIndex={viewModel.tabIndex}
aria-disabled={viewModel.ariaDisabled}
>
{children}
{props.children}
</Typography>
)
})
Expand Down
38 changes: 19 additions & 19 deletions packages/base/Link/src/Link/__snapshots__/test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,7 @@ exports[`Link renders 1`] = `
</div>
`;

exports[`Link renders a Link from react-router 1`] = `
<div>
<div
class="Picasso-root"
>
<div>
<a
class="m-0 font-inherit font-inherit focus:outline-none hover:underline leading-[inherit] text-blue visited:text-purple no-underline"
href="/"
>
Please verify your email
</a>
</div>
</div>
</div>
`;

exports[`Link renders disabled link 1`] = `
exports[`Link when disabled renders disabled link 1`] = `
<div>
<div
class="Picasso-root"
Expand All @@ -48,7 +31,7 @@ exports[`Link renders disabled link 1`] = `
</div>
`;

exports[`Link renders native attributes 1`] = `
exports[`Link when native attributes are provided renders native attributes 1`] = `
<div>
<div
class="Picasso-root"
Expand All @@ -65,3 +48,20 @@ exports[`Link renders native attributes 1`] = `
</div>
</div>
`;

exports[`Link when using react-router Link renders a Link from react-router 1`] = `
<div>
<div
class="Picasso-root"
>
<div>
<a
class="m-0 font-inherit font-inherit focus:outline-none hover:underline leading-[inherit] text-blue visited:text-purple no-underline"
href="/"
>
Please verify your email
</a>
</div>
</div>
</div>
`;
Loading

0 comments on commit a3e5437

Please sign in to comment.