nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: ogen-go/ogen
Pull request #295 (2022-04-13 17:58:47)

fix(jsonschema): add oneOf/anyOf/allOf to refcache before parsing


Patch:
diff --git a/jsonschema/parser.go b/jsonschema/parser.go
index 8fc9bda1..1f0d1fa1 100644
--- a/jsonschema/parser.go
+++ b/jsonschema/parser.go
@@ -119,20 +119,17 @@ func (p *Parser) parseSchema(schema *RawSchema, ctx resolveCtx, hook func(*Schem
 			Format: schema.Format,
 		}), nil
 	case len(schema.OneOf) > 0:
+		s := hook(&Schema{})
+
 		schemas, err := p.parseMany(schema.OneOf, ctx)
 		if err != nil {
 			return nil, errors.Wrapf(err, "oneOf")
 		}
+		s.OneOf = schemas
 
-		return hook(&Schema{OneOf: schemas}), nil
+		return s, nil
 	case len(schema.AnyOf) > 0:
-		schemas, err := p.parseMany(schema.AnyOf, ctx)
-		if err != nil {
-			return nil, errors.Wrapf(err, "anyOf")
-		}
-
-		return hook(&Schema{
-			AnyOf: schemas,
+		s := hook(&Schema{
 			// Object validators
 			MaxProperties: schema.MaxProperties,
 			MinProperties: schema.MinProperties,
@@ -150,14 +147,25 @@ func (p *Parser) parseSchema(schema *RawSchema, ctx resolveCtx, hook func(*Schem
 			MaxLength: schema.MaxLength,
 			MinLength: schema.MinLength,
 			Pattern:   schema.Pattern,
-		}), nil
+		})
+
+		schemas, err := p.parseMany(schema.AnyOf, ctx)
+		if err != nil {
+			return nil, errors.Wrapf(err, "anyOf")
+		}
+		s.AnyOf = schemas
+
+		return s, nil
 	case len(schema.AllOf) > 0:
+		s := hook(&Schema{})
+
 		schemas, err := p.parseMany(schema.AllOf, ctx)
 		if err != nil {
 			return nil, errors.Wrap(err, "allOf")
 		}
+		s.AllOf = schemas
 
-		return hook(&Schema{AllOf: schemas}), nil
+		return s, nil
 	}
 
 	typ := schema.Type


Test patch:
diff --git a/gen/_testdata/jsonschema/recursive.json b/gen/_testdata/jsonschema/recursive.json
new file mode 100644
index 00000000..6cb27ef9
--- /dev/null
+++ b/gen/_testdata/jsonschema/recursive.json
@@ -0,0 +1,45 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "type": "object",
+  "properties": {
+    "foo": {
+      "$ref": "#/definitions/schemaOrReference"
+    }
+  },
+  "definitions": {
+    "schema": {
+      "type": "object",
+      "properties": {
+        "allOf": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/schemaOrReference"
+          },
+          "minItems": 1
+        }
+      }
+    },
+    "reference": {
+      "type": "object",
+      "required": [
+        "$ref"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "$ref": {
+          "type": "string"
+        }
+      }
+    },
+    "schemaOrReference": {
+      "oneOf": [
+        {
+          "$ref": "#/definitions/schema"
+        },
+        {
+          "$ref": "#/definitions/reference"
+        }
+      ]
+    }
+  }
+}
Repository: ogen-go/ogen
Pull request #297 (2022-04-14 19:06:42)

fix(jsonschema): ref-to-ref handling, prevent false-positive infinite recursion detection


Patch:
diff --git a/jsonschema/parser.go b/jsonschema/parser.go
index d49c3305..0255abb1 100644
--- a/jsonschema/parser.go
+++ b/jsonschema/parser.go
@@ -366,6 +366,10 @@ func (p *Parser) resolve(ref string, ctx resolveCtx) (*Schema, error) {
 		return nil, errors.New("infinite recursion")
 	}
 	ctx[ref] = struct{}{}
