Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

223 lines
6.4 KiB
Go

package tsalias
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestResolve_WildcardAlias(t *testing.T) {
m := &Map{
Entries: []Alias{
{AliasPrefix: "@/", TargetPrefix: "src/", HasWildcard: true},
},
}
assert.Equal(t, "src/lib/foo", Resolve(m, "@/lib/foo"))
}
func TestResolve_ExactAlias(t *testing.T) {
m := &Map{
Entries: []Alias{
{AliasPrefix: "$utils", TargetPrefix: "src/util/index.ts"},
},
}
assert.Equal(t, "src/util/index", Resolve(m, "$utils"), "extension stripped")
assert.Equal(t, "", Resolve(m, "$utils/format"), "exact match doesn't fire on a longer specifier")
}
func TestResolve_BaseURLPrepended(t *testing.T) {
m := &Map{
BaseURL: "src",
Entries: []Alias{
{AliasPrefix: "@/", TargetPrefix: "", HasWildcard: true},
},
}
assert.Equal(t, "src/lib/foo", Resolve(m, "@/lib/foo"))
}
func TestResolve_LongestPrefixWins(t *testing.T) {
m := &Map{
Entries: []Alias{
{AliasPrefix: "@components/", TargetPrefix: "src/components/", HasWildcard: true},
{AliasPrefix: "@/", TargetPrefix: "src/", HasWildcard: true},
},
}
// Caller sorts entries; assert that with the sorted order the
// longer prefix matches.
assert.Equal(t, "src/components/Button", Resolve(m, "@components/Button"))
assert.Equal(t, "src/Button", Resolve(m, "@/Button"))
}
func TestResolve_NoMatch(t *testing.T) {
m := &Map{
Entries: []Alias{
{AliasPrefix: "@/", TargetPrefix: "src/", HasWildcard: true},
},
}
assert.Equal(t, "", Resolve(m, "react"))
assert.Equal(t, "", Resolve(nil, "@/foo"))
}
func TestLoad_FindsTsconfigAtRoot(t *testing.T) {
dir := t.TempDir()
cfg := `{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@app": ["src/app/index.ts"]
}
}
}`
require.NoError(t, os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(cfg), 0644))
coll := Load(dir)
require.NotNil(t, coll)
require.Len(t, coll.Maps(), 1)
m := coll.FindForFile("src/components/Button.tsx")
require.NotNil(t, m)
assert.Equal(t, "src/foo", Resolve(m, "@/foo"))
assert.Equal(t, "src/app/index", Resolve(m, "@app"))
}
func TestLoad_NestedTsconfigWinsForChildren(t *testing.T) {
dir := t.TempDir()
rootCfg := `{
"compilerOptions": {
"paths": { "@/*": ["root/*"] }
}
}`
require.NoError(t, os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(rootCfg), 0644))
nestedDir := filepath.Join(dir, "packages", "web")
require.NoError(t, os.MkdirAll(nestedDir, 0755))
nestedCfg := `{
"compilerOptions": {
"paths": { "@/*": ["nested/*"] }
}
}`
require.NoError(t, os.WriteFile(filepath.Join(nestedDir, "tsconfig.json"), []byte(nestedCfg), 0644))
coll := Load(dir)
require.NotNil(t, coll)
// A file under packages/web/ picks up the nested map.
m := coll.FindForFile("packages/web/src/App.tsx")
require.NotNil(t, m)
assert.Equal(t, "packages/web/nested/foo", Resolve(m, "@/foo"),
"nested config target is rooted at the config's own directory")
// A file outside packages/web/ falls back to the root map.
m = coll.FindForFile("apps/api/src/server.ts")
require.NotNil(t, m)
assert.Equal(t, "root/foo", Resolve(m, "@/foo"))
}
func TestLoad_SkipsNodeModules(t *testing.T) {
dir := t.TempDir()
nm := filepath.Join(dir, "node_modules", "some-pkg")
require.NoError(t, os.MkdirAll(nm, 0755))
require.NoError(t, os.WriteFile(filepath.Join(nm, "tsconfig.json"),
[]byte(`{"compilerOptions":{"paths":{"@/*":["should/not/be/used/*"]}}}`), 0644))
coll := Load(dir)
// Either nil (no usable configs found) or a collection with zero
// entries — both prove the node_modules config was skipped.
if coll == nil {
return
}
for _, m := range coll.Maps() {
assert.NotContains(t, m.DirPrefix, "node_modules")
}
}
func TestLoad_NoConfigsReturnsNil(t *testing.T) {
dir := t.TempDir()
assert.Nil(t, Load(dir))
}
func TestLoad_MalformedConfigSkipped(t *testing.T) {
dir := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(dir, "tsconfig.json"),
[]byte(`{ this is not json`), 0644))
// Should not panic; should return nil because no usable config.
assert.Nil(t, Load(dir))
}
func tsaliasWrite(t *testing.T, path, content string) {
t.Helper()
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
t.Fatal(err)
}
}
// TestJSONCTolerantAliasResolution verifies a tsconfig using // and /* */
// comments and trailing commas still yields its aliases (instead of dropping
// every alias for the repo), and that a multi-target alias resolves to the
// target that actually exists on disk rather than blindly to the first.
func TestJSONCTolerantAliasResolution(t *testing.T) {
root := t.TempDir()
cfg := `{
// path aliases for the app
"compilerOptions": {
"baseUrl": ".",
"paths": {
/* first target does not exist; second does */
"@/*": ["nonexistent/*", "src/*"],
"$config": ["src/config.ts"],
},
},
}`
tsaliasWrite(t, filepath.Join(root, "tsconfig.json"), cfg)
tsaliasWrite(t, filepath.Join(root, "src", "Button.ts"), "export const Button = 1;")
tsaliasWrite(t, filepath.Join(root, "src", "config.ts"), "export const c = 1;")
col := Load(root)
require.NotNil(t, col, "JSONC tsconfig must still produce a collection")
m := col.FindForFile("app.ts")
require.NotNil(t, m)
require.NotEmpty(t, m.Entries, "comments / trailing commas must not wipe the aliases")
// Disk-grounded multi-target: @/Button resolves to the existing src/Button,
// not the first (nonexistent) target.
assert.Equal(t, "src/Button", Resolve(m, "@/Button"))
assert.Equal(t, "src/config", Resolve(m, "$config"))
// An import with no matching alias still resolves to "".
assert.Equal(t, "", Resolve(m, "react"))
}
// TestStripJSONCPreservesStrings ensures the stripper never touches
// comment-like or comma sequences inside string literals.
func TestStripJSONCPreservesStrings(t *testing.T) {
in := []byte(`{"a": "http://x.y/* z", "b": "trailing,", /* c */ "d": 1,}`)
out := string(stripJSONC(in))
if !contains(out, `"http://x.y/* z"`) {
t.Fatalf("string content was mangled: %s", out)
}
if !contains(out, `"trailing,"`) {
t.Fatalf("comma inside string was stripped: %s", out)
}
if contains(out, "/* c */") {
t.Fatalf("block comment survived: %s", out)
}
}
func contains(s, sub string) bool {
return len(s) >= len(sub) && (func() bool {
for i := 0; i+len(sub) <= len(s); i++ {
if s[i:i+len(sub)] == sub {
return true
}
}
return false
})()
}