Skip to content

Commit 8b6eafa

Browse files
Add CI testing matrix (#989)
This is starting point for setting up CI on PRs (they already run before publishing pre-release or release versions). This is also intended to test multiple Node versions _and_ Windows.
1 parent f5bcefc commit 8b6eafa

File tree

5 files changed

+75
-41
lines changed

5 files changed

+75
-41
lines changed

.github/workflows/ci.yml

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Run Tests
2+
on:
3+
pull_request:
4+
branches:
5+
- main
6+
7+
jobs:
8+
tests:
9+
strategy:
10+
matrix:
11+
node: [18, 20, 22, 23]
12+
os: [ubuntu-latest, macos-latest, windows-latest]
13+
14+
runs-on: ${{ matrix.os }}
15+
name: Run Tests - Node v${{ matrix.node }} / ${{ matrix.os }}
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
- uses: pnpm/action-setup@v4
20+
- uses: actions/setup-node@v4
21+
with:
22+
cache: 'pnpm'
23+
node-version: ${{ matrix.node-version }}
24+
25+
- name: Install dependencies
26+
run: pnpm install
27+
28+
- name: Run tests
29+
run: |
30+
cd packages/tailwindcss-language-server &&
31+
pnpm run build &&
32+
pnpm run test

packages/tailwindcss-language-server/src/project-locator.test.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { URL, fileURLToPath } from 'url'
55
import { Settings } from '@tailwindcss/language-service/src/util/state'
66
import { createResolver } from './resolver'
77
import { css, defineTest, js, json, scss, Storage, TestUtils } from './testing'
8+
import { normalizePath } from './utils'
89

910
let settings: Settings = {
1011
tailwindCSS: {
@@ -29,12 +30,14 @@ function testFixture(fixture: string, details: any[]) {
2930

3031
let detail = details[i]
3132

32-
let configPath = path.relative(fixturePath, project.config.path)
33+
let configPath = path.posix.relative(normalizePath(fixturePath), project.config.path)
3334

3435
expect(configPath).toEqual(detail?.config)
3536

3637
if (detail?.content) {
37-
let expected = detail?.content.map((path) => path.replace('{URL}', fixturePath)).sort()
38+
let expected = detail?.content
39+
.map((path) => path.replace('{URL}', normalizePath(fixturePath)))
40+
.sort()
3841

3942
let actual = project.documentSelector
4043
.filter((selector) => selector.priority === 1 /** content */)
@@ -45,7 +48,9 @@ function testFixture(fixture: string, details: any[]) {
4548
}
4649

4750
if (detail?.selectors) {
48-
let expected = detail?.selectors.map((path) => path.replace('{URL}', fixturePath)).sort()
51+
let expected = detail?.selectors
52+
.map((path) => path.replace('{URL}', normalizePath(fixturePath)))
53+
.sort()
4954

5055
let actual = project.documentSelector.map((selector) => selector.pattern).sort()
5156

@@ -364,7 +369,7 @@ async function prepare({ root }: TestUtils) {
364369
} as Settings
365370

366371
function adjustPath(filepath: string) {
367-
filepath = filepath.replace(root, '{URL}')
372+
filepath = filepath.replace(normalizePath(root), '{URL}')
368373

369374
if (filepath.startsWith('{URL}/')) {
370375
filepath = filepath.slice(5)

packages/tailwindcss-language-server/src/testing/index.ts

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { onTestFinished, test, TestOptions } from 'vitest'
2+
import * as os from 'node:os'
23
import * as fs from 'node:fs/promises'
34
import * as path from 'node:path'
45
import * as proc from 'node:child_process'
@@ -12,6 +13,7 @@ export interface TestUtils {
1213
export interface StorageSymlink {
1314
[IS_A_SYMLINK]: true
1415
filepath: string
16+
type: 'file' | 'dir' | undefined
1517
}
1618

1719
export interface Storage {
@@ -56,7 +58,13 @@ async function setup<T>(config: TestConfig<T>): Promise<TestUtils> {
5658

5759
onTestFinished(async (result) => {
5860
// Once done, move all the files to a new location
59-
await fs.rename(baseDir, doneDir)
61+
try {
62+
await fs.rename(baseDir, doneDir)
63+
} catch {
64+
// If it fails it doesn't really matter. It only fails on Windows and then
65+
// only randomly so whatever
66+
console.error('Failed to move test files to done directory')
67+
}
6068

6169
if (result.state === 'fail') return
6270

@@ -75,10 +83,11 @@ async function setup<T>(config: TestConfig<T>): Promise<TestUtils> {
7583
}
7684

7785
const IS_A_SYMLINK = Symbol('is-a-symlink')
78-
export function symlinkTo(filepath: string): StorageSymlink {
86+
export function symlinkTo(filepath: string, type?: 'file' | 'dir'): StorageSymlink {
7987
return {
8088
[IS_A_SYMLINK]: true as const,
8189
filepath,
90+
type,
8291
}
8392
}
8493

@@ -93,7 +102,14 @@ async function prepareFileSystem(base: string, storage: Storage) {
93102

94103
if (typeof content === 'object' && IS_A_SYMLINK in content) {
95104
let target = path.resolve(base, content.filepath)
96-
await fs.symlink(target, fullPath)
105+
106+
let type: string = content.type
107+
108+
if (os.platform() === 'win32' && content.type === 'dir') {
109+
type = 'junction'
110+
}
111+
112+
await fs.symlink(target, fullPath, type)
97113
continue
98114
}
99115

packages/tailwindcss-language-server/tests/document-links/document-links.test.js

+14-33
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { test } from 'vitest'
2-
import { withFixture } from '../common'
32
import * as path from 'path'
3+
import { URI } from 'vscode-uri'
4+
import { withFixture } from '../common'
45

56
withFixture('basic', (c) => {
67
async function testDocumentLinks(name, { text, lang, expected }) {
@@ -19,9 +20,7 @@ withFixture('basic', (c) => {
1920
lang: 'css',
2021
expected: [
2122
{
22-
target: `file://${path
23-
.resolve('./tests/fixtures/basic/tailwind.config.js')
24-
.replace(/@/g, '%40')}`,
23+
target: URI.file(path.resolve('./tests/fixtures/basic/tailwind.config.js')).toString(),
2524
range: { start: { line: 0, character: 8 }, end: { line: 0, character: 28 } },
2625
},
2726
],
@@ -32,9 +31,7 @@ withFixture('basic', (c) => {
3231
lang: 'css',
3332
expected: [
3433
{
35-
target: `file://${path
36-
.resolve('./tests/fixtures/basic/does-not-exist.js')
37-
.replace(/@/g, '%40')}`,
34+
target: URI.file(path.resolve('./tests/fixtures/basic/does-not-exist.js')).toString(),
3835
range: { start: { line: 0, character: 8 }, end: { line: 0, character: 27 } },
3936
},
4037
],
@@ -58,9 +55,7 @@ withFixture('v4/basic', (c) => {
5855
lang: 'css',
5956
expected: [
6057
{
61-
target: `file://${path
62-
.resolve('./tests/fixtures/v4/basic/tailwind.config.js')
63-
.replace(/@/g, '%40')}`,
58+
target: URI.file(path.resolve('./tests/fixtures/v4/basic/tailwind.config.js')).toString(),
6459
range: { start: { line: 0, character: 8 }, end: { line: 0, character: 28 } },
6560
},
6661
],
@@ -71,9 +66,7 @@ withFixture('v4/basic', (c) => {
7166
lang: 'css',
7267
expected: [
7368
{
74-
target: `file://${path
75-
.resolve('./tests/fixtures/v4/basic/does-not-exist.js')
76-
.replace(/@/g, '%40')}`,
69+
target: URI.file(path.resolve('./tests/fixtures/v4/basic/does-not-exist.js')).toString(),
7770
range: { start: { line: 0, character: 8 }, end: { line: 0, character: 27 } },
7871
},
7972
],
@@ -84,9 +77,7 @@ withFixture('v4/basic', (c) => {
8477
lang: 'css',
8578
expected: [
8679
{
87-
target: `file://${path
88-
.resolve('./tests/fixtures/v4/basic/plugin.js')
89-
.replace(/@/g, '%40')}`,
80+
target: URI.file(path.resolve('./tests/fixtures/v4/basic/plugin.js')).toString(),
9081
range: { start: { line: 0, character: 8 }, end: { line: 0, character: 19 } },
9182
},
9283
],
@@ -97,9 +88,7 @@ withFixture('v4/basic', (c) => {
9788
lang: 'css',
9889
expected: [
9990
{
100-
target: `file://${path
101-
.resolve('./tests/fixtures/v4/basic/does-not-exist.js')
102-
.replace(/@/g, '%40')}`,
91+
target: URI.file(path.resolve('./tests/fixtures/v4/basic/does-not-exist.js')).toString(),
10392
range: { start: { line: 0, character: 8 }, end: { line: 0, character: 27 } },
10493
},
10594
],
@@ -110,9 +99,7 @@ withFixture('v4/basic', (c) => {
11099
lang: 'css',
111100
expected: [
112101
{
113-
target: `file://${path
114-
.resolve('./tests/fixtures/v4/basic/index.html')
115-
.replace(/@/g, '%40')}`,
102+
target: URI.file(path.resolve('./tests/fixtures/v4/basic/index.html')).toString(),
116103
range: { start: { line: 0, character: 8 }, end: { line: 0, character: 20 } },
117104
},
118105
],
@@ -123,9 +110,7 @@ withFixture('v4/basic', (c) => {
123110
lang: 'css',
124111
expected: [
125112
{
126-
target: `file://${path
127-
.resolve('./tests/fixtures/v4/basic/does-not-exist.html')
128-
.replace(/@/g, '%40')}`,
113+
target: URI.file(path.resolve('./tests/fixtures/v4/basic/does-not-exist.html')).toString(),
129114
range: { start: { line: 0, character: 8 }, end: { line: 0, character: 29 } },
130115
},
131116
],
@@ -136,9 +121,7 @@ withFixture('v4/basic', (c) => {
136121
lang: 'css',
137122
expected: [
138123
{
139-
target: `file://${path
140-
.resolve('./tests/fixtures/v4/basic/index.html')
141-
.replace(/@/g, '%40')}`,
124+
target: URI.file(path.resolve('./tests/fixtures/v4/basic/index.html')).toString(),
142125
range: { start: { line: 0, character: 12 }, end: { line: 0, character: 24 } },
143126
},
144127
],
@@ -149,9 +132,7 @@ withFixture('v4/basic', (c) => {
149132
lang: 'css',
150133
expected: [
151134
{
152-
target: `file://${path
153-
.resolve('./tests/fixtures/v4/basic/does-not-exist.html')
154-
.replace(/@/g, '%40')}`,
135+
target: URI.file(path.resolve('./tests/fixtures/v4/basic/does-not-exist.html')).toString(),
155136
range: { start: { line: 0, character: 12 }, end: { line: 0, character: 33 } },
156137
},
157138
],
@@ -177,11 +158,11 @@ withFixture('v4/basic', (c) => {
177158
lang: 'css',
178159
expected: [
179160
{
180-
target: `file://${path.resolve('./tests/fixtures').replace(/@/g, '%40')}`,
161+
target: URI.file(path.resolve('./tests/fixtures')).toString(),
181162
range: { start: { line: 1, character: 35 }, end: { line: 1, character: 43 } },
182163
},
183164
{
184-
target: `file://${path.resolve('./tests/fixtures').replace(/@/g, '%40')}`,
165+
target: URI.file(path.resolve('./tests/fixtures')).toString(),
185166
range: { start: { line: 2, character: 33 }, end: { line: 2, character: 41 } },
186167
},
187168
],

packages/tailwindcss-language-server/tests/env/v4.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ defineTest({
737737
presets: [require('some-pkg/config/tailwind.config.js').default]
738738
}
739739
`,
740-
'packages/some-pkg': symlinkTo('packages/some-pkg#c3f1e'),
740+
'packages/some-pkg': symlinkTo('packages/some-pkg#c3f1e', 'dir'),
741741
'packages/some-pkg#c3f1e/package.json': json`
742742
{
743743
"name": "some-pkg",

0 commit comments

Comments
 (0)