diff --git a/internal/runner/jest.go b/internal/runner/jest.go index 7c0b59e..6520b86 100644 --- a/internal/runner/jest.go +++ b/internal/runner/jest.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "os/exec" + "path/filepath" "regexp" "slices" "strings" @@ -112,12 +113,22 @@ func (j Jest) Run(result *RunResult, testCases []plan.TestCase, retry bool) erro status = TestStatusSkipped } + wordDir, err := os.Getwd() + if err != nil { + return fmt.Errorf("failed to get current working directory: %v", err) + } + testPath, err := filepath.Rel(wordDir, testResult.FileName) + if err != nil { + return fmt.Errorf("failed to get relative path of test file: %v", err) + } + // The scope and name has to match with the scope generated by Buildkite test collector. // For more details, see: // [Buildkite Test Collector - Jest implementation](https://github.com/buildkite/test-collector-javascript/blob/42b803a618a15a07edf0169038ef4b5eba88f98d/jest/reporter.js#L40) testCase := plan.TestCase{ Name: example.Title, Scope: strings.Join(example.AncestorTitles, " "), + Path: fmt.Sprintf("%s:%d:%d", testPath, example.Location.Line, example.Location.Column), } result.RecordTestResult(testCase, status) @@ -136,6 +147,10 @@ type JestExample struct { Status string `json:"status"` Title string `json:"title"` AncestorTitles []string `json:"ancestorTitles"` + Location struct { + Line int + Column int + } } type JestReport struct { @@ -143,6 +158,7 @@ type JestReport struct { NumRuntimeErrorTestSuites int TestResults []struct { AssertionResults []JestExample + FileName string `json:"name"` } } diff --git a/internal/runner/jest_test.go b/internal/runner/jest_test.go index dca567c..d80cc01 100644 --- a/internal/runner/jest_test.go +++ b/internal/runner/jest_test.go @@ -134,6 +134,7 @@ func TestJestRun_TestFailed(t *testing.T) { { Scope: "this will fail", Name: "for sure", + Path: "failure.spec.js:2:3", }, } @@ -176,12 +177,12 @@ func TestJestRun_TestSkipped(t *testing.T) { t.Errorf("Jest.Run(%q) RunResult.Status = %v, want %v", testCases, result.Status(), RunStatusPassed) } - test := result.tests["this will be skipped/for sure"] + test := result.tests["this will be skipped/for sure/skipped.spec.js:2:3"] if test.Status != TestStatusSkipped { t.Errorf("Jest.Run(%q) test.Status = %v, want %v", testCases, test.Status, TestStatusSkipped) } - todoTest := result.tests["this will be skipped/todo yeah"] + todoTest := result.tests["this will be skipped/todo yeah/skipped.spec.js:6:6"] if todoTest.Status != TestStatusSkipped { t.Errorf("Jest.Run(%q) todoTest.Status = %v, want %v", testCases, todoTest.Status, TestStatusSkipped) } diff --git a/internal/runner/testdata/jest/jest.config.js b/internal/runner/testdata/jest/jest.config.js index b9ff3e5..8c573fb 100644 --- a/internal/runner/testdata/jest/jest.config.js +++ b/internal/runner/testdata/jest/jest.config.js @@ -1,3 +1,8 @@ // This file is intentionally left blank. // Jest requires a jest.config.js file to run. It can be empty, so it doesn't // serve much use other than to satisfy Jest for the Jest tests. +const config = { + "testLocationInResults": true, +}; + +module.exports = config;