Skip to content

Commit 34c5d41

Browse files
authored
[ts-next-plugin] add testing utils (#79079)
Ported from #78505, this PR adds testing utils and a basic log test for the Next.js TypeScript language service plugin.
1 parent c75350d commit 34c5d41

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { PluginLanguageService } from './test-utils'
2+
import { getPluginLanguageService } from './test-utils'
3+
4+
describe('typescript-plugin', () => {
5+
let languageService: PluginLanguageService
6+
7+
beforeAll(() => {
8+
languageService = getPluginLanguageService(__dirname)
9+
})
10+
11+
it('should be able to get the language service', () => {
12+
expect(languageService).toBeDefined()
13+
const capturedLogs = languageService.getCapturedLogs()
14+
expect(capturedLogs).toContain(
15+
'[next] Initialized Next.js TypeScript plugin'
16+
)
17+
})
18+
})
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import tsNextPluginFactory from 'next'
2+
import ts from 'typescript'
3+
export { NEXT_TS_ERRORS } from 'next/dist/server/typescript/constant'
4+
5+
export type PluginLanguageService = ts.LanguageService & {
6+
getCapturedLogs: () => string
7+
}
8+
9+
export function getPluginLanguageService(dir: string): PluginLanguageService {
10+
const files = ts.sys.readDirectory(dir)
11+
12+
const compilerOptions = ts.getDefaultCompilerOptions()
13+
const compilerHost = ts.createCompilerHost(compilerOptions)
14+
15+
let logs = ''
16+
const logger = {
17+
info: (...args: any[]) => {
18+
const message = args
19+
.map((arg) => (typeof arg === 'string' ? arg : JSON.stringify(arg)))
20+
.join(' ')
21+
logs += message + '\n'
22+
console.log(...args)
23+
},
24+
}
25+
26+
const languageServiceHost: ts.LanguageServiceHost = {
27+
...compilerHost,
28+
getCompilationSettings: () => compilerOptions,
29+
getScriptFileNames: () => files,
30+
getScriptSnapshot: (fileName) => {
31+
const contents = ts.sys.readFile(fileName)
32+
if (contents && typeof contents === 'string') {
33+
return ts.ScriptSnapshot.fromString(contents)
34+
}
35+
return
36+
},
37+
getScriptVersion: () => '0',
38+
writeFile: ts.sys.writeFile,
39+
}
40+
41+
const languageService = ts.createLanguageService(languageServiceHost)
42+
43+
const pluginCreateInfo: ts.server.PluginCreateInfo = {
44+
project: {
45+
projectService: {
46+
logger,
47+
},
48+
getCurrentDirectory: () => dir,
49+
} as unknown as ts.server.Project,
50+
languageService,
51+
languageServiceHost,
52+
serverHost: null,
53+
config: {},
54+
}
55+
56+
const plugin: ts.server.PluginModule = (
57+
tsNextPluginFactory as unknown as ts.server.PluginModuleFactory
58+
)({ typescript: ts })
59+
60+
const service = plugin.create(pluginCreateInfo) as PluginLanguageService
61+
62+
// Add a custom method to get captured logs
63+
service.getCapturedLogs = () => logs
64+
65+
return service
66+
}
67+
68+
export function getTsFiles(dir: string): string[] {
69+
return ts.sys.readDirectory(dir)
70+
}

0 commit comments

Comments
 (0)