+	defer func() {
+		// Drop the resolved ref to prevent false-positive infinite recursion detection.
+		delete(ctx, ref)
+	}()
 
 	raw, err := p.resolver.ResolveReference(ref)
 	if err != nil {


Test patch:
diff --git a/jsonschema/parser_test.go b/jsonschema/parser_test.go
index 4fec4186..a4758924 100644
--- a/jsonschema/parser_test.go
+++ b/jsonschema/parser_test.go
@@ -177,6 +177,41 @@ func TestSchemaInfiniteRecursion(t *testing.T) {
 	}
 }
 
+func TestSchemaRefToRef(t *testing.T) {
+	// This regression test checks ref-to-ref handling.
+	//
+	// Such schema caused a false-positive infinite recursion error before.
+	components := components{
+		"first": {
+			Ref: "#/components/schemas/second",
+		},
+		"second": {
+			Ref: "#/components/schemas/third",
+		},
+		"third": {
+			Ref: "#/components/schemas/actual",
+		},
+		"actual": {
+			Type: "integer",
+		},
+		"referer": {
+			Type: "object",
+			Properties: RawProperties{
+				{"Ref1", &RawSchema{Ref: "#/components/schemas/first"}},
+				{"Ref2", &RawSchema{Ref: "#/components/schemas/first"}},
+				{"Ref3", &RawSchema{Ref: "#/components/schemas/second"}},
+			},
+		},
+	}
+	parser := NewParser(Settings{
+		Resolver: components,
+	})
+	_, err := parser.Parse(&RawSchema{
+		Ref: "#/components/schemas/referer",
+	})
+	require.NoError(t, err)
+}
+
 func TestSchemaSideEffects(t *testing.T) {
 	expectSide := []*Schema{
 		{
Repository: ogen-go/ogen
Pull request #339 (2022-05-13 10:20:14)

fix(gen): handle path parameters with unsupported content correctly


Patch:
diff --git a/gen/gen_parameters.go b/gen/gen_parameters.go
index de7fcabf..6bb629a0 100644
--- a/gen/gen_parameters.go
+++ b/gen/gen_parameters.go
@@ -14,10 +14,16 @@ func (g *Generator) generateParameters(ctx *genctx, opName string, params []*ope
 	result := make([]*ir.Parameter, 0, len(params))
 	for i, p := range params {
 		if p.Content != nil {
-			if err := g.fail(&ErrNotImplemented{"parameter content field"}); err != nil {
+			notImplemented := &ErrNotImplemented{"parameter content field"}
+			if err := g.fail(notImplemented); err != nil {
 				return nil, errors.Wrap(err, "fail")
 			}
 
+			// Path parameters are required.
+			if p.In == openapi.LocationPath {
+				return nil, notImplemented
+			}
+
 			continue
 		}
 


Test patch:
diff --git a/_testdata/positive/test_content_path_parameter.yml b/_testdata/positive/test_content_path_parameter.yml
new file mode 100644
index 00000000..f085f39e
--- /dev/null
+++ b/_testdata/positive/test_content_path_parameter.yml
@@ -0,0 +1,22 @@
+openapi: 3.0.0
+info:
+  title: Test schema
+  version: 0.1.0
+paths:
+  /{shortURL}:
+    get:
+      parameters:
+        - name: shortURL
+          in: path
+          required: true
+          content:
+            '*/*':
+              schema:
+                type: string
+      responses:
+        '200':
+          description: Response
+          content:
+            application/json:
+              schema:
+                type: string
diff --git a/gen_test.go b/gen_test.go
index 14c52167..babf5f20 100644
--- a/gen_test.go
+++ b/gen_test.go
@@ -4,6 +4,7 @@ import (
 	"embed"
 	"io/fs"
 	"path/filepath"
+	"runtime/debug"
 	"strings"
 	"testing"
 
@@ -33,7 +34,7 @@ func testGenerate(_ bool, name string, ignore ...string) func(t *testing.T) {
 		t.Run("Gen", func(t *testing.T) {
 			defer func() {
 				if rr := recover(); rr != nil {
-					t.Fatalf("panic: %+v", rr)
+					t.Fatalf("panic: %+v\n%s", rr, debug.Stack())
 				}
 			}()
Repository: ogen-go/ogen
Pull request #653 (2022-11-02 15:27:53)

feat(gen): implement enum `allOf` merge


Patch:
diff --git a/gen/schema_gen_sum.go b/gen/schema_gen_sum.go
index 78db8847..66871a0e 100644
--- a/gen/schema_gen_sum.go
+++ b/gen/schema_gen_sum.go
@@ -728,6 +728,26 @@ func mergeEnums(s1, s2 *jsonschema.Schema) ([]any, error) {
 		return s2.Enum, nil
 	}
 
-	// TODO: Merge enums and check for duplicates.
-	return nil, &ErrNotImplemented{Name: "allOf enum merging"}
+	var (
+		small = s1.Enum
+		big   = s2.Enum
+	)
+	if len(s1.Enum) > len(s2.Enum) {
+		small = s2.Enum
+		big = s1.Enum
+	}
+	// Keep values that are present in both enums.
+	var result []any
+	for _, v := range small {
+		// FIXME(tdakkota): quadratic complexity.
+		if xslices.ContainsFunc(big, func(x any) bool {
+			return reflect.DeepEqual(x, v)
+		}) {
+			result = append(result, v)
+		}
+	}
+	if len(result) == 0 {
+		return nil, &ErrNotImplemented{Name: "allOf enum merging"}
+	}
+	return result, nil
 }


Test patch:
diff --git a/gen/schema_gen_sum_test.go b/gen/schema_gen_sum_test.go
new file mode 100644
index 00000000..729432a2
--- /dev/null
+++ b/gen/schema_gen_sum_test.go
@@ -0,0 +1,69 @@
+package gen
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+
+	"github.com/ogen-go/ogen/jsonschema"
+)
+
+func Test_mergeEnums(t *testing.T) {
+	tests := []struct {
+		a, b    []any
+		want    []any
+		wantErr bool
+	}{
+		// Fast path.
+		{nil, nil, nil, false},
+		{[]any{1, 2, 3}, nil, []any{1, 2, 3}, false},
+		// Merge.
+		{[]any{1, 2, 3}, []any{3, 4, 5}, []any{3}, false},
+		{[]any{3}, []any{3, 4, 5}, []any{3}, false},
+		{[]any{"a"}, []any{"b", "a", "c"}, []any{"a"}, false},
+		{[]any{
+			"a", "b",
+			0, 2,
+			false, true,
+			[]any{1}, []any{2},
+		}, []any{
+			"a", "c",
+			0, 3,
+			true,
+			[]any{1}, []any{[]any{1}},
+		}, []any{
+			"a",
+			0,
+			true,
+			[]any{1},
+		}, false},
+		// No common values.
+		{[]any{1, 2, 3}, []any{4, 5, 6}, nil, true},
+	}
+	for i, tt := range tests {
+		tt := tt
+		t.Run(fmt.Sprintf("Test%d", i+1), func(t *testing.T) {
+			a := require.New(t)
+
+			// Ensure that merge is commutative.
+			got1, err1 := mergeEnums(
+				&jsonschema.Schema{Enum: tt.a},
+				&jsonschema.Schema{Enum: tt.b},
+			)
+			got2, err2 := mergeEnums(
+				&jsonschema.Schema{Enum: tt.b},
+				&jsonschema.Schema{Enum: tt.a},
+			)
+			if tt.wantErr {
+				a.Error(err1)
+				a.Error(err2)
+				return
+			}
+			a.NoError(err1)
+			a.NoError(err2)
+			a.Equal(tt.want, got1)
+			a.Equal(tt.want, got2)
+		})
+	}
+}
Repository: ogen-go/ogen
Pull request #673 (2022-11-13 11:51:24)

fix(http): pass multipart writer error


Patch:
diff --git a/http/multipart.go b/http/multipart.go
index 8407389b..69a15d53 100644
--- a/http/multipart.go
+++ b/http/multipart.go
@@ -16,7 +16,11 @@ func CreateMultipartBody(cb func(mw *multipart.Writer) error) (body io.ReadClose
 	wg.Go(func() (rerr error) {
 		defer func() {
 			_ = mw.Close()
-			_ = pipew.Close()
+			if rerr != nil {
+				_ = pipew.CloseWithError(rerr)
+			} else {
+				_ = pipew.Close()
+			}
 		}()
 		return cb(mw)
 	})
@@ -38,12 +42,12 @@ type bodyReader struct {
 	wg *errgroup.Group
 }
 
-func (w bodyReader) Read(p []byte) (int, error) {
-	return w.r.Read(p)
+func (r bodyReader) Read(p []byte) (int, error) {
+	return r.r.Read(p)
 }
 
-func (w bodyReader) Close() (rerr error) {
-	rerr = w.r.Close()
-	_ = w.wg.Wait()
+func (r bodyReader) Close() (rerr error) {
+	rerr = r.r.Close()
+	_ = r.wg.Wait()
 	return rerr
 }


Test patch:
diff --git a/http/multipart_test.go b/http/multipart_test.go
new file mode 100644
index 00000000..1b0d6734
--- /dev/null
+++ b/http/multipart_test.go
@@ -0,0 +1,46 @@
+package http
+
+import (
+	"fmt"
+	"io"
+	"mime/multipart"
+	"strings"
+	"testing"
+
+	"github.com/go-faster/errors"
+	"github.com/stretchr/testify/require"
+)
+
+func TestCreateMultipartBody(t *testing.T) {
+	t.Run("WriteError", func(t *testing.T) {
+		testErr := errors.New("test error")
+		reader, _ := CreateMultipartBody(func(mw *multipart.Writer) error {
+			return testErr
+		})
+
+		_, err := io.ReadAll(reader)
+		require.ErrorIs(t, err, testErr)
+	})
+	t.Run("Good", func(t *testing.T) {
+		reader, boundary := CreateMultipartBody(func(mw *multipart.Writer) error {
+			w, err := mw.CreateFormFile("file", "file.txt")
+			if err != nil {
+				return err
+			}
+			_, err = io.WriteString(w, "text data")
+			return err
+		})
+
+		a := require.New(t)
+		var s strings.Builder
+		_, err := io.Copy(&s, reader)
+		a.NoError(err)
+
+		expected := fmt.Sprintf("--%[1]s"+"\r\n"+
+			`Content-Disposition: form-data; name="file"; filename="file.txt"`+"\r\n"+
+			`Content-Type: application/octet-stream`+"\r\n\r\n"+
+			`text data`+"\r\n"+
+			`--%[1]s--`+"\r\n", boundary)
+		a.Equal(expected, s.String())
+	})
+}
Repository: ogen-go/ogen
Pull request #971 (2023-07-08 09:10:18)

Fix logic for decoding valueless query parameter into an array
Given the schema below,

```yaml
/resource:
  get:
  parameters:
    - name: my_enums
      in: query
      required: true
      type: array
      items:
        type: string
        enum:
          - a
          - b
```

hitting the generated ogen server API using the generated ogen client with an empty array raises validation error, because the client encodes `[]MyEnums{}` into `/resource?my_eums=` then the server tries to enum-validate against the net/url decoded value `[]string{""}`.

This PR attempts to fix this by making array decoder not call the child decoder for `[]string{""}`.

Seems to me like the spec doesn't clearly state about this empty array case:
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#style-examples

found a stackoverflow question without answer:
https://stackoverflow.com/questions/74589019/openapi-empty-array-object-query-parameter-serializing

Unless I'm missing something, the framework needs decide what to do with valueless array parameter.

<img width="424" alt="image" src="https://github.com/ogen-go/ogen/assets/1630378/e49e901d-94b1-42b0-9596-1ddc4497ec27">



Patch:
diff --git a/uri/query_param_decoder.go b/uri/query_param_decoder.go
index 654c64b8..3b487bc7 100644
--- a/uri/query_param_decoder.go
+++ b/uri/query_param_decoder.go
@@ -59,6 +59,11 @@ func (d *queryParamDecoder) DecodeArray(f func(d Decoder) error) error {
 			return errors.New("invalid value")
 		}
 
+		// do not decode `?param=` as `[""]` and leave the parameter as whatever zero value it has
+		if values[0] == "" {
+			return nil
+		}
+
 		for _, item := range strings.Split(values[0], ",") {
 			if err := f(&constval{item}); err != nil {
 				return err


Test patch:
diff --git a/uri/query_param_decoder_test.go b/uri/query_param_decoder_test.go
index a3f5d70b..a9e20c36 100644
--- a/uri/query_param_decoder_test.go
+++ b/uri/query_param_decoder_test.go
@@ -70,6 +70,20 @@ func TestQueryParamDecoder(t *testing.T) {
 				Style:   QueryStyleForm,
 				Explode: false,
 			},
+			{
+				Param:   "id",
+				Input:   "id=",
+				Expect:  []string{""},
+				Style:   QueryStyleForm,
+				Explode: true,
+			},
+			{
+				Param:   "id",
+				Input:   "id=",
+				Expect:  []string(nil),
+				Style:   QueryStyleForm,
+				Explode: false,
+			},
 			{
 				Param:   "id",
 				Input:   "id=3&id=4&id=5",
diff --git a/uri/query_param_encoder_test.go b/uri/query_param_encoder_test.go
index 985a642a..915e131d 100644
--- a/uri/query_param_encoder_test.go
+++ b/uri/query_param_encoder_test.go
@@ -69,6 +69,20 @@ func TestQueryParamEncoder(t *testing.T) {
 				Style:   QueryStyleForm,
 				Explode: false,
 			},
+			{
+				Param:   "id",
+				Input:   []string{},
+				Expect:  "",
+				Style:   QueryStyleForm,
+				Explode: true,
+			},
+			{
+				Param:   "id",
+				Input:   []string{},
+				Expect:  "id=",
+				Style:   QueryStyleForm,
+				Explode: false,
+			},
 			{
 				Param:   "id",
 				Input:   []string{"3", "4", "5"},
Repository: ogen-go/ogen
Pull request #1016 (2023-08-29 00:51:38)

fix: linter memory aliasing issue


Patch:
diff --git a/gen/generator.go b/gen/generator.go
index 44bfb832..1a333ad5 100644
--- a/gen/generator.go
+++ b/gen/generator.go
@@ -219,7 +219,7 @@ func (g *Generator) makeWebhooks(webhooks []openapi.Webhook) error {
 				continue
 			}
 
-			xslices.Filter(&spec.Parameters, func(p *openapi.Parameter) bool {
+			spec.Parameters = xslices.Filter(spec.Parameters, func(p *openapi.Parameter) bool {
 				if p.In.Path() {
 					log.Warn("Webhooks can't have path parameters",
 						zap.String("name", p.Name),
diff --git a/gen/schema_gen_sum.go b/gen/schema_gen_sum.go
index 94272726..440ef50b 100644
--- a/gen/schema_gen_sum.go
+++ b/gen/schema_gen_sum.go
@@ -283,7 +283,7 @@ func (g *schemaGen) oneOf(name string, schema *jsonschema.Schema, side bool) (*i
 					})
 
 					// Filter discriminator field in-place.
-					xslices.Filter(&s.Fields, func(f *ir.Field) bool {
+					s.Fields = xslices.Filter(s.Fields, func(f *ir.Field) bool {
 						return f.Tag.JSON != propName
 					})
 
diff --git a/internal/xslices/xslices.go b/internal/xslices/xslices.go
index d0aecc2c..fcc5e03c 100644
--- a/internal/xslices/xslices.go
+++ b/internal/xslices/xslices.go
@@ -4,18 +4,16 @@ package xslices
 import "golang.org/x/exp/slices"
 
 // Filter performs in-place filtering of a slice.
-func Filter[S ~[]E, E any](sptr *S, keep func(E) bool) {
-	var (
-		n int
-		s = *sptr
-	)
+func Filter[S ~[]E, E any](s S, keep func(E) bool) S {
+	var n int
 	for _, v := range s {
 		if keep(v) {
 			s[n] = v
 			n++
 		}
 	}
-	*sptr = s[:n]
+	s = s[:n]
+	return s
 }
 
 // FindFunc returns the first element satisfying the predicate.
diff --git a/jsonschema/parser_enum.go b/jsonschema/parser_enum.go
index bfa9a848..220c91dd 100644
--- a/jsonschema/parser_enum.go
+++ b/jsonschema/parser_enum.go
@@ -107,7 +107,7 @@ func handleNullableEnum(s *Schema) {
 	})
 	// Filter all `null`s.
 	if s.Nullable {
-		xslices.Filter(&s.Enum, func(v any) bool {
+		s.Enum = xslices.Filter(s.Enum, func(v any) bool {
 			return v != nil
 		})
 	}


Test patch:
diff --git a/internal/xslices/xslices_test.go b/internal/xslices/xslices_test.go
index 281d678f..d168529c 100644
--- a/internal/xslices/xslices_test.go
+++ b/internal/xslices/xslices_test.go
@@ -12,10 +12,7 @@ func TestFilter(t *testing.T) {
 	odd := func(x int) bool {
 		return x%2 == 1
 	}
-	filter := func(v []int, cb func(int) bool) []int {
-		Filter(&v, cb)
-		return v
-	}
+	filter := Filter[[]int]
 
 	a.Empty(filter([]int(nil), odd))
 	a.Empty(filter([]int{}, odd))
Repository: probe-rs/probe-rs
Pull request #2380 (2024-04-17 18:56:33)

smoke-tester: normalize chip name to lower case
Previously, esp32c6 and probably other prefix-named chips failed with something like the following:

```
./smoke_tester --dut-definitions duts
For tests, chip definition must be exact. Chip name ESP32C6 matches multiple chips:
        esp32c6_lp
        esp32c6
Error: Failed to parse definition 'duts/c6.toml'
```


Patch:
diff --git a/probe-rs/targets/esp32c6.yaml b/probe-rs/targets/esp32c6.yaml
index bc0d11ba..4c539b9d 100644
--- a/probe-rs/targets/esp32c6.yaml
+++ b/probe-rs/targets/esp32c6.yaml
@@ -34,12 +34,6 @@ variants:
           end: 0x4087FFFF
         cores:
           - main
-      - !Ram
-        range:
-          start: 0x50000000
-          end: 0x50003FFF
-        cores:
-          - main
     flash_algorithms:
       - esp32c6-flashloader
 flash_algorithms:


Test patch:
diff --git a/.github/workflows/smoketest.yml b/.github/workflows/smoketest.yml
index fec93f1e..64d0f9d5 100644
--- a/.github/workflows/smoketest.yml
+++ b/.github/workflows/smoketest.yml
@@ -22,18 +22,18 @@ jobs:
       - name: Install target for cross-compilation
         run: rustup target add aarch64-unknown-linux-gnu
 
-      - name: Install cross 
+      - name: Install cross
         uses: taiki-e/install-action@v2.32.17
         with:
           tool: cross
 
       - name: Cache Dependencies
         uses: Swatinem/rust-cache@v2.7.3
-      
+
       - name: Build smoke-tester
         run:
           cross build --release --target aarch64-unknown-linux-gnu -p smoke_tester
-      
+
       - uses: actions/upload-artifact@v4
         with:
           name: smoke_tester
diff --git a/smoke-tester/README.md b/smoke-tester/README.md
index 28b80dc2..a7a942fb 100644
--- a/smoke-tester/README.md
+++ b/smoke-tester/README.md
@@ -22,8 +22,7 @@ chip = "nrf51822_xxAB"
 
 probe_selector = "0d28:0204:9900360150494e4500492002000000600000000097969901"
 
-# Optional binary (ELF format), used to test flashing.
-# The path is relative to the .toml file.
+# Optional binary (ELF format), used to test flashing. Needs to be specified as an absolute path.
 flash_test_binary = "gpio_hal_blinky"
 ```
 
diff --git a/smoke-tester/src/dut_definition.rs b/smoke-tester/src/dut_definition.rs
index 318bdb1f..96d1ae45 100644
--- a/smoke-tester/src/dut_definition.rs
+++ b/smoke-tester/src/dut_definition.rs
@@ -190,7 +190,10 @@ impl DutDefinition {
 }
 
 fn lookup_unique_target(chip: &str) -> Result<Target> {
-    let targets = search_chips(chip)?;
+    let targets = search_chips(chip)?
+        .into_iter()
+        .map(|chip| chip.to_ascii_lowercase())
+        .collect::<Vec<_>>();
 
     ensure!(
         !targets.is_empty(),
@@ -199,7 +202,7 @@ fn lookup_unique_target(chip: &str) -> Result<Target> {
     );
 
     if targets.len() > 1 {
-        let target_string = String::from(chip).to_ascii_uppercase();
+        let target_string = chip.to_ascii_lowercase();
         if targets.contains(&target_string) {
             // Multiple chips returned, but one was an exact match so we're using it
             let target = get_target_by_name(target_string)?;
Repository: GoogleChrome/lighthouse
Pull request #9555 (2019-08-14 01:18:24)

report: add utm params to web.dev links


Patch:
diff --git a/lighthouse-core/report/html/renderer/dom.js b/lighthouse-core/report/html/renderer/dom.js
index 28de47bb2..4f7b0a94d 100644
--- a/lighthouse-core/report/html/renderer/dom.js
+++ b/lighthouse-core/report/html/renderer/dom.js
@@ -127,8 +127,8 @@ class DOM {
       // Otherwise, append any links found.
       const url = new URL(segment.linkHref);
 
-      const DEVELOPERS_GOOGLE_ORIGIN = 'https://developers.google.com';
-      if (url.origin === DEVELOPERS_GOOGLE_ORIGIN) {
+      const DOCS_ORIGINS = ['https://developers.google.com', 'https://web.dev'];
+      if (DOCS_ORIGINS.includes(url.origin)) {
         url.searchParams.set('utm_source', 'lighthouse');
         url.searchParams.set('utm_medium', this._lighthouseChannel);
       }


Test patch:
diff --git a/lighthouse-core/test/report/html/renderer/dom-test.js b/lighthouse-core/test/report/html/renderer/dom-test.js
index 39a35b960..63fc457c3 100644
--- a/lighthouse-core/test/report/html/renderer/dom-test.js
+++ b/lighthouse-core/test/report/html/renderer/dom-test.js
@@ -127,7 +127,14 @@ describe('DOM', () => {
       assert.equal(result.innerHTML, '<a rel="noopener" target="_blank" href="https://developers.google.com/web/tools/lighthouse/audits/description?utm_source=lighthouse&amp;utm_medium=someChannel">Learn more</a>.');
     });
 
-    it('doesn\'t append utm params to non https://developers.google.com origins', () => {
+    it('appends utm params to the URLs with https://web.dev origin', () => {
+      const text = '[Learn more](https://web.dev/tap-targets/).';
+
+      const result = dom.convertMarkdownLinkSnippets(text);
+      assert.equal(result.innerHTML, '<a rel="noopener" target="_blank" href="https://web.dev/tap-targets/?utm_source=lighthouse&amp;utm_medium=someChannel">Learn more</a>.');
+    });
+
+    it('doesn\'t append utm params to other (non-docs) origins', () => {
       const text = '[Learn more](https://example.com/info).';
 
       const result = dom.convertMarkdownLinkSnippets(text);