File: yarnpnp_test.go

package info (click to toggle)
golang-github-evanw-esbuild 0.25.10-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 10,184 kB
  • sloc: javascript: 28,602; makefile: 856; sh: 17
file content (105 lines) | stat: -rw-r--r-- 3,298 bytes parent folder | download
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)
		}
	}
}