import { __unstable__loadDesignSystem } from '@tailwindcss/node'
import { describe, expect, test, vi } from 'vitest'
import * as versions from '../../utils/version'
import { migrateCandidate } from './migrate'
vi.spyOn(versions, 'isMajor').mockReturnValue(true)
const css = String.raw
describe('is-safe-migration', async () => {
let designSystem = await __unstable__loadDesignSystem(
css`
@import 'tailwindcss';
@theme {
--*: initial;
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
}
`,
{ base: __dirname },
)
test.each([
[`let notBorder = !border \n`, '!border'],
[`{ "foo": !border.something + ""}\n`, '!border'],
[`<div v-if="something && !border"></div>\n`, '!border'],
[`<div v-else-if="something && !border"></div>\n`, '!border'],
[`<div v-show="something && !border"></div>\n`, '!border'],
[`<div v-if="!border || !border"></div>\n`, '!border'],
[`<div v-else-if="!border || !border"></div>\n`, '!border'],
[`<div v-show="!border || !border"></div>\n`, '!border'],
[`<div v-if="!border"></div>\n`, '!border'],
[`<div v-else-if="!border"></div>\n`, '!border'],
[`<div v-show="!border"></div>\n`, '!border'],
[`<div x-if="!border"></div>\n`, '!border'],
[`let notShadow = shadow \n`, 'shadow'],
[`{ "foo": shadow.something + ""}\n`, 'shadow'],
[`<div v-if="something && shadow"></div>\n`, 'shadow'],
[`<div v-else-if="something && shadow"></div>\n`, 'shadow'],
[`<div v-show="something && shadow"></div>\n`, 'shadow'],
[`<div v-if="shadow || shadow"></div>\n`, 'shadow'],
[`<div v-else-if="shadow || shadow"></div>\n`, 'shadow'],
[`<div v-show="shadow || shadow"></div>\n`, 'shadow'],
[`<div v-if="shadow"></div>\n`, 'shadow'],
[`<div v-else-if="shadow"></div>\n`, 'shadow'],
[`<div v-show="shadow"></div>\n`, 'shadow'],
[`<div x-if="shadow"></div>\n`, 'shadow'],
[`<div style={{filter: 'drop-shadow(30px 10px 4px #4444dd)'}}/>\n`, 'shadow'],
[`<Image placeholder="blur" src="/image.jpg" />`, 'blur'],
[`<Image placeholder={'blur'} src="/image.jpg" />`, 'blur'],
[`<Image placeholder={blur} src="/image.jpg" />`, 'blur'],
['<div v-if="!duration">', '!duration'],
['<div :active="!duration">', '!duration'],
['<div :active="!visible">', '!visible'],
['<x-input.number required="foo" wire:model.blur="coins" />', 'blur'],
[`emit('blur', props.modelValue)\n`, 'blur'],
[`$emit('blur', props.modelValue)\n`, 'blur'],
[`document.addEventListener('blur',handleBlur)`, 'blur'],
[`document.addEventListener('blur', handleBlur)`, 'blur'],
[`function foo({ outline = true })`, 'outline'],
[`function foo({ before = false, outline = true })`, 'outline'],
[`function foo({before=false,outline=true })`, 'outline'],
[`function foo({outline=true })`, 'outline'],
[
`function foo({ size = "1.25rem", digit, outline = true, textClass = "", className = "" })`,
'outline',
],
[
`function foo({ size = "1.25rem", digit, outline, textClass = "", className = "" })`,
'outline',
],
[
`function foo({ size = "1.25rem", digit, outline })`,
'outline',
],
[
`function foo({ size = "1.25rem", digit, outline }): { return "foo" }`,
'outline',
],
[
`function foo({ before = "'", outline, after = "'" }): { return "foo" }`,
'outline',
],
[`function foo(blur, foo)`, 'blur'],
[`function foo(blur,foo)`, 'blur'],
[`<Button variant="outline" />`, 'outline'],
[`<Button variant='outline' />`, 'outline'],
[`<Button variant={"outline"} />`, 'outline'],
[`<Button variant={'outline'} />`, 'outline'],
[`function Button({ variant = "outline" }) {}`, 'outline'],
[`function Button({ variant = 'outline' }) {}`, 'outline'],
[`function Button({ variant="outline" }) {}`, 'outline'],
[`function Button({ variant='outline' }) {}`, 'outline'],
[`Button({ variant: "outline" })`, 'outline'],
[`Button({ variant: 'outline' })`, 'outline'],
])('does not replace classes in invalid positions #%#', async (example, candidate) => {
expect(
await migrateCandidate(designSystem, {}, candidate, {
contents: example,
start: example.indexOf(candidate),
end: example.indexOf(candidate) + candidate.length,
}),
).toEqual(candidate)
})
test.each([
[`<div class="shadow"></div>`, 'shadow', 'shadow-sm'],
[`<div :class="{ shadow: true }"></div>`, 'shadow', 'shadow-sm'],
[`<div enter-class="shadow"></div>`, 'shadow', 'shadow-sm'],
[`<div :enter-class="{ shadow: true }"></div>`, 'shadow', 'shadow-sm'],
[`<div className="shadow"></div>`, 'shadow', 'shadow-sm'],
[`<div enterClassName="shadow"></div>`, 'shadow', 'shadow-sm'],
[`<div enterClass="shadow"></div>`, 'shadow', 'shadow-sm'],
])('replaces classes in valid positions #%#', async (example, candidate, expected) => {
expect(
await migrateCandidate(designSystem, {}, candidate, {
contents: example,
start: example.indexOf(candidate),
end: example.indexOf(candidate) + candidate.length,
}),
).toEqual(expected)
})
})