-
Notifications
You must be signed in to change notification settings - Fork 464
Expand file tree
/
Copy pathproject-root.test.ts
More file actions
128 lines (104 loc) · 4.86 KB
/
Copy pathproject-root.test.ts
File metadata and controls
128 lines (104 loc) · 4.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import path from 'node:path';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { getRelativeFolder } from '../lib/file-info';
import { classifyFolder } from '../lib/match-folders';
import { findEslintProjectRoot, resolveProjectRoot } from '../lib/project-root';
let projectRoot: string;
beforeEach(async () => {
projectRoot = await mkdtemp(path.join(tmpdir(), 'clerk-project-root-'));
});
afterEach(async () => {
await rm(projectRoot, { recursive: true, force: true });
});
describe('findEslintProjectRoot', () => {
it('returns the directory containing eslint.config.js', async () => {
await writeFile(path.join(projectRoot, 'eslint.config.js'), 'export default [];\n');
const file = path.join(projectRoot, 'app', 'dashboard', 'page.tsx');
await mkdir(path.dirname(file), { recursive: true });
await writeFile(file, '');
expect(findEslintProjectRoot(file)).toBe(projectRoot.replaceAll('\\', '/'));
});
it('walks up past intermediate directories', async () => {
const appRoot = path.join(projectRoot, 'apps', 'web');
await mkdir(appRoot, { recursive: true });
await writeFile(path.join(appRoot, 'eslint.config.mjs'), 'export default [];\n');
const file = path.join(appRoot, 'app', 'sign-in', 'page.tsx');
await mkdir(path.dirname(file), { recursive: true });
await writeFile(file, '');
expect(findEslintProjectRoot(file)).toBe(appRoot.replaceAll('\\', '/'));
});
it('returns null when no eslint.config.* exists', async () => {
const file = path.join(projectRoot, 'app', 'page.tsx');
await mkdir(path.dirname(file), { recursive: true });
await writeFile(file, '');
expect(findEslintProjectRoot(file)).toBeNull();
});
});
describe('resolveProjectRoot', () => {
it('prefers explicit rootDir over discovered config and cwd', async () => {
await writeFile(path.join(projectRoot, 'eslint.config.js'), 'export default [];\n');
const file = path.join(projectRoot, 'app', 'page.tsx');
await mkdir(path.dirname(file), { recursive: true });
await writeFile(file, '');
const explicit = path.join(projectRoot, 'explicit-root');
expect(resolveProjectRoot(file, { rootDir: explicit, cwd: '/elsewhere' })).toBe(explicit.replaceAll('\\', '/'));
});
it('resolves relative rootDir against cwd', () => {
expect(resolveProjectRoot('/repo/apps/web/src/app/page.tsx', { rootDir: 'apps/web', cwd: '/repo' })).toBe(
'/repo/apps/web',
);
});
it('uses nearest eslint.config.* when rootDir is omitted', async () => {
await writeFile(path.join(projectRoot, 'eslint.config.js'), 'export default [];\n');
const file = path.join(projectRoot, 'app', 'page.tsx');
await mkdir(path.dirname(file), { recursive: true });
await writeFile(file, '');
expect(resolveProjectRoot(file, { cwd: '/Users' })).toBe(projectRoot.replaceAll('\\', '/'));
});
it('falls back to cwd when config discovery finds nothing', () => {
expect(resolveProjectRoot('/no/config/here/app/page.tsx', { cwd: '/no/config/here' })).toBe('/no/config/here');
});
});
describe('path classification with project root', () => {
it('classifies public folders correctly when ESLint cwd is above the project', async () => {
const myproj = path.join(projectRoot, 'work', 'myproj');
await mkdir(myproj, { recursive: true });
await writeFile(path.join(myproj, 'eslint.config.js'), 'export default [];\n');
const file = path.join(myproj, 'app', 'sign-in', 'page.tsx');
await mkdir(path.dirname(file), { recursive: true });
await writeFile(file, '');
const resolved = resolveProjectRoot(file, { cwd: projectRoot });
const folder = getRelativeFolder(file, resolved);
const classification = classifyFolder(folder!, {
protected: ['app/**'],
public: ['app/sign-in/**'],
});
expect(folder).toBe('app/sign-in');
expect(classification).toBe('public');
});
it('fixes misclassification when only a high cwd is available but rootDir is explicit', () => {
const file = '/Users/app/work/myproj/app/sign-in/page.tsx';
const root = '/Users/app/work/myproj';
const folder = getRelativeFolder(file, resolveProjectRoot(file, { rootDir: root, cwd: '/Users' }));
expect(folder).toBe('app/sign-in');
expect(
classifyFolder(folder!, {
protected: ['app/**'],
public: ['app/sign-in/**'],
}),
).toBe('public');
});
it('classifies folders relative to a cwd-resolved rootDir', () => {
const file = '/repo/apps/web/src/app/sign-in/page.tsx';
const folder = getRelativeFolder(file, resolveProjectRoot(file, { rootDir: 'apps/web', cwd: '/repo' }));
expect(folder).toBe('src/app/sign-in');
expect(
classifyFolder(folder!, {
protected: ['**'],
public: ['src/app/sign-in/**'],
}),
).toBe('public');
});
});