Skip to content

Commit e247eae

Browse files
committed
test: Cover stale configured project ATA results
1 parent 6781f4c commit e247eae

1 file changed

Lines changed: 179 additions & 0 deletions

File tree

‎tsc/internal/project/ata/ata_test.go‎

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,33 @@ package ata_test
33
import (
44
"context"
55
"slices"
6+
"sync"
67
"testing"
8+
"time"
79

810
"github.com/microsoft/TypeScript/tsc/internal/bundled"
11+
"github.com/microsoft/TypeScript/tsc/internal/collections"
12+
"github.com/microsoft/TypeScript/tsc/internal/core"
13+
"github.com/microsoft/TypeScript/tsc/internal/glob"
914
"github.com/microsoft/TypeScript/tsc/internal/ls/lsutil"
1015
"github.com/microsoft/TypeScript/tsc/internal/lsp/lsproto"
1116
"github.com/microsoft/TypeScript/tsc/internal/project"
1217
"github.com/microsoft/TypeScript/tsc/internal/testutil/projecttestutil"
18+
"github.com/microsoft/TypeScript/tsc/internal/tspath"
19+
"github.com/microsoft/TypeScript/tsc/internal/vfs/vfstest"
1320
"gotest.tools/v3/assert"
1421
)
1522

23+
func waitForInstall(t *testing.T, installStarted <-chan struct{}) {
24+
t.Helper()
25+
select {
26+
case <-installStarted:
27+
return
28+
case <-time.After(10 * time.Second):
29+
t.Fatal("timed out waiting for typings installation to start")
30+
}
31+
}
32+
1633
func TestATA(t *testing.T) {
1734
t.Parallel()
1835
if !bundled.Embedded {
@@ -89,6 +106,168 @@ func TestATA(t *testing.T) {
89106
assert.Equal(t, len(utils.Client().RefreshDiagnosticsCalls()), 1)
90107
})
91108

109+
t.Run("configured project ignores ATA results from before manifest invalidation", func(t *testing.T) {
110+
t.Parallel()
111+
112+
files := map[string]any{
113+
"/user/username/projects/project/app.js": ``,
114+
"/user/username/projects/project/tsconfig.json": `{
115+
"compilerOptions": { "allowJs": true },
116+
"typeAcquisition": { "enable": true },
117+
}`,
118+
"/user/username/projects/project/package.json": `{
119+
"name": "test",
120+
"dependencies": {
121+
"jquery": "^3.1.0"
122+
}
123+
}`,
124+
}
125+
126+
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
127+
PackageToFile: map[string]string{
128+
"commander": `declare const commander: { x: number }`,
129+
"jquery": `declare const $: { x: number }`,
130+
},
131+
})
132+
133+
ctx := context.Background()
134+
uri := lsproto.DocumentUri("file:///user/username/projects/project/app.js")
135+
packageJSONURI := lsproto.DocumentUri("file:///user/username/projects/project/package.json")
136+
session.DidOpenFile(ctx, uri, 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
137+
session.WaitForBackgroundTasks()
138+
_, err := session.GetLanguageService(ctx, uri)
139+
assert.NilError(t, err)
140+
session.WaitForBackgroundTasks()
141+
142+
originalNpmInstall := utils.NpmExecutor().NpmInstallFunc
143+
installStarted := make(chan struct{}, 1)
144+
releaseInstall := make(chan struct{})
145+
var releaseInstallOnce sync.Once
146+
release := func() { releaseInstallOnce.Do(func() { close(releaseInstall) }) }
147+
defer release()
148+
utils.NpmExecutor().NpmInstallFunc = func(cwd string, args []string) ([]byte, error) {
149+
if slices.Contains(args, "@types/commander@latest") {
150+
installStarted <- struct{}{}
151+
<-releaseInstall
152+
}
153+
return originalNpmInstall(cwd, args)
154+
}
155+
156+
err = utils.FS().WriteFile(packageJSONURI.FileName(), `{
157+
"name": "test",
158+
"dependencies": {
159+
"commander": "^14.0.0",
160+
"jquery": "^3.1.0"
161+
}
162+
}`)
163+
assert.NilError(t, err)
164+
session.DidChangeWatchedFiles(ctx, []*lsproto.FileEvent{{
165+
Uri: packageJSONURI,
166+
Type: lsproto.FileChangeTypeChanged,
167+
}})
168+
snapshot, err := session.APIUpdate(ctx, project.FileChangeSummary{}, nil)
169+
assert.NilError(t, err)
170+
snapshot.Deref()
171+
waitForInstall(t, installStarted)
172+
173+
session.Configure(lsutil.ParseUserPreferences(map[string]any{
174+
"js/ts": map[string]any{
175+
"tsserver": map[string]any{
176+
"automaticTypeAcquisition": map[string]any{
177+
"enabled": false,
178+
},
179+
},
180+
},
181+
}))
182+
err = utils.FS().WriteFile(packageJSONURI.FileName(), files["/user/username/projects/project/package.json"].(string))
183+
assert.NilError(t, err)
184+
session.DidChangeWatchedFiles(ctx, []*lsproto.FileEvent{{
185+
Uri: packageJSONURI,
186+
Type: lsproto.FileChangeTypeChanged,
187+
}})
188+
snapshot, err = session.APIUpdate(ctx, project.FileChangeSummary{}, nil)
189+
assert.NilError(t, err)
190+
snapshot.Deref()
191+
192+
release()
193+
session.WaitForBackgroundTasks()
194+
195+
ls, err := session.GetLanguageService(ctx, uri)
196+
assert.NilError(t, err)
197+
commanderTypesFile := ls.GetProgram().GetSourceFile(projecttestutil.TestTypingsLocation + "/node_modules/@types/commander/index.d.ts")
198+
assert.Assert(t, commanderTypesFile == nil, "stale commander typings should not be applied after the manifest changes")
199+
})
200+
201+
t.Run("configured project ignores ATA results from a previous project lifetime", func(t *testing.T) {
202+
t.Parallel()
203+
204+
files := map[string]any{
205+
"/user/username/projects/project/app.js": ``,
206+
"/user/username/projects/project/tsconfig.json": `{
207+
"compilerOptions": { "allowJs": true },
208+
"typeAcquisition": { "enable": true },
209+
}`,
210+
"/user/username/projects/project/package.json": `{
211+
"name": "test",
212+
"dependencies": {
213+
"commander": "^14.0.0"
214+
}
215+
}`,
216+
}
217+
218+
session, utils := projecttestutil.SetupWithTypingsInstaller(files, &projecttestutil.TypingsInstallerOptions{
219+
PackageToFile: map[string]string{
220+
"commander": `declare const commander: { x: number }`,
221+
},
222+
})
223+
224+
originalNpmInstall := utils.NpmExecutor().NpmInstallFunc
225+
installStarted := make(chan struct{}, 1)
226+
releaseInstall := make(chan struct{})
227+
var releaseInstallOnce sync.Once
228+
release := func() { releaseInstallOnce.Do(func() { close(releaseInstall) }) }
229+
defer release()
230+
utils.NpmExecutor().NpmInstallFunc = func(cwd string, args []string) ([]byte, error) {
231+
if slices.Contains(args, "@types/commander@latest") {
232+
installStarted <- struct{}{}
233+
<-releaseInstall
234+
}
235+
return originalNpmInstall(cwd, args)
236+
}
237+
238+
ctx := context.Background()
239+
uri := lsproto.DocumentUri("file:///user/username/projects/project/app.js")
240+
session.DidOpenFile(ctx, uri, 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
241+
waitForInstall(t, installStarted)
242+
243+
session.DidCloseFile(ctx, uri)
244+
snapshot, err := session.APIUpdate(ctx, project.FileChangeSummary{}, &project.APISnapshotRequest{
245+
CloseFiles: &collections.Set[tspath.Path]{},
246+
})
247+
assert.NilError(t, err)
248+
assert.Equal(t, len(snapshot.ProjectCollection.Projects()), 0)
249+
snapshot.Deref()
250+
251+
session.Configure(lsutil.ParseUserPreferences(map[string]any{
252+
"js/ts": map[string]any{
253+
"tsserver": map[string]any{
254+
"automaticTypeAcquisition": map[string]any{
255+
"enabled": false,
256+
},
257+
},
258+
},
259+
}))
260+
session.DidOpenFile(ctx, uri, 1, files["/user/username/projects/project/app.js"].(string), lsproto.LanguageKindJavaScript)
261+
262+
release()
263+
session.WaitForBackgroundTasks()
264+
265+
ls, err := session.GetLanguageService(ctx, uri)
266+
assert.NilError(t, err)
267+
commanderTypesFile := ls.GetProgram().GetSourceFile(projecttestutil.TestTypingsLocation + "/node_modules/@types/commander/index.d.ts")
268+
assert.Assert(t, commanderTypesFile == nil, "stale commander typings should not be applied to a replacement project")
269+
})
270+
92271
t.Run("inferred projects", func(t *testing.T) {
93272
t.Parallel()
94273

0 commit comments

Comments
 (0)