tailwindcss/tests/source-maps.test.js
Robin Malfait 352c563d99
Fix source maps issue resulting in a crash (#11319)
* only try to pretty print `err.source` if it exists

* fix small typo

* drop unnecessary path resolving

* add `from` and `to` to `run` test helper

* enable all source map tests

* ensure source maps are generated properly

* update annotation values in tests

* handle `map: true`

* add test for `map: { inline: true }`

* force Lightning CSS to handle an inline source map

* base64 encode the test name

This will get rid of special characters that can cause issues /
confusion when debugging tests.

* ensure utilities and components with variants are pointing to the correct source

Co-authored-by: Jordan Pittman <jordan@cryptica.me>

* update changelog

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2023-05-31 18:28:11 +02:00

485 lines
12 KiB
JavaScript

import postcss from 'postcss'
import { parseSourceMaps } from './util/source-maps'
import { runWithSourceMaps as run, html, css, map } from './util/run'
test('apply generates source maps', async () => {
let config = {
content: [
{
raw: html`
<div class="with-declaration"></div>
<div class="with-comment"></div>
<div class="just-apply"></div>
`,
},
],
corePlugins: { preflight: false },
}
let input = css`
.with-declaration {
background-color: red;
@apply h-4 w-4 bg-green-500;
}
.with-comment {
/* sourcemap will work here too */
@apply h-4 w-4 bg-red-500;
}
.just-apply {
@apply h-4 w-4 bg-black;
}
`
let result = await run(input, config)
let { sources, annotations } = parseSourceMaps(result)
// All CSS generated by Tailwind CSS should be annotated with source maps
// And always be able to point to the original source file
expect(sources).not.toContain('<no source>')
expect(sources.length).toBe(2)
expect(annotations).toMatchInlineSnapshot(`
[
"2:4 -> 1:0",
"2:2-14 -> 2:2-14",
"3:2-13 -> 3:2-13",
"4:2-20 -> 4:2-20",
"5:2-23 -> 5:2-23",
"6:2-57 -> 6:2-57",
"7:0 -> 7:0",
"7:4 -> 9:0",
"10:2-14 -> 10:2-14",
"11:2-13 -> 11:2-13",
"12:2-20 -> 12:2-20",
"13:2-57 -> 13:2-57",
"14:0 -> 14:0",
"13:6 -> 16:0",
"17:2-14 -> 17:2-14",
"18:2-13 -> 18:2-13",
"19:2-20 -> 19:2-20",
"20:2-53 -> 20:2-53",
"21:0 -> 21:0",
]
`)
})
test('preflight + base have source maps', async () => {
let config = {
content: [],
}
let input = css`
@tailwind base;
`
let result = await run(input, config)
let { sources, annotations } = parseSourceMaps(result)
// All CSS generated by Tailwind CSS should be annotated with source maps
// And always be able to point to the original source file
expect(sources).not.toContain('<no source>')
expect(sources.length).toBe(2)
expect(annotations).toMatchInlineSnapshot(`
[
"2:4 -> 1:0",
"2:2-24 -> 2:2-24",
"3:2-25 -> 3:2-25",
"4:0 -> 4:0",
"2:4 -> 6:0",
"7:2-18 -> 7:2-18",
"8:0 -> 8:0",
"2:4 -> 10:0",
"11:2-32 -> 11:2-32",
"12:2-13 -> 12:2-13",
"13:2-31 -> 13:2-31",
"14:2-33 -> 14:2-33",
"15:2-208 -> 15:2-208",
"16:2-18 -> 16:2-18",
"17:0 -> 17:0",
"2:4 -> 19:0",
"20:2-22 -> 20:2-22",
"21:2-11 -> 21:2-11",
"22:0 -> 22:0",
"2:4 -> 24:0",
"25:2-11 -> 25:2-11",
"26:2-16 -> 26:2-16",
"27:2-23 -> 27:2-23",
"28:0 -> 28:0",
"2:4 -> 30:0",
"31:2-35 -> 31:2-35",
"32:0 -> 32:0",
"2:4 -> 34:0",
"35:2-20 -> 35:2-20",
"36:2-22 -> 36:2-22",
"37:0 -> 37:0",
"2:4 -> 39:0",
"40:2-16 -> 40:2-16",
"41:2-26 -> 41:2-26",
"42:0 -> 42:0",
"2:4 -> 44:0",
"45:2-21 -> 45:2-21",
"46:0 -> 46:0",
"2:4 -> 48:0",
"49:2-109 -> 49:2-109",
"50:2-16 -> 50:2-16",
"51:0 -> 51:0",
"2:4 -> 53:0",
"54:2-16 -> 54:2-16",
"55:0 -> 55:0",
"2:4 -> 57:0",
"58:2-26 -> 58:2-26",
"59:2-16 -> 59:2-16",
"60:2-16 -> 60:2-16",
"61:2-20 -> 61:2-20",
"62:0 -> 62:0",
"2:4 -> 64:0",
"65:2-16 -> 65:2-16",
"66:0 -> 66:0",
"2:4 -> 68:0",
"69:2-12 -> 69:2-12",
"70:0 -> 70:0",
"2:4 -> 72:0",
"73:2-16 -> 73:2-16",
"74:2-23 -> 74:2-23",
"75:2-27 -> 75:2-27",
"76:0 -> 76:0",
"2:4 -> 78:0",
"79:2-32 -> 79:2-32",
"80:2-34 -> 80:2-34",
"81:2-22 -> 81:2-22",
"82:2-17 -> 82:2-17",
"83:2-22 -> 83:2-22",
"84:2-22 -> 84:2-22",
"85:2-16 -> 85:2-16",
"86:2-11 -> 86:2-11",
"87:2-12 -> 87:2-12",
"88:0 -> 88:0",
"2:4 -> 90:0",
"91:2-22 -> 91:2-22",
"92:0 -> 92:0",
"2:4 -> 94:0",
"95:2-28 -> 95:2-28",
"96:2-25 -> 96:2-25",
"97:2-24 -> 97:2-24",
"98:0 -> 98:0",
"2:4 -> 100:0",
"101:2-15 -> 101:2-15",
"102:0 -> 102:0",
"2:4 -> 104:0",
"105:2-18 -> 105:2-18",
"106:0 -> 106:0",
"2:4 -> 108:0",
"109:2-26 -> 109:2-26",
"110:0 -> 110:0",
"2:4 -> 112:0",
"113:2-14 -> 113:2-14",
"114:0 -> 114:0",
"2:4 -> 116:0",
"117:2-31 -> 117:2-31",
"118:2-22 -> 118:2-22",
"119:0 -> 119:0",
"2:4 -> 121:0",
"122:2-26 -> 122:2-26",
"123:0 -> 123:0",
"2:4 -> 125:0",
"126:2-28 -> 126:2-28",
"127:2-15 -> 127:2-15",
"128:0 -> 128:0",
"2:4 -> 130:0",
"131:2-20 -> 131:2-20",
"132:0 -> 132:0",
"2:4 -> 134:0",
"135:2-11 -> 135:2-11",
"136:0 -> 136:0",
"2:4 -> 138:0",
"139:2-11 -> 139:2-11",
"140:2-12 -> 140:2-12",
"141:0 -> 141:0",
"2:4 -> 143:0",
"144:2-12 -> 144:2-12",
"145:0 -> 145:0",
"2:4 -> 147:0",
"148:2-11 -> 148:2-11",
"149:2-12 -> 149:2-12",
"150:2-18 -> 150:2-18",
"151:0 -> 151:0",
"2:4 -> 153:0",
"154:2-12 -> 154:2-12",
"155:0 -> 155:0",
"2:4 -> 157:0",
"158:2-18 -> 158:2-18",
"159:0 -> 159:0",
"2:4 -> 161:0",
"162:2-12 -> 162:2-12",
"163:2-16 -> 163:2-16",
"164:0 -> 164:0",
"2:4 -> 166:0",
"167:2-17 -> 167:2-17",
"168:0 -> 168:0",
"2:4 -> 170:0",
"171:2-17 -> 171:2-17",
"172:0 -> 172:0",
"2:4 -> 174:0",
"175:2-24 -> 175:2-24",
"176:2-16 -> 176:2-16",
"177:0 -> 177:0",
"2:4 -> 179:0",
"180:2-17 -> 180:2-17",
"181:2-14 -> 181:2-14",
"182:0 -> 182:0",
"2:4 -> 184:0",
"185:2-15 -> 185:2-15",
"186:0 -> 186:0",
"2:4 -> 188:0",
"189:2-26 -> 189:2-26",
"190:2-26 -> 190:2-26",
"191:2-21 -> 191:2-21",
"192:2-21 -> 192:2-21",
"193:2-16 -> 193:2-16",
"194:2-16 -> 194:2-16",
"195:2-16 -> 195:2-16",
"196:2-17 -> 196:2-17",
"197:2-17 -> 197:2-17",
"198:2-14 -> 198:2-14",
"199:2-14 -> 199:2-14",
"200:2-19 -> 200:2-19",
"201:2-40 -> 201:2-40",
"202:2-31 -> 202:2-31",
"203:2-30 -> 203:2-30",
"204:2-29 -> 204:2-29",
"205:2-16 -> 205:2-16",
"206:2-21 -> 206:2-21",
"207:2-23 -> 207:2-23",
"208:2-24 -> 208:2-24",
"209:2-25 -> 209:2-25",
"210:2-19 -> 210:2-19",
"211:2-29 -> 211:2-29",
"212:2-30 -> 212:2-30",
"213:2-28 -> 213:2-28",
"214:2-36 -> 214:2-36",
"215:2-29 -> 215:2-29",
"216:2-24 -> 216:2-24",
"217:2-32 -> 217:2-32",
"218:2-13 -> 218:2-13",
"219:2-19 -> 219:2-19",
"220:2-17 -> 220:2-17",
"221:2-18 -> 221:2-18",
"222:2-19 -> 222:2-19",
"223:2-15 -> 223:2-15",
"224:2-17 -> 224:2-17",
"225:2-14 -> 225:2-14",
"226:2-20 -> 226:2-20",
"227:2-22 -> 227:2-22",
"228:2-28 -> 228:2-28",
"229:2-26 -> 229:2-26",
"230:2-27 -> 230:2-27",
"231:2-28 -> 231:2-28",
"232:2-24 -> 232:2-24",
"233:2-25 -> 233:2-25",
"234:2-26 -> 234:2-26",
"235:2-23 -> 235:2-23",
"236:0 -> 236:0",
]
`)
})
test('utilities have source maps', async () => {
let config = {
content: [{ raw: `text-red-500` }],
}
let input = css`
@tailwind utilities;
`
let result = await run(input, config)
let { sources, annotations } = parseSourceMaps(result)
// All CSS generated by Tailwind CSS should be annotated with source maps
// And always be able to point to the original source file
expect(sources).not.toContain('<no source>')
expect(sources.length).toBe(2)
expect(annotations).toMatchInlineSnapshot(`
[
"2:4 -> 1:0",
"2:2-22 -> 2:2-22",
"3:2-48 -> 3:2-48",
"4:0 -> 4:0",
]
`)
})
test('components have source maps', async () => {
let config = {
content: [{ raw: `container` }],
}
let input = css`
@tailwind components;
`
let result = await run(input, config)
let { sources, annotations } = parseSourceMaps(result)
// All CSS generated by Tailwind CSS should be annotated with source maps
// And always be able to point to the original source file
expect(sources).not.toContain('<no source>')
expect(sources.length).toBe(2)
expect(annotations).toMatchInlineSnapshot(`
[
"2:4 -> 1:0",
"2:2-13 -> 2:2-13",
"3:0 -> 3:0",
"2:4 -> 5:0",
"2:4 -> 6:2",
"7:4-20 -> 7:4-20",
"8:2 -> 8:2",
"9:0 -> 9:0",
"2:4 -> 11:0",
"2:4 -> 12:2",
"13:4-20 -> 13:4-20",
"14:2 -> 14:2",
"15:0 -> 15:0",
"2:4 -> 17:0",
"2:4 -> 18:2",
"19:4-21 -> 19:4-21",
"20:2 -> 20:2",
"21:0 -> 21:0",
"2:4 -> 23:0",
"2:4 -> 24:2",
"25:4-21 -> 25:4-21",
"26:2 -> 26:2",
"27:0 -> 27:0",
"2:4 -> 29:0",
"2:4 -> 30:2",
"31:4-21 -> 31:4-21",
"32:2 -> 32:2",
"33:0 -> 33:0",
]
`)
})
test('source maps for layer rules are not rewritten to point to @tailwind directives', async () => {
let config = {
content: [{ raw: `font-normal foo hover:foo` }],
}
let utilitiesFile = postcss.parse(
css`
@tailwind utilities;
`,
{ from: 'components.css', map: { prev: map } }
)
let mainCssFile = postcss.parse(
css`
@layer utilities {
.foo {
background-color: red;
}
}
`,
{ from: 'input.css', map: { prev: map } }
)
// Just pretend that there's an @import in `mainCssFile` that imports the nodes from `utilitiesFile`
let input = postcss.root({
nodes: [...utilitiesFile.nodes, ...mainCssFile.nodes],
source: mainCssFile.source,
})
let result = await run(input, config)
let { sources, annotations } = parseSourceMaps(result)
// All CSS generated by Tailwind CSS should be annotated with source maps
// And always be able to point to the original source file
expect(sources).not.toContain('<no source>')
// And we should see that the source map for the layer rule is not rewritten
// to point to the @tailwind directive but instead points to the original
expect(sources.length).toBe(3)
expect(sources).toMatchInlineSnapshot(`
[
"components.css",
"source-maps.test.js%3Ftest=c291cmNlIG1hcHMgZm9yIGxheWVyIHJ1bGVzIGFyZSBub3QgcmV3cml0dGVuIHRvIHBvaW50IHRvIEB0YWlsd2luZCBkaXJlY3RpdmVz",
"input.css",
]
`)
expect(annotations).toMatchInlineSnapshot(`
[
"2:6 -> 1:0",
"2:2-18 -> 2:2-18",
"3:0 -> 3:0",
"3:8 -> 5:0",
"6:2-23 -> 6:2-23",
"7:0 -> 7:0",
]
`)
})
test('it handles `map: true` correctly', async () => {
let config = {
content: [{ raw: `text-red-500` }],
}
let input = css`
@tailwind utilities;
`
let result = await run(input, config, {
map: true,
})
let { sources, annotations } = parseSourceMaps(result)
// All CSS generated by Tailwind CSS should be annotated with source maps
// And always be able to point to the original source file
expect(sources).not.toContain('<no source>')
expect(sources.length).toBe(2)
expect(annotations).toMatchInlineSnapshot(`
[
"2:4 -> 1:0",
"2:2-22 -> 2:2-22",
"3:2-48 -> 3:2-48",
"4:0 -> 4:0",
]
`)
})
test('it handles `map: { inline: true }` correctly', async () => {
let config = {
content: [{ raw: `text-red-500` }],
}
let input = css`
@tailwind utilities;
`
let result = await run(input, config, {
map: {
inline: true,
},
})
let { sources, annotations } = parseSourceMaps(result)
// All CSS generated by Tailwind CSS should be annotated with source maps
// And always be able to point to the original source file
expect(sources).not.toContain('<no source>')
expect(sources.length).toBe(2)
expect(annotations).toMatchInlineSnapshot(`
[
"2:4 -> 1:0",
"2:2-22 -> 2:2-22",
"3:2-48 -> 3:2-48",
"4:0 -> 4:0",
]
`)
})