2021-04-30 16:58:40 +02:00
|
|
|
import fs from 'fs'
|
|
|
|
|
import path from 'path'
|
2021-04-02 11:16:15 -04:00
|
|
|
|
2022-02-15 13:44:19 -05:00
|
|
|
import { html, run, css, defaults } from './util/run'
|
2021-07-29 13:31:06 +02:00
|
|
|
|
2021-04-02 11:16:15 -04:00
|
|
|
test('basic usage', () => {
|
|
|
|
|
let config = {
|
Remove AOT (#5340)
* make `jit` mode the default when no mode is specified
* unify JIT and AOT codepaths
* ensure `Object.entries` on undefined doesn't break
It could be that sometimes you don't have values in your config (e.g.: `presets: []`), this in turn will break some plugins where we assume we have a value.
* drop AOT specific tests
These tests are all covered by JIT mode already and were AOT specific.
* simplify tests, and add a few
Some of the tests were written for AOT specifically, some were missing. We also updated the way we write those tests, essentially making Tailwind a blackbox, by testing against the final output.
Now that JIT mode is the default, this is super fast because we only generate what is used, instead of partially testing in a 3MB file or building it all, then purging.
* add some todo's to make sure we warn in a few cases
* make `darkMode: 'media'`, the default
This also includes moving dark mode tests to its own dedicated file.
* remove PostCSS 7 compat mode
* update CLI to be JIT-first
* fix integration tests
This is not a _real_ fix, but it does solve the broken test for now.
* warn when using @responsive or @variants
* remove the JIT preview warning
* remove AOT-only code paths
* remove all `mode: 'jit'` blocks
Also remove `variants: {}` since they are not useful in `JIT` mode
anymore.
* drop unused dependencies
* rename `purge` to `content`
* remove static CDN builds
* mark `--purge` as deprecated in the CLI
This will still work, but a warning will be printed and it won't show up
in the `--help` output.
* cleanup nesting plugin
We don't have to duplicate it anymore since there is no PostCSS 7
version anymore.
* make sure integration tests run in band
* cleanup folder structure
* make sure nesting folder is available
* simplify resolving of purge/content information
2021-09-01 17:13:59 +02:00
|
|
|
content: [path.resolve(__dirname, './basic-usage.test.html')],
|
2021-04-02 11:16:15 -04:00
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-29 13:31:06 +02:00
|
|
|
let input = css`
|
2021-04-02 11:16:15 -04:00
|
|
|
@tailwind base;
|
|
|
|
|
@tailwind components;
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
2021-07-29 13:31:06 +02:00
|
|
|
return run(input, config).then((result) => {
|
2021-04-02 11:16:15 -04:00
|
|
|
let expectedPath = path.resolve(__dirname, './basic-usage.test.css')
|
|
|
|
|
let expected = fs.readFileSync(expectedPath, 'utf8')
|
|
|
|
|
|
2021-04-02 13:51:48 -04:00
|
|
|
expect(result.css).toMatchFormattedCss(expected)
|
2021-04-02 11:16:15 -04:00
|
|
|
})
|
|
|
|
|
})
|
2021-12-15 18:07:26 +01:00
|
|
|
|
|
|
|
|
test('all plugins are executed that match a candidate', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
content: [{ raw: html`<div class="bg-green-light bg-green"></div>` }],
|
|
|
|
|
theme: {
|
|
|
|
|
colors: {
|
|
|
|
|
green: {
|
|
|
|
|
light: 'green',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
|
|
|
|
|
.bg-green {
|
|
|
|
|
/* Empty on purpose */
|
|
|
|
|
}
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
.bg-green-light {
|
|
|
|
|
--tw-bg-opacity: 1;
|
|
|
|
|
background-color: rgb(0 128 0 / var(--tw-bg-opacity));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.bg-green {
|
|
|
|
|
/* Empty on purpose */
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
2021-12-16 16:19:54 -05:00
|
|
|
|
|
|
|
|
test('per-plugin colors with the same key can differ when using a custom colors object', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
content: [
|
|
|
|
|
{
|
|
|
|
|
raw: html`
|
|
|
|
|
<div class="bg-theme text-theme">This should be green text on red background.</div>
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
theme: {
|
|
|
|
|
// colors & theme MUST be plain objects
|
|
|
|
|
// If they're functions here the test passes regardless
|
|
|
|
|
colors: {
|
|
|
|
|
theme: {
|
|
|
|
|
bg: 'red',
|
|
|
|
|
text: 'green',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
extend: {
|
|
|
|
|
textColor: {
|
|
|
|
|
theme: {
|
|
|
|
|
DEFAULT: 'green',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
backgroundColor: {
|
|
|
|
|
theme: {
|
|
|
|
|
DEFAULT: 'red',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
.bg-theme {
|
|
|
|
|
--tw-bg-opacity: 1;
|
|
|
|
|
background-color: rgb(255 0 0 / var(--tw-bg-opacity));
|
|
|
|
|
}
|
|
|
|
|
.text-theme {
|
|
|
|
|
--tw-text-opacity: 1;
|
|
|
|
|
color: rgb(0 128 0 / var(--tw-text-opacity));
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
2022-01-05 16:37:07 -05:00
|
|
|
|
2022-02-22 16:51:04 -05:00
|
|
|
test('default ring color can be a function', () => {
|
|
|
|
|
function color(variable) {
|
|
|
|
|
return function ({ opacityVariable, opacityValue }) {
|
|
|
|
|
if (opacityValue !== undefined) {
|
|
|
|
|
return `rgba(${variable}, ${opacityValue})`
|
|
|
|
|
}
|
|
|
|
|
if (opacityVariable !== undefined) {
|
|
|
|
|
return `rgba(${variable}, var(${opacityVariable}, 1))`
|
|
|
|
|
}
|
|
|
|
|
return `rgb(${variable})`
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let config = {
|
|
|
|
|
content: [
|
|
|
|
|
{
|
|
|
|
|
raw: html` <div class="ring"></div> `,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
theme: {
|
|
|
|
|
extend: {
|
|
|
|
|
ringColor: {
|
|
|
|
|
DEFAULT: color('var(--red)'),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
plugins: [],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind base;
|
|
|
|
|
@tailwind components;
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
2022-06-09 16:26:18 -04:00
|
|
|
${defaults({ defaultRingColor: 'rgba(var(--red), 0.5)' })}
|
2022-02-22 16:51:04 -05:00
|
|
|
.ring {
|
|
|
|
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
|
|
|
|
var(--tw-ring-offset-color);
|
|
|
|
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width))
|
|
|
|
|
var(--tw-ring-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
2022-06-09 16:26:18 -04:00
|
|
|
it('falsy config values still work', () => {
|
2022-01-05 16:37:07 -05:00
|
|
|
let config = {
|
|
|
|
|
content: [{ raw: html`<div class="inset-0"></div>` }],
|
|
|
|
|
theme: {
|
|
|
|
|
inset: {
|
|
|
|
|
0: 0,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
plugins: [],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
.inset-0 {
|
|
|
|
|
top: 0;
|
|
|
|
|
right: 0;
|
|
|
|
|
bottom: 0;
|
|
|
|
|
left: 0;
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
2022-02-01 11:54:03 -05:00
|
|
|
|
|
|
|
|
it('shadows support values without a leading zero', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
content: [{ raw: html`<div class="shadow-one shadow-two"></div>` }],
|
|
|
|
|
theme: {
|
|
|
|
|
boxShadow: {
|
|
|
|
|
one: '0.5rem 0.5rem 0.5rem #0005',
|
|
|
|
|
two: '.5rem .5rem .5rem #0005',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
plugins: [],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
.shadow-one {
|
|
|
|
|
--tw-shadow: 0.5rem 0.5rem 0.5rem #0005;
|
|
|
|
|
--tw-shadow-colored: 0.5rem 0.5rem 0.5rem var(--tw-shadow-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
|
|
|
|
var(--tw-shadow);
|
|
|
|
|
}
|
|
|
|
|
.shadow-two {
|
|
|
|
|
--tw-shadow: 0.5rem 0.5rem 0.5rem #0005;
|
|
|
|
|
--tw-shadow-colored: 0.5rem 0.5rem 0.5rem var(--tw-shadow-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
|
|
|
|
var(--tw-shadow);
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
2022-02-07 09:52:54 -05:00
|
|
|
|
|
|
|
|
it('can scan extremely long classes without crashing', () => {
|
|
|
|
|
let val = 'cols-' + '-a'.repeat(65536)
|
|
|
|
|
let config = {
|
|
|
|
|
content: [{ raw: html`<div class="${val}"></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css``)
|
|
|
|
|
})
|
|
|
|
|
})
|
2022-02-15 13:44:19 -05:00
|
|
|
|
|
|
|
|
it('does not produce duplicate output when seeing variants preceding a wildcard (*)', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
content: [{ raw: html`underline focus:*` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind base;
|
|
|
|
|
@tailwind components;
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
|
|
|
|
|
* {
|
|
|
|
|
color: red;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.combined,
|
|
|
|
|
* {
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@layer base {
|
|
|
|
|
* {
|
|
|
|
|
color: blue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.combined,
|
|
|
|
|
* {
|
|
|
|
|
color: red;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
* {
|
|
|
|
|
color: blue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.combined,
|
|
|
|
|
* {
|
|
|
|
|
color: red;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
${defaults}
|
|
|
|
|
|
|
|
|
|
.underline {
|
|
|
|
|
text-decoration-line: underline;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
* {
|
|
|
|
|
color: red;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.combined,
|
|
|
|
|
* {
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
2022-02-23 11:31:55 -05:00
|
|
|
|
2022-03-17 16:35:40 +01:00
|
|
|
it('can parse box shadows with variables', () => {
|
2022-02-23 11:31:55 -05:00
|
|
|
let config = {
|
|
|
|
|
content: [{ raw: html`<div class="shadow-lg"></div>` }],
|
|
|
|
|
theme: {
|
|
|
|
|
boxShadow: {
|
WIP: New `@apply` logic
use `lightningcss` and `prettier` for `toMatchFormattedCss`
Lightning CSS applies some optimizations and prettier ensures that the
output is always formatted in the same way.
In a future version, we will be using Lightning CSS to apply
optimizations like handling the nesting, optimizing selectors, sorting
declarations, simplifying colors and so on.
To guarantee that we have the same output in both the normal version and
OXIDE version, we can apply lightningcss in our tests so that it always
produces correct results in both version with the same optimizations
applied.
This also aliases `toMatchCss` to `toMatchFormattedCss` so that we can
guarantee the same output. This has a small caveat where `lightningcss`
is pretty strict. It will complain about `@media screen(md) {}` for
example. This is correct because it is not valid CSS, but we eventually
take care of it.
In this case, we will catch the error and use prettier instead (since
this should only happen in tests that doesn't use end-to-end tests, but
uses a more specialized test instead). If prettier still finds an error,
we will ensure to throw the original error.
Eventually, all the "lower" level tests, should probably become higher
level end-to-end tests. But let's do everything step by step!
2022-12-08 15:07:06 +01:00
|
|
|
lg: 'var(--a, 0 35px 60px -15px rgba(0, 0, 0)), 0 0 1px rgb(0, 0, 0)',
|
2022-02-23 11:31:55 -05:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
.shadow-lg {
|
WIP: New `@apply` logic
use `lightningcss` and `prettier` for `toMatchFormattedCss`
Lightning CSS applies some optimizations and prettier ensures that the
output is always formatted in the same way.
In a future version, we will be using Lightning CSS to apply
optimizations like handling the nesting, optimizing selectors, sorting
declarations, simplifying colors and so on.
To guarantee that we have the same output in both the normal version and
OXIDE version, we can apply lightningcss in our tests so that it always
produces correct results in both version with the same optimizations
applied.
This also aliases `toMatchCss` to `toMatchFormattedCss` so that we can
guarantee the same output. This has a small caveat where `lightningcss`
is pretty strict. It will complain about `@media screen(md) {}` for
example. This is correct because it is not valid CSS, but we eventually
take care of it.
In this case, we will catch the error and use prettier instead (since
this should only happen in tests that doesn't use end-to-end tests, but
uses a more specialized test instead). If prettier still finds an error,
we will ensure to throw the original error.
Eventually, all the "lower" level tests, should probably become higher
level end-to-end tests. But let's do everything step by step!
2022-12-08 15:07:06 +01:00
|
|
|
--tw-shadow: var(--a, 0 35px 60px -15px rgba(0, 0, 0)), 0 0 1px rgb(0, 0, 0);
|
2022-02-23 11:31:55 -05:00
|
|
|
--tw-shadow-colored: 0 35px 60px -15px var(--tw-shadow-color),
|
|
|
|
|
0 0 1px var(--tw-shadow-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
|
|
|
|
var(--tw-shadow);
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
2022-03-17 16:35:40 +01:00
|
|
|
|
|
|
|
|
it('should generate styles using :not(.unknown-class) even if `.unknown-class` does not exist', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
content: [{ raw: html`<div></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind components;
|
|
|
|
|
|
|
|
|
|
@layer components {
|
|
|
|
|
div:not(.unknown-class) {
|
|
|
|
|
color: red;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
div:not(.unknown-class) {
|
|
|
|
|
color: red;
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
2022-05-04 16:08:25 -04:00
|
|
|
|
|
|
|
|
it('supports multiple backgrounds as arbitrary values even if only some are quoted', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
content: [
|
|
|
|
|
{
|
|
|
|
|
raw: html`<div
|
|
|
|
|
class="bg-[url('/images/one-two-three.png'),linear-gradient(to_right,_#eeeeee,_#000000)]"
|
|
|
|
|
></div>`,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
WIP: New `@apply` logic
use `lightningcss` and `prettier` for `toMatchFormattedCss`
Lightning CSS applies some optimizations and prettier ensures that the
output is always formatted in the same way.
In a future version, we will be using Lightning CSS to apply
optimizations like handling the nesting, optimizing selectors, sorting
declarations, simplifying colors and so on.
To guarantee that we have the same output in both the normal version and
OXIDE version, we can apply lightningcss in our tests so that it always
produces correct results in both version with the same optimizations
applied.
This also aliases `toMatchCss` to `toMatchFormattedCss` so that we can
guarantee the same output. This has a small caveat where `lightningcss`
is pretty strict. It will complain about `@media screen(md) {}` for
example. This is correct because it is not valid CSS, but we eventually
take care of it.
In this case, we will catch the error and use prettier instead (since
this should only happen in tests that doesn't use end-to-end tests, but
uses a more specialized test instead). If prettier still finds an error,
we will ensure to throw the original error.
Eventually, all the "lower" level tests, should probably become higher
level end-to-end tests. But let's do everything step by step!
2022-12-08 15:07:06 +01:00
|
|
|
.bg-\[url\(\'\/images\/one-two-three\.png\'\)\,
|
|
|
|
|
linear-gradient\(to_right\,
|
|
|
|
|
_\#eeeeee\,
|
2022-05-04 16:08:25 -04:00
|
|
|
_\#000000\)\] {
|
WIP: New `@apply` logic
use `lightningcss` and `prettier` for `toMatchFormattedCss`
Lightning CSS applies some optimizations and prettier ensures that the
output is always formatted in the same way.
In a future version, we will be using Lightning CSS to apply
optimizations like handling the nesting, optimizing selectors, sorting
declarations, simplifying colors and so on.
To guarantee that we have the same output in both the normal version and
OXIDE version, we can apply lightningcss in our tests so that it always
produces correct results in both version with the same optimizations
applied.
This also aliases `toMatchCss` to `toMatchFormattedCss` so that we can
guarantee the same output. This has a small caveat where `lightningcss`
is pretty strict. It will complain about `@media screen(md) {}` for
example. This is correct because it is not valid CSS, but we eventually
take care of it.
In this case, we will catch the error and use prettier instead (since
this should only happen in tests that doesn't use end-to-end tests, but
uses a more specialized test instead). If prettier still finds an error,
we will ensure to throw the original error.
Eventually, all the "lower" level tests, should probably become higher
level end-to-end tests. But let's do everything step by step!
2022-12-08 15:07:06 +01:00
|
|
|
background-image: url('/images/one-two-three.png'), linear-gradient(to right, #eee, #000);
|
2022-05-04 16:08:25 -04:00
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
2022-05-27 09:48:27 -04:00
|
|
|
|
|
|
|
|
it('The "default" ring opacity is used by the default ring color when not using respectDefaultRingColorOpacity (1)', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
content: [{ raw: html`<div class="ring"></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind base;
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
${defaults({ defaultRingColor: 'rgb(59 130 246 / 0.5)' })}
|
|
|
|
|
.ring {
|
|
|
|
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
|
|
|
|
var(--tw-ring-offset-color);
|
|
|
|
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width))
|
|
|
|
|
var(--tw-ring-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('The "default" ring opacity is used by the default ring color when not using respectDefaultRingColorOpacity (2)', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
content: [{ raw: html`<div class="ring"></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
theme: {
|
|
|
|
|
ringOpacity: {
|
|
|
|
|
DEFAULT: 0.75,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind base;
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
${defaults({ defaultRingColor: 'rgb(59 130 246 / 0.75)' })}
|
|
|
|
|
.ring {
|
|
|
|
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
|
|
|
|
var(--tw-ring-offset-color);
|
|
|
|
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width))
|
|
|
|
|
var(--tw-ring-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('Customizing the default ring color uses the "default" opacity when not using respectDefaultRingColorOpacity (1)', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
content: [{ raw: html`<div class="ring"></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
theme: {
|
|
|
|
|
ringColor: {
|
|
|
|
|
DEFAULT: '#ff7f7f',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind base;
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
${defaults({ defaultRingColor: 'rgb(255 127 127 / 0.5)' })}
|
|
|
|
|
.ring {
|
|
|
|
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
|
|
|
|
var(--tw-ring-offset-color);
|
|
|
|
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width))
|
|
|
|
|
var(--tw-ring-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('Customizing the default ring color uses the "default" opacity when not using respectDefaultRingColorOpacity (2)', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
content: [{ raw: html`<div class="ring"></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
theme: {
|
|
|
|
|
ringColor: {
|
|
|
|
|
DEFAULT: '#ff7f7f00',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind base;
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
${defaults({ defaultRingColor: 'rgb(255 127 127 / 0.5)' })}
|
|
|
|
|
.ring {
|
|
|
|
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
|
|
|
|
var(--tw-ring-offset-color);
|
|
|
|
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width))
|
|
|
|
|
var(--tw-ring-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('The "default" ring color ignores the default opacity when using respectDefaultRingColorOpacity (1)', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
future: { respectDefaultRingColorOpacity: true },
|
|
|
|
|
content: [{ raw: html`<div class="ring"></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind base;
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
${defaults({ defaultRingColor: '#3b82f67f' })}
|
|
|
|
|
.ring {
|
|
|
|
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
|
|
|
|
var(--tw-ring-offset-color);
|
|
|
|
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width))
|
|
|
|
|
var(--tw-ring-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('The "default" ring color ignores the default opacity when using respectDefaultRingColorOpacity (2)', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
future: { respectDefaultRingColorOpacity: true },
|
|
|
|
|
content: [{ raw: html`<div class="ring"></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
theme: {
|
|
|
|
|
ringOpacity: {
|
|
|
|
|
DEFAULT: 0.75,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind base;
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
${defaults({ defaultRingColor: '#3b82f67f' })}
|
|
|
|
|
.ring {
|
|
|
|
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
|
|
|
|
var(--tw-ring-offset-color);
|
|
|
|
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width))
|
|
|
|
|
var(--tw-ring-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('Customizing the default ring color preserves its opacity when using respectDefaultRingColorOpacity (1)', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
future: { respectDefaultRingColorOpacity: true },
|
|
|
|
|
content: [{ raw: html`<div class="ring"></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
theme: {
|
|
|
|
|
ringColor: {
|
|
|
|
|
DEFAULT: '#ff7f7f',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind base;
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
${defaults({ defaultRingColor: '#ff7f7f' })}
|
|
|
|
|
.ring {
|
|
|
|
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
|
|
|
|
var(--tw-ring-offset-color);
|
|
|
|
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width))
|
|
|
|
|
var(--tw-ring-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('Customizing the default ring color preserves its opacity when using respectDefaultRingColorOpacity (2)', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
future: { respectDefaultRingColorOpacity: true },
|
|
|
|
|
content: [{ raw: html`<div class="ring"></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
theme: {
|
|
|
|
|
ringColor: {
|
|
|
|
|
DEFAULT: '#ff7f7f00',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind base;
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
${defaults({ defaultRingColor: '#ff7f7f00' })}
|
|
|
|
|
.ring {
|
|
|
|
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
|
|
|
|
var(--tw-ring-offset-color);
|
|
|
|
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width))
|
|
|
|
|
var(--tw-ring-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
2022-05-27 09:59:52 -04:00
|
|
|
|
|
|
|
|
it('A bare ring-opacity utility is not supported when not using respectDefaultRingColorOpacity', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
content: [{ raw: html`<div class="ring-opacity"></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
theme: {
|
|
|
|
|
ringOpacity: {
|
|
|
|
|
DEFAULT: '0.33',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css``)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('A bare ring-opacity utility is supported when using respectDefaultRingColorOpacity', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
future: { respectDefaultRingColorOpacity: true },
|
|
|
|
|
content: [{ raw: html`<div class="ring-opacity"></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
theme: {
|
|
|
|
|
ringOpacity: {
|
|
|
|
|
DEFAULT: '0.33',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
.ring-opacity {
|
|
|
|
|
--tw-ring-opacity: 0.33;
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|
2022-08-10 10:36:04 -04:00
|
|
|
|
|
|
|
|
it('Ring color utilities are generated when using respectDefaultRingColorOpacity', () => {
|
|
|
|
|
let config = {
|
|
|
|
|
future: { respectDefaultRingColorOpacity: true },
|
|
|
|
|
content: [{ raw: html`<div class="ring ring-blue-500"></div>` }],
|
|
|
|
|
corePlugins: { preflight: false },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let input = css`
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
return run(input, config).then((result) => {
|
|
|
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
|
|
|
.ring {
|
|
|
|
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
|
|
|
|
var(--tw-ring-offset-color);
|
|
|
|
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width))
|
|
|
|
|
var(--tw-ring-color);
|
|
|
|
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
|
|
|
}
|
|
|
|
|
.ring-blue-500 {
|
|
|
|
|
--tw-ring-opacity: 1;
|
|
|
|
|
--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
|
|
|
|
|
}
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
})
|