vendor tsgo
This commit is contained in:
767
tools/tsgo/internal/project/ata/ata_test.go
Normal file
767
tools/tsgo/internal/project/ata/ata_test.go
Normal file
@@ -0,0 +1,767 @@
|
||||
package ata_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/bundled"
|
||||
"github.com/microsoft/typescript-go/internal/ls/lsutil"
|
||||
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
|
||||
"github.com/microsoft/typescript-go/internal/project"
|
||||
"github.com/microsoft/typescript-go/internal/testutil/projecttestutil"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestATA(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !bundled.Embedded {
|
||||
t.Skip("bundled files are not embedded")
|
||||
}
|
||||
|
||||
t.Run("local module should not be picked up", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": `const c = require('./config');`,
|
||||
"/user/username/projects/project/config.js": `export let x = 1`,
|
||||
"/user/username/projects/project/jsconfig.json": `{
|
||||
"compilerOptions": { "moduleResolution": "commonjs" },
|
||||
"typeAcquisition": { "enable": true }
|
||||
}`,
|
||||
}
|
||||
|
||||
testOptions := &projecttestutil.TypingsInstallerOptions{
|
||||
TypesRegistry: []string{"config"},
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, testOptions)
|
||||
uri := lsproto.DocumentUri("file:///user/username/projects/project/app.js")
|
||||
content := files["/user/username/projects/project/app.js"].(string)
|
||||
|
||||
// Open the file
|
||||
session.DidOpenFile(context.Background(), uri, 1, content, lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
ls, err := session.GetLanguageService(context.Background(), uri)
|
||||
assert.NilError(t, err)
|
||||
// Verify the local config.js file is included in the program
|
||||
program := ls.GetProgram()
|
||||
assert.Assert(t, program != nil)
|
||||
configFile := program.GetSourceFile("/user/username/projects/project/config.js")
|
||||
assert.Assert(t, configFile != nil, "local config.js should be included")
|
||||
|
||||
// Verify that only types-registry was installed (no @types/config since it's a local module)
|
||||
npmCalls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, len(npmCalls), 1)
|
||||
assert.Equal(t, npmCalls[0].Args[2], "types-registry@latest")
|
||||
})
|
||||
|
||||
t.Run("configured projects", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": ``,
|
||||
"/user/username/projects/project/tsconfig.json": `{
|
||||
"compilerOptions": { "allowJs": true },
|
||||
"typeAcquisition": { "enable": true },
|
||||
}`,
|
||||
"/user/username/projects/project/package.json": `{
|
||||
"name": "test",
|
||||
"dependencies": {
|
||||
"jquery": "^3.1.0"
|
||||
}
|
||||
}`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": `declare const $: { x: number }`,
|
||||
},
|
||||
})
|
||||
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"), 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
npmCalls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, len(npmCalls), 2)
|
||||
assert.Equal(t, npmCalls[0].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.Equal(t, npmCalls[0].Args[2], "types-registry@latest")
|
||||
assert.Equal(t, npmCalls[1].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.Assert(t, slices.Contains(npmCalls[1].Args, "@types/jquery@latest"))
|
||||
assert.Equal(t, len(utils.Client().RefreshDiagnosticsCalls()), 1)
|
||||
})
|
||||
|
||||
t.Run("inferred projects", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": ``,
|
||||
"/user/username/projects/project/package.json": `{
|
||||
"name": "test",
|
||||
"dependencies": {
|
||||
"jquery": "^3.1.0"
|
||||
}
|
||||
}`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": `declare const $: { x: number }`,
|
||||
},
|
||||
})
|
||||
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"), 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
// Check that npm install was called twice
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 2, len(calls), "Expected exactly 2 npm install calls")
|
||||
assert.Equal(t, calls[0].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.DeepEqual(t, calls[0].Args, []string{"install", "--ignore-scripts", "types-registry@latest"})
|
||||
assert.Equal(t, calls[1].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.Equal(t, calls[1].Args[2], "@types/jquery@latest")
|
||||
|
||||
// Verify the types file was installed
|
||||
ls, err := session.GetLanguageService(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"))
|
||||
assert.NilError(t, err)
|
||||
program := ls.GetProgram()
|
||||
jqueryTypesFile := program.GetSourceFile(projecttestutil.TestTypingsLocation + "/node_modules/@types/jquery/index.d.ts")
|
||||
assert.Assert(t, jqueryTypesFile != nil, "jquery types should be installed")
|
||||
})
|
||||
|
||||
t.Run("type acquisition with disableFilenameBasedTypeAcquisition:true", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/jquery.js": ``,
|
||||
"/user/username/projects/project/tsconfig.json": `{
|
||||
"compilerOptions": { "allowJs": true },
|
||||
"typeAcquisition": { "enable": true, "disableFilenameBasedTypeAcquisition": true }
|
||||
}`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
TypesRegistry: []string{"jquery"},
|
||||
})
|
||||
|
||||
// Should only get types-registry install, no jquery install since filename-based acquisition is disabled
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/jquery.js"), 1, files["/user/username/projects/project/jquery.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// Check that npm install was called once (only types-registry)
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 1, len(calls), "Expected exactly 1 npm install call")
|
||||
assert.Equal(t, calls[0].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.DeepEqual(t, calls[0].Args, []string{"install", "--ignore-scripts", "types-registry@latest"})
|
||||
})
|
||||
|
||||
t.Run("discover from node_modules", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": "",
|
||||
"/user/username/projects/project/package.json": `{
|
||||
"dependencies": {
|
||||
"jquery": "1.0.0"
|
||||
}
|
||||
}`,
|
||||
"/user/username/projects/project/jsconfig.json": `{}`,
|
||||
"/user/username/projects/project/node_modules/commander/index.js": "",
|
||||
"/user/username/projects/project/node_modules/commander/package.json": `{ "name": "commander" }`,
|
||||
"/user/username/projects/project/node_modules/jquery/index.js": "",
|
||||
"/user/username/projects/project/node_modules/jquery/package.json": `{ "name": "jquery" }`,
|
||||
"/user/username/projects/project/node_modules/jquery/nested/package.json": `{ "name": "nested" }`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
TypesRegistry: []string{"nested", "commander"},
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": "declare const jquery: { x: number }",
|
||||
},
|
||||
})
|
||||
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"), 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// Check that npm install was called twice
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 2, len(calls), "Expected exactly 2 npm install calls")
|
||||
assert.Equal(t, calls[0].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.DeepEqual(t, calls[0].Args, []string{"install", "--ignore-scripts", "types-registry@latest"})
|
||||
assert.Equal(t, calls[1].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.Equal(t, calls[1].Args[2], "@types/jquery@latest")
|
||||
})
|
||||
|
||||
t.Run("discover from node_modules empty types", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": "",
|
||||
"/user/username/projects/project/package.json": `{"dependencies": {"jquery": "1.0.0"}}`,
|
||||
"/user/username/projects/project/jsconfig.json": `{"compilerOptions": {"types": []}}`,
|
||||
"/user/username/projects/project/node_modules/commander/index.js": "",
|
||||
"/user/username/projects/project/node_modules/commander/package.json": `{ "name": "commander" }`,
|
||||
"/user/username/projects/project/node_modules/jquery/index.js": "",
|
||||
"/user/username/projects/project/node_modules/jquery/package.json": `{ "name": "jquery" }`,
|
||||
"/user/username/projects/project/node_modules/jquery/nested/package.json": `{ "name": "nested" }`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
TypesRegistry: []string{"nested", "commander"},
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": "declare const jquery: { x: number }",
|
||||
},
|
||||
})
|
||||
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"), 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// Only types-registry should be installed
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 1, len(calls))
|
||||
assert.DeepEqual(t, calls[0].Args, []string{"install", "--ignore-scripts", "types-registry@latest"})
|
||||
})
|
||||
|
||||
t.Run("discover from node_modules explicit types", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": "",
|
||||
"/user/username/projects/project/package.json": `{"dependencies": {"jquery": "1.0.0"}}`,
|
||||
"/user/username/projects/project/jsconfig.json": `{"compilerOptions": {"types": ["jquery"]}}`,
|
||||
"/user/username/projects/project/node_modules/commander/index.js": "",
|
||||
"/user/username/projects/project/node_modules/commander/package.json": `{ "name": "commander" }`,
|
||||
"/user/username/projects/project/node_modules/jquery/index.js": "",
|
||||
"/user/username/projects/project/node_modules/jquery/package.json": `{ "name": "jquery" }`,
|
||||
"/user/username/projects/project/node_modules/jquery/nested/package.json": `{ "name": "nested" }`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
TypesRegistry: []string{"nested", "commander"},
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": "declare const jquery: { x: number }",
|
||||
},
|
||||
})
|
||||
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"), 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// Only types-registry should be installed
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 1, len(calls))
|
||||
assert.DeepEqual(t, calls[0].Args, []string{"install", "--ignore-scripts", "types-registry@latest"})
|
||||
})
|
||||
|
||||
t.Run("discover from node_modules empty types has import", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": `import "jquery";`,
|
||||
"/user/username/projects/project/package.json": `{"dependencies": {"jquery": "1.0.0"}}`,
|
||||
"/user/username/projects/project/jsconfig.json": `{"compilerOptions": {"types": []}}`,
|
||||
"/user/username/projects/project/node_modules/commander/index.js": "",
|
||||
"/user/username/projects/project/node_modules/commander/package.json": `{ "name": "commander" }`,
|
||||
"/user/username/projects/project/node_modules/jquery/index.js": "",
|
||||
"/user/username/projects/project/node_modules/jquery/package.json": `{ "name": "jquery" }`,
|
||||
"/user/username/projects/project/node_modules/jquery/nested/package.json": `{ "name": "nested" }`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
TypesRegistry: []string{"nested", "commander"},
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": "declare const jquery: { x: number }",
|
||||
},
|
||||
})
|
||||
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"), 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// types-registry + jquery types
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 2, len(calls))
|
||||
assert.DeepEqual(t, calls[0].Args, []string{"install", "--ignore-scripts", "types-registry@latest"})
|
||||
assert.Assert(t, slices.Contains(calls[1].Args, "@types/jquery@latest"))
|
||||
})
|
||||
|
||||
t.Run("discover from bower_components", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": ``,
|
||||
"/user/username/projects/project/jsconfig.json": `{}`,
|
||||
"/user/username/projects/project/bower_components/jquery/index.js": "",
|
||||
"/user/username/projects/project/bower_components/jquery/bower.json": `{ "name": "jquery" }`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": "declare const jquery: { x: number }",
|
||||
},
|
||||
})
|
||||
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"), 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// Check that npm install was called twice
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 2, len(calls), "Expected exactly 2 npm install calls")
|
||||
assert.Equal(t, calls[0].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.DeepEqual(t, calls[0].Args, []string{"install", "--ignore-scripts", "types-registry@latest"})
|
||||
assert.Equal(t, calls[1].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.Equal(t, calls[1].Args[2], "@types/jquery@latest")
|
||||
|
||||
// Verify the types file was installed
|
||||
ls, err := session.GetLanguageService(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"))
|
||||
assert.NilError(t, err)
|
||||
jqueryTypesFile := ls.GetProgram().GetSourceFile(projecttestutil.TestTypingsLocation + "/node_modules/@types/jquery/index.d.ts")
|
||||
assert.Assert(t, jqueryTypesFile != nil, "jquery types should be installed")
|
||||
})
|
||||
|
||||
t.Run("discover from bower.json", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": ``,
|
||||
"/user/username/projects/project/jsconfig.json": `{}`,
|
||||
"/user/username/projects/project/bower.json": `{
|
||||
"dependencies": {
|
||||
"jquery": "^3.1.0"
|
||||
}
|
||||
}`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": "declare const jquery: { x: number }",
|
||||
},
|
||||
})
|
||||
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"), 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// Check that npm install was called twice
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 2, len(calls), "Expected exactly 2 npm install calls")
|
||||
assert.Equal(t, calls[0].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.DeepEqual(t, calls[0].Args, []string{"install", "--ignore-scripts", "types-registry@latest"})
|
||||
assert.Equal(t, calls[1].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.Equal(t, calls[1].Args[2], "@types/jquery@latest")
|
||||
|
||||
// Verify the types file was installed
|
||||
ls, err := session.GetLanguageService(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"))
|
||||
assert.NilError(t, err)
|
||||
jqueryTypesFile := ls.GetProgram().GetSourceFile(projecttestutil.TestTypingsLocation + "/node_modules/@types/jquery/index.d.ts")
|
||||
assert.Assert(t, jqueryTypesFile != nil, "jquery types should be installed")
|
||||
})
|
||||
|
||||
t.Run("Malformed package.json should be watched", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": "",
|
||||
"/user/username/projects/project/package.json": `{"dependencies": { "co } }`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
PackageToFile: map[string]string{
|
||||
"commander": "export let x: number",
|
||||
},
|
||||
})
|
||||
|
||||
uri := lsproto.DocumentUri("file:///user/username/projects/project/app.js")
|
||||
session.DidOpenFile(context.Background(), uri, 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// Initially only types-registry update attempted
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 1, len(calls))
|
||||
assert.DeepEqual(t, calls[0].Args, []string{"install", "--ignore-scripts", "types-registry@latest"})
|
||||
|
||||
// Fix package.json and notify watcher
|
||||
assert.NilError(t, utils.FS().WriteFile(
|
||||
"/user/username/projects/project/package.json",
|
||||
`{ "dependencies": { "commander": "0.0.2" } }`,
|
||||
))
|
||||
session.DidChangeWatchedFiles(context.Background(), []*lsproto.FileEvent{{
|
||||
Type: lsproto.FileChangeTypeChanged,
|
||||
Uri: lsproto.DocumentUri("file:///user/username/projects/project/package.json"),
|
||||
}})
|
||||
// diagnostics refresh triggered - simulate by getting the language service
|
||||
_, _ = session.GetLanguageService(context.Background(), uri)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
calls = utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 2, len(calls))
|
||||
assert.Assert(t, slices.Contains(calls[1].Args, "@types/commander@latest"))
|
||||
|
||||
// Verify types file present
|
||||
ls, err := session.GetLanguageService(context.Background(), uri)
|
||||
assert.NilError(t, err)
|
||||
program := ls.GetProgram()
|
||||
assert.Assert(t, program.GetSourceFile(projecttestutil.TestTypingsLocation+"/node_modules/@types/commander/index.d.ts") != nil)
|
||||
})
|
||||
|
||||
t.Run("should redo resolution that resolved to '.js' file after typings are installed", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": `\n import * as commander from "commander";\n `,
|
||||
"/user/username/projects/node_modules/commander/index.js": "module.exports = 0",
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
PackageToFile: map[string]string{
|
||||
"commander": "export let commander: number",
|
||||
},
|
||||
})
|
||||
|
||||
uri := lsproto.DocumentUri("file:///user/username/projects/project/app.js")
|
||||
session.DidOpenFile(context.Background(), uri, 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 2, len(calls))
|
||||
assert.Assert(t, slices.Contains(calls[1].Args, "@types/commander@latest"))
|
||||
|
||||
ls, err := session.GetLanguageService(context.Background(), uri)
|
||||
assert.NilError(t, err)
|
||||
program := ls.GetProgram()
|
||||
// Types file present
|
||||
assert.Assert(t, program.GetSourceFile(projecttestutil.TestTypingsLocation+"/node_modules/@types/commander/index.d.ts") != nil)
|
||||
// JS resolution should be dropped
|
||||
assert.Assert(t, program.GetSourceFile("/user/username/projects/node_modules/commander/index.js") == nil)
|
||||
})
|
||||
|
||||
t.Run("expired cache entry (inferred project, should install typings)", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": "",
|
||||
"/user/username/projects/project/package.json": `{"name":"test","dependencies":{"jquery":"^3.1.0"}}`,
|
||||
projecttestutil.TestTypingsLocation + "/node_modules/@types/jquery/index.d.ts": "export const x = 10;",
|
||||
projecttestutil.TestTypingsLocation + "/package.json": `{"dependencies":{"types-registry":"^0.1.317"},"devDependencies":{"@types/jquery":"^1.0.0"}}`,
|
||||
projecttestutil.TestTypingsLocation + "/package-lock.json": `{"dependencies":{"@types/jquery":{"version":"1.0.0"}}}`,
|
||||
}
|
||||
|
||||
session, _ := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": "export const y = 10",
|
||||
},
|
||||
})
|
||||
|
||||
uri := lsproto.DocumentUri("file:///user/username/projects/project/app.js")
|
||||
session.DidOpenFile(context.Background(), uri, 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
ls, err := session.GetLanguageService(context.Background(), uri)
|
||||
assert.NilError(t, err)
|
||||
program := ls.GetProgram()
|
||||
// Expect updated content from installed typings
|
||||
assert.Equal(t, program.GetSourceFile(projecttestutil.TestTypingsLocation+"/node_modules/@types/jquery/index.d.ts").Text(), "export const y = 10")
|
||||
})
|
||||
|
||||
t.Run("non-expired cache entry (inferred project, should not install typings)", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": "",
|
||||
"/user/username/projects/project/package.json": `{"name":"test","dependencies":{"jquery":"^3.1.0"}}`,
|
||||
projecttestutil.TestTypingsLocation + "/node_modules/@types/jquery/index.d.ts": "export const x = 10;",
|
||||
projecttestutil.TestTypingsLocation + "/package.json": `{"dependencies":{"types-registry":"^0.1.317"},"devDependencies":{"@types/jquery":"^1.3.0"}}`,
|
||||
projecttestutil.TestTypingsLocation + "/package-lock.json": `{"dependencies":{"@types/jquery":{"version":"1.3.0"}}}`,
|
||||
}
|
||||
|
||||
session, _ := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
TypesRegistry: []string{"jquery"},
|
||||
})
|
||||
|
||||
uri := lsproto.DocumentUri("file:///user/username/projects/project/app.js")
|
||||
session.DidOpenFile(context.Background(), uri, 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
ls, err := session.GetLanguageService(context.Background(), uri)
|
||||
assert.NilError(t, err)
|
||||
program := ls.GetProgram()
|
||||
// Expect existing content unchanged
|
||||
assert.Equal(t, program.GetSourceFile(projecttestutil.TestTypingsLocation+"/node_modules/@types/jquery/index.d.ts").Text(), "export const x = 10;")
|
||||
})
|
||||
|
||||
t.Run("deduplicate from local @types packages", func(t *testing.T) {
|
||||
t.Skip("Todo - implement removing local @types from include list")
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": "",
|
||||
"/user/username/projects/project/node_modules/@types/node/index.d.ts": "declare var node;",
|
||||
"/user/username/projects/project/jsconfig.json": `{
|
||||
"typeAcquisition": { "include": ["node"] }
|
||||
}`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
TypesRegistry: []string{"node"},
|
||||
})
|
||||
|
||||
uri := lsproto.DocumentUri("file:///user/username/projects/project/app.js")
|
||||
session.DidOpenFile(context.Background(), uri, 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// Only the types-registry should be installed; @types/node should NOT be installed since it exists locally
|
||||
npmCalls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, len(npmCalls), 1)
|
||||
assert.Equal(t, npmCalls[0].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.DeepEqual(t, npmCalls[0].Args, []string{"install", "--ignore-scripts", "types-registry@latest"})
|
||||
|
||||
// And the program should include the local @types/node declaration file
|
||||
ls, err := session.GetLanguageService(context.Background(), uri)
|
||||
assert.NilError(t, err)
|
||||
program := ls.GetProgram()
|
||||
assert.Assert(t, program.GetSourceFile("/user/username/projects/project/node_modules/@types/node/index.d.ts") != nil)
|
||||
})
|
||||
|
||||
t.Run("expired cache entry (inferred project, should install typings) lockfile3", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": "",
|
||||
"/user/username/projects/project/package.json": `{"name":"test","dependencies":{"jquery":"^3.1.0"}}`,
|
||||
projecttestutil.TestTypingsLocation + "/node_modules/@types/jquery/index.d.ts": "export const x = 10;",
|
||||
projecttestutil.TestTypingsLocation + "/package.json": `{"dependencies":{"types-registry":"^0.1.317"},"devDependencies":{"@types/jquery":"^1.0.0"}}`,
|
||||
projecttestutil.TestTypingsLocation + "/package-lock.json": `{"packages":{"node_modules/@types/jquery":{"version":"1.0.0"}}}`,
|
||||
}
|
||||
|
||||
session, _ := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": "export const y = 10",
|
||||
},
|
||||
})
|
||||
|
||||
uri := lsproto.DocumentUri("file:///user/username/projects/project/app.js")
|
||||
session.DidOpenFile(context.Background(), uri, 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
ls, err := session.GetLanguageService(context.Background(), uri)
|
||||
assert.NilError(t, err)
|
||||
program := ls.GetProgram()
|
||||
// Expect updated content from installed typings
|
||||
assert.Equal(t, program.GetSourceFile(projecttestutil.TestTypingsLocation+"/node_modules/@types/jquery/index.d.ts").Text(), "export const y = 10")
|
||||
})
|
||||
|
||||
t.Run("non-expired cache entry (inferred project, should not install typings) lockfile3", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": "",
|
||||
"/user/username/projects/project/package.json": `{"name":"test","dependencies":{"jquery":"^3.1.0"}}`,
|
||||
projecttestutil.TestTypingsLocation + "/node_modules/@types/jquery/index.d.ts": "export const x = 10;",
|
||||
projecttestutil.TestTypingsLocation + "/package.json": `{"dependencies":{"types-registry":"^0.1.317"},"devDependencies":{"@types/jquery":"^1.3.0"}}`,
|
||||
projecttestutil.TestTypingsLocation + "/package-lock.json": `{"packages":{"node_modules/@types/jquery":{"version":"1.3.0"}}}`,
|
||||
}
|
||||
|
||||
session, _ := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
TypesRegistry: []string{"jquery"},
|
||||
})
|
||||
|
||||
uri := lsproto.DocumentUri("file:///user/username/projects/project/app.js")
|
||||
session.DidOpenFile(context.Background(), uri, 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
ls, err := session.GetLanguageService(context.Background(), uri)
|
||||
assert.NilError(t, err)
|
||||
program := ls.GetProgram()
|
||||
// Expect existing content unchanged
|
||||
assert.Equal(t, program.GetSourceFile(projecttestutil.TestTypingsLocation+"/node_modules/@types/jquery/index.d.ts").Text(), "export const x = 10;")
|
||||
})
|
||||
|
||||
t.Run("should install typings for unresolved imports", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": `
|
||||
import * as fs from "fs";
|
||||
import * as commander from "commander";
|
||||
import * as component from "@ember/component";
|
||||
`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
PackageToFile: map[string]string{
|
||||
"node": "export let node: number",
|
||||
"commander": "export let commander: number",
|
||||
"ember__component": "export let ember__component: number",
|
||||
},
|
||||
})
|
||||
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"), 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// Check that npm install was called twice
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 2, len(calls), "Expected exactly 2 npm install calls")
|
||||
assert.Equal(t, calls[0].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.DeepEqual(t, calls[0].Args, []string{"install", "--ignore-scripts", "types-registry@latest"})
|
||||
|
||||
// The second call should install all three packages at once
|
||||
assert.Equal(t, calls[1].Cwd, projecttestutil.TestTypingsLocation)
|
||||
assert.Equal(t, calls[1].Args[0], "install")
|
||||
assert.Equal(t, calls[1].Args[1], "--ignore-scripts")
|
||||
// Check that all three packages are in the install command
|
||||
installArgs := calls[1].Args
|
||||
assert.Assert(t, slices.Contains(installArgs, "@types/ember__component@latest"))
|
||||
assert.Assert(t, slices.Contains(installArgs, "@types/commander@latest"))
|
||||
assert.Assert(t, slices.Contains(installArgs, "@types/node@latest"))
|
||||
|
||||
// Verify the types files were installed
|
||||
ls, err := session.GetLanguageService(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"))
|
||||
assert.NilError(t, err)
|
||||
program := ls.GetProgram()
|
||||
nodeTypesFile := program.GetSourceFile(projecttestutil.TestTypingsLocation + "/node_modules/@types/node/index.d.ts")
|
||||
assert.Assert(t, nodeTypesFile != nil, "node types should be installed")
|
||||
commanderTypesFile := program.GetSourceFile(projecttestutil.TestTypingsLocation + "/node_modules/@types/commander/index.d.ts")
|
||||
assert.Assert(t, commanderTypesFile != nil, "commander types should be installed")
|
||||
emberComponentTypesFile := program.GetSourceFile(projecttestutil.TestTypingsLocation + "/node_modules/@types/ember__component/index.d.ts")
|
||||
assert.Assert(t, emberComponentTypesFile != nil, "ember__component types should be installed")
|
||||
})
|
||||
|
||||
// Test that ATA works correctly when `WatchEnabled` is false but `TypingsLocation` is set.
|
||||
// Previously if `WatchEnabled` was false but `TypingsLocation` was set, ATA would run but
|
||||
// crash when cloning file-watcher data for a new snapshot.
|
||||
t.Run("ATA with WatchEnabled false should not panic", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": ``,
|
||||
"/user/username/projects/project/package.json": `{
|
||||
"name": "test",
|
||||
"dependencies": {
|
||||
"jquery": "^3.1.0"
|
||||
}
|
||||
}`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithOptionsAndTypingsInstaller(files, &project.SessionOptions{
|
||||
CurrentDirectory: "/",
|
||||
DefaultLibraryPath: bundled.LibPath(),
|
||||
TypingsLocation: projecttestutil.TestTypingsLocation,
|
||||
PositionEncoding: lsproto.PositionEncodingKindUTF8,
|
||||
WatchEnabled: false,
|
||||
LoggingEnabled: true,
|
||||
}, &projecttestutil.TypingsInstallerOptions{
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": `declare const $: { x: number }`,
|
||||
},
|
||||
})
|
||||
|
||||
// Open a file to trigger project creation and ATA.
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"), 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
// ATA should have run
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 2, len(calls), "Expected exactly 2 npm install calls")
|
||||
|
||||
// Getting the language service should not panic after
|
||||
// applying ATA changes and grabbing the latest snapshot.
|
||||
ls, err := session.GetLanguageService(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"))
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, ls != nil)
|
||||
})
|
||||
|
||||
ataDisabledCases := []struct {
|
||||
name string
|
||||
config map[string]any
|
||||
}{
|
||||
{
|
||||
name: "unified setting",
|
||||
config: map[string]any{
|
||||
"js/ts": map[string]any{
|
||||
"tsserver": map[string]any{
|
||||
"automaticTypeAcquisition": map[string]any{
|
||||
"enabled": false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "deprecated setting",
|
||||
config: map[string]any{
|
||||
"typescript": map[string]any{
|
||||
"disableAutomaticTypeAcquisition": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range ataDisabledCases {
|
||||
t.Run("ATA disabled via "+tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": ``,
|
||||
"/user/username/projects/project/package.json": `{
|
||||
"name": "test",
|
||||
"dependencies": {
|
||||
"jquery": "^3.1.0"
|
||||
}
|
||||
}`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": `declare const $: { x: number }`,
|
||||
},
|
||||
})
|
||||
|
||||
session.Configure(lsutil.ParseUserPreferences(tc.config))
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"), 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 0, len(calls), "Expected no npm install calls when ATA is disabled via "+tc.name)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("ATA re-enabled after being disabled triggers diagnostics refresh", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := map[string]any{
|
||||
"/user/username/projects/project/app.js": ``,
|
||||
"/user/username/projects/project/package.json": `{
|
||||
"name": "test",
|
||||
"dependencies": {
|
||||
"jquery": "^3.1.0"
|
||||
}
|
||||
}`,
|
||||
}
|
||||
|
||||
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
|
||||
PackageToFile: map[string]string{
|
||||
"jquery": `declare const $: { x: number }`,
|
||||
},
|
||||
})
|
||||
|
||||
// Disable ATA
|
||||
session.Configure(lsutil.ParseUserPreferences(map[string]any{
|
||||
"js/ts": map[string]any{
|
||||
"tsserver": map[string]any{
|
||||
"automaticTypeAcquisition": map[string]any{
|
||||
"enabled": false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
session.DidOpenFile(context.Background(), lsproto.DocumentUri("file:///user/username/projects/project/app.js"), 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
calls := utils.NpmExecutor().NpmInstallCalls()
|
||||
assert.Equal(t, 0, len(calls), "Expected no npm install calls when ATA is disabled")
|
||||
|
||||
baselineRefreshCount := len(utils.Client().RefreshDiagnosticsCalls())
|
||||
|
||||
// Re-enable ATA
|
||||
session.Configure(lsutil.ParseUserPreferences(map[string]any{}))
|
||||
session.WaitForBackgroundTasks()
|
||||
|
||||
refreshCount := len(utils.Client().RefreshDiagnosticsCalls())
|
||||
assert.Assert(t, refreshCount > baselineRefreshCount, "Expected RefreshDiagnostics call after ATA re-enabled")
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user