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
|
package resolver
import (
"encoding/json"
"fmt"
"io/ioutil"
"strings"
"testing"
"github.com/evanw/esbuild/internal/config"
"github.com/evanw/esbuild/internal/fs"
"github.com/evanw/esbuild/internal/js_parser"
"github.com/evanw/esbuild/internal/logger"
"github.com/evanw/esbuild/internal/test"
)
type pnpTestExpectation struct {
Manifest interface{}
Tests []pnpTest
}
type pnpTest struct {
It string
Imported string
Importer string
Expected string
}
func TestYarnPnP(t *testing.T) {
t.Helper()
contents, err := ioutil.ReadFile("testExpectations.json")
if err != nil {
t.Fatalf("Failed to read testExpectations.json: %s", err.Error())
}
var expectations []pnpTestExpectation
err = json.Unmarshal(contents, &expectations)
if err != nil {
t.Fatalf("Failed to parse testExpectations.json: %s", err.Error())
}
for i, expectation := range expectations {
path := fmt.Sprintf("testExpectations[%d].manifest", i)
contents, err := json.Marshal(expectation.Manifest)
if err != nil {
t.Fatalf("Failed to generate JSON: %s", err.Error())
}
source := logger.Source{
KeyPath: logger.Path{Text: path},
PrettyPaths: logger.PrettyPaths{Abs: path, Rel: path},
Contents: string(contents),
}
tempLog := logger.NewDeferLog(logger.DeferLogAll, nil)
expr, ok := js_parser.ParseJSON(tempLog, source, js_parser.JSONOptions{})
if !ok {
t.Fatalf("Failed to re-parse JSON: %s", path)
}
msgs := tempLog.Done()
if len(msgs) != 0 {
t.Fatalf("Log not empty after re-parsing JSON: %s", path)
}
manifest := compileYarnPnPData(path, "/path/to/project/", expr, source)
for _, current := range expectation.Tests {
func(current pnpTest) {
t.Run(current.It, func(t *testing.T) {
fs := fs.MockFS(nil, fs.MockUnix, "/")
r := resolverQuery{Resolver: NewResolver(config.BuildCall, fs, logger.NewDeferLog(logger.DeferLogNoVerboseOrDebug, nil), nil, &config.Options{})}
result := r.resolveToUnqualified(current.Imported, current.Importer, manifest)
var observed string
switch result.status {
case pnpSuccess:
observed = fs.Join(result.pkgDirPath, result.pkgSubpath)
case pnpSkipped:
observed = current.Imported
default:
observed = "error!"
}
// If a we aren't going through PnP, then we should just run the
// normal node module resolution rules instead of throwing an error.
// However, this test requires us to throw an error, which seems
// incorrect. So we change the expected value of the test instead.
expected := current.Expected
if current.It == `shouldn't go through PnP when trying to resolve dependencies from packages covered by ignorePatternData` {
expected = current.Imported
} else if observed != "error!" && !strings.HasSuffix(observed, "/") {
// This is important for matching Yarn PnP's expectations in tests,
// but it's important for esbuild that the slash isn't present.
// Otherwise esbuild's implementation of node module resolution
// (which runs after Yarn PnP resolution) will fail. Specifically
// "foo/" will look for "foo/foo.js" instead of "foo/index.js".
observed += "/"
}
test.AssertEqualWithDiff(t, observed, expected)
})
}(current)
}
}
}
|