Setup integration tests (#5466)
* setup integration tests * fix rgb color syntax * ensure integration tests always exit If for any reason the integration tests fail, then it will run forever on CI (~2hours or something). The `--forceExit` is not ideal but it will prevent long running processes. * fix incorrect test We were never properly waiting for the command to finish. * handle AbortError properly In CI, when an AbortController gets aborted an error is thrown (AbortError). If we don't catch it properly then it will "leak" and the test will fail. * improve IO functions * quit integration tests after 10seconds * only test a few integrations * test all integrations using matrix This will cancel other builds when one fails, it will also separate the output per integration which can be useful especially now that we are still figuring things out. * rename `build` to `test` * add --verbose flag to receive output in the console * when reading stdout or stderr, wait a certain about to ensure stability Debouncing for 200ms means that if another message comes in within those 200ms we delay the execution of the callback. * simplify workflow * use terminal output instead of disk events * cache node_modules for integrations * empty commit, to test cache hits
This commit is contained in:
parent
fda1c4403f
commit
516ba530f0
26 changed files with 298 additions and 227 deletions
59
.github/workflows/integration-tests.yml
vendored
Normal file
59
.github/workflows/integration-tests.yml
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
name: Integration Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
integration: [parcel, postcss-cli, rollup, tailwindcss-cli, vite, webpack-4, webpack-5]
|
||||
node-version: [16]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Use cached node_modules (tailwindcss)
|
||||
id: cache-tailwindcss
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: node_modules
|
||||
key: nodeModules-${{ hashFiles('**/package-lock.json') }}-${{ matrix.node-version }}-tailwindcss
|
||||
restore-keys: |
|
||||
nodeModules-
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.cache-tailwindcss.outputs.cache-hit != 'true'
|
||||
run: npm install
|
||||
env:
|
||||
CI: true
|
||||
|
||||
- name: Build Tailwind CSS
|
||||
run: npm run prepublishOnly
|
||||
|
||||
- name: Use cached node_modules (integrations)
|
||||
id: cache-integrations
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ./integrations/**/node_modules
|
||||
key: nodeModules-${{ hashFiles('**/package-lock.json') }}-${{ matrix.node-version }}-${{ matrix.integration }}-integrations
|
||||
restore-keys: |
|
||||
nodeModules-
|
||||
|
||||
- name: Install shared dependencies
|
||||
if: steps.cache-integrations.outputs.cache-hit != 'true'
|
||||
run: npm run install:integrations
|
||||
env:
|
||||
CI: true
|
||||
|
||||
- name: Test ${{ matrix.integration }}
|
||||
run: npm test --prefix ./integrations/${{ matrix.integration }}
|
||||
|
|
@ -8,6 +8,15 @@ afterEach(() => {
|
|||
runningProcessess.splice(0).forEach((runningProcess) => runningProcess.stop())
|
||||
})
|
||||
|
||||
function debounce(fn, ms) {
|
||||
let state = { timer: undefined }
|
||||
|
||||
return (...args) => {
|
||||
if (state.timer) clearTimeout(state.timer)
|
||||
state.timer = setTimeout(() => fn(...args), ms)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function $(command, options = {}) {
|
||||
let abortController = new AbortController()
|
||||
let cwd = resolveToolRoot()
|
||||
|
|
@ -37,13 +46,13 @@ module.exports = function $(command, options = {}) {
|
|||
}
|
||||
}
|
||||
|
||||
function notifyNextStdoutActor() {
|
||||
let notifyNextStdoutActor = debounce(() => {
|
||||
return notifyNext(stdoutActors, stdoutMessages)
|
||||
}
|
||||
}, 200)
|
||||
|
||||
function notifyNextStderrActor() {
|
||||
let notifyNextStderrActor = debounce(() => {
|
||||
return notifyNext(stderrActors, stderrMessages)
|
||||
}
|
||||
}, 200)
|
||||
|
||||
let runningProcess = new Promise((resolve, reject) => {
|
||||
let child = spawn(command, args, {
|
||||
|
|
@ -74,6 +83,12 @@ module.exports = function $(command, options = {}) {
|
|||
combined += data
|
||||
})
|
||||
|
||||
child.on('error', (err) => {
|
||||
if (err.name !== 'AbortError') {
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
child.on('close', (code, signal) => {
|
||||
;(signal === 'SIGTERM' ? resolve : code === 0 ? resolve : reject)({
|
||||
code,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,17 @@ let chokidar = require('chokidar')
|
|||
|
||||
let resolveToolRoot = require('./resolve-tool-root')
|
||||
|
||||
function getWatcherOptions() {
|
||||
return {
|
||||
usePolling: true,
|
||||
interval: 200,
|
||||
awaitWriteFinish: {
|
||||
stabilityThreshold: 1500,
|
||||
pollInterval: 50,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function ({
|
||||
/** Output directory, relative to the tool. */
|
||||
output = 'dist',
|
||||
|
|
@ -95,6 +106,10 @@ module.exports = function ({
|
|||
file = await resolveFile(file, absoluteOutputFolder)
|
||||
return fs.readFile(path.resolve(absoluteOutputFolder, file), 'utf8')
|
||||
},
|
||||
async readInputFile(file) {
|
||||
file = await resolveFile(file, absoluteInputFolder)
|
||||
return fs.readFile(path.resolve(absoluteInputFolder, file), 'utf8')
|
||||
},
|
||||
async appendToInputFile(file, contents) {
|
||||
let filePath = path.resolve(absoluteInputFolder, file)
|
||||
if (!fileCache[filePath]) {
|
||||
|
|
@ -122,48 +137,41 @@ module.exports = function ({
|
|||
async waitForOutputFileCreation(file) {
|
||||
if (file instanceof RegExp) {
|
||||
let r = file
|
||||
let watcher = chokidar.watch(absoluteOutputFolder)
|
||||
let watcher = chokidar.watch(absoluteOutputFolder, getWatcherOptions())
|
||||
|
||||
return new Promise((resolve) => {
|
||||
watcher.on('add', (file) => {
|
||||
if (r.test(file)) {
|
||||
watcher.close()
|
||||
resolve()
|
||||
watcher.close().then(() => resolve())
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
let filePath = path.resolve(absoluteOutputFolder, file)
|
||||
let watcher = chokidar.watch(filePath)
|
||||
|
||||
let watcherPromise = new Promise((resolve) => {
|
||||
watcher.once('add', () => {
|
||||
watcher.close()
|
||||
resolve()
|
||||
return new Promise((resolve) => {
|
||||
let watcher = chokidar.watch(absoluteOutputFolder, getWatcherOptions())
|
||||
|
||||
watcher.on('add', (addedFile) => {
|
||||
if (addedFile !== filePath) return
|
||||
return watcher.close().finally(resolve)
|
||||
})
|
||||
})
|
||||
|
||||
if (existsSync(filePath)) {
|
||||
watcher.close()
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
return watcherPromise
|
||||
}
|
||||
},
|
||||
async waitForOutputFileChange(file, cb = () => {}) {
|
||||
file = await resolveFile(file, absoluteOutputFolder)
|
||||
|
||||
let filePath = path.resolve(absoluteOutputFolder, file)
|
||||
let watcher = chokidar.watch(filePath)
|
||||
|
||||
return new Promise((resolve) => {
|
||||
let chain = Promise.resolve()
|
||||
watcher.once('change', () => {
|
||||
watcher.close()
|
||||
chain.then(() => resolve())
|
||||
})
|
||||
chain.then(() => cb())
|
||||
let watcher = chokidar.watch(absoluteOutputFolder, getWatcherOptions())
|
||||
|
||||
watcher
|
||||
.on('change', (changedFile) => {
|
||||
if (changedFile !== filePath) return
|
||||
return watcher.close().finally(resolve)
|
||||
})
|
||||
.on('ready', cb)
|
||||
})
|
||||
},
|
||||
}
|
||||
|
|
|
|||
1
integrations/package-lock.json
generated
1
integrations/package-lock.json
generated
|
|
@ -5,6 +5,7 @@
|
|||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "integrations",
|
||||
"version": "0.0.0",
|
||||
"devDependencies": {
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"test": "jest --runInBand"
|
||||
"test": "jest --runInBand --forceExit"
|
||||
},
|
||||
"jest": {
|
||||
"testTimeout": 30000,
|
||||
|
|
|
|||
1
integrations/parcel/package-lock.json
generated
1
integrations/parcel/package-lock.json
generated
|
|
@ -5,6 +5,7 @@
|
|||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "parcel",
|
||||
"version": "0.0.0",
|
||||
"devDependencies": {
|
||||
"parcel": "nightly"
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@
|
|||
"scripts": {
|
||||
"build": "parcel build ./src/index.html --no-cache",
|
||||
"dev": "parcel watch ./src/index.html --no-cache",
|
||||
"test": "jest --runInBand"
|
||||
"test": "jest --runInBand --forceExit"
|
||||
},
|
||||
"jest": {
|
||||
"testTimeout": 10000,
|
||||
"displayName": "parcel",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ describe.skip('watcher', () => {
|
|||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
|
|
@ -240,7 +240,7 @@ describe.skip('watcher', () => {
|
|||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
|
|
|
|||
1
integrations/postcss-cli/package-lock.json
generated
1
integrations/postcss-cli/package-lock.json
generated
|
|
@ -5,6 +5,7 @@
|
|||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "postcss-cli",
|
||||
"version": "0.0.0",
|
||||
"devDependencies": {
|
||||
"postcss": "^8.2.15",
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@
|
|||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production postcss ./src/index.css -o ./dist/main.css",
|
||||
"test": "jest --runInBand"
|
||||
"build": "NODE_ENV=production postcss ./src/index.css -o ./dist/main.css --verbose",
|
||||
"test": "jest --runInBand --forceExit"
|
||||
},
|
||||
"jest": {
|
||||
"testTimeout": 10000,
|
||||
"displayName": "PostCSS CLI",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
let $ = require('../../execute')
|
||||
let { css, html, javascript } = require('../../syntax')
|
||||
|
||||
let {
|
||||
readOutputFile,
|
||||
appendToInputFile,
|
||||
writeInputFile,
|
||||
waitForOutputFileCreation,
|
||||
waitForOutputFileChange,
|
||||
} = require('../../io')({ output: 'dist', input: 'src' })
|
||||
let { readOutputFile, appendToInputFile, writeInputFile } = require('../../io')({
|
||||
output: 'dist',
|
||||
input: 'src',
|
||||
})
|
||||
|
||||
function ready(message) {
|
||||
return message.includes('Finished')
|
||||
}
|
||||
|
||||
describe('static build', () => {
|
||||
it('should be possible to generate tailwind output', async () => {
|
||||
|
|
@ -31,11 +32,10 @@ describe('watcher', () => {
|
|||
test('classes are generated when the html file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
let runningProcess = $('postcss ./src/index.css -o ./dist/main.css -w', {
|
||||
let runningProcess = $('postcss ./src/index.css -o ./dist/main.css -w --verbose', {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -45,9 +45,8 @@ describe('watcher', () => {
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
})
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -60,15 +59,14 @@ describe('watcher', () => {
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
|
||||
})
|
||||
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
|
|
@ -85,11 +83,11 @@ describe('watcher', () => {
|
|||
test('classes are generated when the tailwind.config.js file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold md:font-medium"></div>`)
|
||||
|
||||
let runningProcess = $('postcss ./src/index.css -o ./dist/main.css -w', {
|
||||
let runningProcess = $('postcss ./src/index.css -o ./dist/main.css -w --verbose', {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -104,10 +102,9 @@ describe('watcher', () => {
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'../tailwind.config.js',
|
||||
javascript`
|
||||
await writeInputFile(
|
||||
'../tailwind.config.js',
|
||||
javascript`
|
||||
module.exports = {
|
||||
content: ['./src/index.html'],
|
||||
theme: {
|
||||
|
|
@ -126,8 +123,8 @@ describe('watcher', () => {
|
|||
plugins: [],
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -148,11 +145,11 @@ describe('watcher', () => {
|
|||
test('classes are generated when the index.css file changes', async () => {
|
||||
await writeInputFile('index.html', html`<div class="font-bold btn"></div>`)
|
||||
|
||||
let runningProcess = $('postcss ./src/index.css -o ./dist/main.css -w', {
|
||||
let runningProcess = $('postcss ./src/index.css -o ./dist/main.css -w --verbose', {
|
||||
env: { TAILWIND_MODE: 'watch' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -162,22 +159,21 @@ describe('watcher', () => {
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded;
|
||||
}
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
}
|
||||
`
|
||||
)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -194,29 +190,28 @@ describe('watcher', () => {
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded bg-red-500;
|
||||
}
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded bg-red-500;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
}
|
||||
`
|
||||
)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@
|
|||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"test": "jest --runInBand"
|
||||
"test": "jest --runInBand --forceExit"
|
||||
},
|
||||
"jest": {
|
||||
"testTimeout": 10000,
|
||||
"displayName": "rollup.js",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
]
|
||||
"setupFilesAfterEnv": ["<rootDir>/../../jest/customMatchers.js"]
|
||||
},
|
||||
"devDependencies": {
|
||||
"rollup": "^2.48.0",
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
let $ = require('../../execute')
|
||||
let { css, html, javascript } = require('../../syntax')
|
||||
|
||||
let {
|
||||
readOutputFile,
|
||||
appendToInputFile,
|
||||
writeInputFile,
|
||||
waitForOutputFileCreation,
|
||||
waitForOutputFileChange,
|
||||
} = require('../../io')({ output: 'dist', input: 'src' })
|
||||
let { readOutputFile, appendToInputFile, writeInputFile } = require('../../io')({
|
||||
output: 'dist',
|
||||
input: 'src',
|
||||
})
|
||||
|
||||
function ready(message) {
|
||||
return message.includes('created')
|
||||
}
|
||||
|
||||
describe('static build', () => {
|
||||
it('should be possible to generate tailwind output', async () => {
|
||||
|
|
@ -32,8 +33,7 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
let runningProcess = $('rollup -c --watch', { env })
|
||||
|
||||
await waitForOutputFileCreation('index.css')
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -43,9 +43,8 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('index.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
})
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -58,15 +57,14 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('index.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
|
||||
})
|
||||
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
|
|
@ -84,8 +82,7 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
await writeInputFile('index.html', html`<div class="font-bold md:font-medium"></div>`)
|
||||
|
||||
let runningProcess = $('rollup -c --watch', { env })
|
||||
|
||||
await waitForOutputFileCreation('index.css')
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -100,10 +97,9 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('index.css', async () => {
|
||||
await writeInputFile(
|
||||
'../tailwind.config.js',
|
||||
javascript`
|
||||
await writeInputFile(
|
||||
'../tailwind.config.js',
|
||||
javascript`
|
||||
module.exports = {
|
||||
content: ['./src/index.html'],
|
||||
theme: {
|
||||
|
|
@ -122,8 +118,8 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
plugins: [],
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -145,8 +141,7 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
await writeInputFile('index.html', html`<div class="font-bold btn"></div>`)
|
||||
|
||||
let runningProcess = $('rollup -c --watch', { env })
|
||||
|
||||
await waitForOutputFileCreation('index.css')
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -156,22 +151,21 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('index.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded;
|
||||
}
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
}
|
||||
`
|
||||
)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -188,29 +182,28 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('index.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded bg-red-500;
|
||||
}
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded bg-red-500;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
}
|
||||
`
|
||||
)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('index.css')).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
|
|
|
|||
1
integrations/tailwindcss-cli/package-lock.json
generated
1
integrations/tailwindcss-cli/package-lock.json
generated
|
|
@ -5,6 +5,7 @@
|
|||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "tailwindcss-cli",
|
||||
"version": "0.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@
|
|||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css",
|
||||
"test": "jest --runInBand"
|
||||
"test": "jest --runInBand --forceExit"
|
||||
},
|
||||
"jest": {
|
||||
"testTimeout": 10000,
|
||||
"displayName": "Tailwind CSS CLI",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ describe('Build command', () => {
|
|||
|
||||
.btn-after {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
|
|
@ -238,7 +238,7 @@ describe('Build command', () => {
|
|||
|
||||
.btn-after {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
let $ = require('../../execute')
|
||||
let { css, html, javascript } = require('../../syntax')
|
||||
|
||||
let {
|
||||
readOutputFile,
|
||||
appendToInputFile,
|
||||
writeInputFile,
|
||||
waitForOutputFileCreation,
|
||||
waitForOutputFileChange,
|
||||
} = require('../../io')({ output: 'dist', input: 'src' })
|
||||
let { readOutputFile, appendToInputFile, writeInputFile } = require('../../io')({
|
||||
output: 'dist',
|
||||
input: 'src',
|
||||
})
|
||||
|
||||
function ready(message) {
|
||||
return message.includes('Done in')
|
||||
}
|
||||
|
||||
describe('static build', () => {
|
||||
it('should be possible to generate tailwind output', async () => {
|
||||
|
|
@ -48,22 +49,20 @@ describe('static build', () => {
|
|||
`
|
||||
)
|
||||
|
||||
$('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css', {
|
||||
await $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css', {
|
||||
env: { NODE_ENV: 'production' },
|
||||
})
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-red-600 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(220, 38, 38, var(--tw-bg-opacity));
|
||||
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.font-bold {
|
||||
|
|
@ -79,8 +78,7 @@ describe('watcher', () => {
|
|||
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
|
||||
|
||||
let runningProcess = $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css -w')
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -90,9 +88,8 @@ describe('watcher', () => {
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
})
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -105,15 +102,14 @@ describe('watcher', () => {
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
|
||||
})
|
||||
await appendToInputFile('index.html', html`<div class="bg-red-500"></div>`)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
|
|
@ -145,8 +141,7 @@ describe('watcher', () => {
|
|||
)
|
||||
|
||||
let runningProcess = $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css -w')
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -156,9 +151,8 @@ describe('watcher', () => {
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
})
|
||||
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).not.toIncludeCss(css`
|
||||
@layer base {
|
||||
|
|
@ -186,8 +180,7 @@ describe('watcher', () => {
|
|||
await writeInputFile('index.html', html`<div class="font-bold md:font-medium"></div>`)
|
||||
|
||||
let runningProcess = $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css -w')
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -202,10 +195,9 @@ describe('watcher', () => {
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'../tailwind.config.js',
|
||||
javascript`
|
||||
await writeInputFile(
|
||||
'../tailwind.config.js',
|
||||
javascript`
|
||||
module.exports = {
|
||||
content: ['./src/index.html'],
|
||||
theme: {
|
||||
|
|
@ -224,8 +216,8 @@ describe('watcher', () => {
|
|||
plugins: [],
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -247,8 +239,7 @@ describe('watcher', () => {
|
|||
await writeInputFile('index.html', html`<div class="font-bold btn"></div>`)
|
||||
|
||||
let runningProcess = $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css -w')
|
||||
|
||||
await waitForOutputFileCreation('main.css')
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -258,22 +249,21 @@ describe('watcher', () => {
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded;
|
||||
}
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
}
|
||||
`
|
||||
)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
|
|
@ -290,29 +280,28 @@ describe('watcher', () => {
|
|||
`
|
||||
)
|
||||
|
||||
await waitForOutputFileChange('main.css', async () => {
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
await writeInputFile(
|
||||
'index.css',
|
||||
css`
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded bg-red-500;
|
||||
}
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply px-2 py-1 rounded bg-red-500;
|
||||
}
|
||||
`
|
||||
)
|
||||
})
|
||||
}
|
||||
`
|
||||
)
|
||||
await runningProcess.onStderr(ready)
|
||||
|
||||
expect(await readOutputFile('main.css')).toIncludeCss(
|
||||
css`
|
||||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
|
|
|
|||
1
integrations/vite/package-lock.json
generated
1
integrations/vite/package-lock.json
generated
|
|
@ -5,6 +5,7 @@
|
|||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "vite",
|
||||
"version": "0.0.0",
|
||||
"devDependencies": {
|
||||
"vite": "^2.3.3"
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@
|
|||
"browser": "./src/index.js",
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
"test": "jest --runInBand"
|
||||
"test": "jest --runInBand --forceExit"
|
||||
},
|
||||
"jest": {
|
||||
"testTimeout": 10000,
|
||||
"displayName": "vite",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ describe('watcher', () => {
|
|||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
|
|
@ -242,7 +242,7 @@ describe('watcher', () => {
|
|||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
|
|
|
|||
1
integrations/webpack-4/package-lock.json
generated
1
integrations/webpack-4/package-lock.json
generated
|
|
@ -5,6 +5,7 @@
|
|||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "webpack-4",
|
||||
"version": "0.0.0",
|
||||
"devDependencies": {
|
||||
"css-loader": "^5.2.4",
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@
|
|||
"scripts": {
|
||||
"build": "webpack --mode=production",
|
||||
"dev": "webpack --mode=development --watch",
|
||||
"test": "jest --runInBand"
|
||||
"test": "jest --runInBand --forceExit"
|
||||
},
|
||||
"jest": {
|
||||
"testTimeout": 10000,
|
||||
"displayName": "webpack 4",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
|
|
@ -208,7 +208,7 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
|
|
|
|||
1
integrations/webpack-5/package-lock.json
generated
1
integrations/webpack-5/package-lock.json
generated
|
|
@ -5,6 +5,7 @@
|
|||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "webpack-5",
|
||||
"version": "0.0.0",
|
||||
"devDependencies": {
|
||||
"css-loader": "^5.2.4",
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@
|
|||
"scripts": {
|
||||
"build": "webpack --mode=production",
|
||||
"dev": "webpack --mode=development",
|
||||
"test": "jest"
|
||||
"test": "jest --runInBand --forceExit"
|
||||
},
|
||||
"jest": {
|
||||
"testTimeout": 10000,
|
||||
"displayName": "webpack 5",
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/../../jest/customMatchers.js"
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
|
|
@ -208,7 +208,7 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
.btn {
|
||||
border-radius: 0.25rem;
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.25rem;
|
||||
|
|
@ -253,12 +253,12 @@ describe.each([{ TAILWIND_MODE: 'watch' }, { TAILWIND_MODE: undefined }])('watch
|
|||
css`
|
||||
.bg-red-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-red-600 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgba(220, 38, 38, var(--tw-bg-opacity));
|
||||
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.font-bold {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue