|  | // Copyright 2024 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package wrap | 
|  |  | 
|  | import ( | 
|  | "encoding/json" | 
|  | "fmt" | 
|  | "testing" | 
|  |  | 
|  | "github.com/google/go-cmp/cmp" | 
|  | "golang.org/x/oscar/internal/storage" | 
|  | ) | 
|  |  | 
|  | func TestWrapper(t *testing.T) { | 
|  | w := New("test-bot", "test") | 
|  | body := "this is a comment" | 
|  | metadata := &struct { | 
|  | Foo string | 
|  | Bar int | 
|  | }{ | 
|  | Foo: "foo", | 
|  | Bar: 123, | 
|  | } | 
|  |  | 
|  | for _, tc := range []struct { | 
|  | name     string | 
|  | body     string | 
|  | meta     any | 
|  | wantMeta json.RawMessage | 
|  | }{ | 
|  | { | 
|  | name:     "no_metadata", | 
|  | body:     body, | 
|  | meta:     nil, | 
|  | wantMeta: nil, | 
|  | }, | 
|  | { | 
|  | name:     "metadata", | 
|  | body:     body, | 
|  | meta:     metadata, | 
|  | wantMeta: storage.JSON(metadata), | 
|  | }, | 
|  | } { | 
|  | t.Run(tc.name, func(t *testing.T) { | 
|  | wrapped, err := w.Wrap(tc.body, tc.meta) | 
|  | if err != nil { | 
|  | t.Fatal(err) | 
|  | } | 
|  | wrappedEdit := "something" + wrapped + "something else" | 
|  |  | 
|  | t.Run("IsWrapped", func(t *testing.T) { | 
|  | if !Is(wrapped) { | 
|  | t.Errorf("IsWrapped(%s, nil) = false, want true", wrapped) | 
|  | } | 
|  |  | 
|  | // IsWrapped expects an an exact match. | 
|  | if Is(wrappedEdit) { | 
|  | t.Errorf("IsWrapped(%s) = true, want false", wrappedEdit) | 
|  | } | 
|  | }) | 
|  |  | 
|  | t.Run("ContainsWrapped", func(t *testing.T) { | 
|  | if !Contains(wrapped) { | 
|  | t.Errorf("ContainsWrapped(%s, nil) = false, want true", wrapped) | 
|  | } | 
|  |  | 
|  | if !Contains(wrappedEdit) { | 
|  | t.Errorf("ContainsWrapped(%s) = false, want true", wrappedEdit) | 
|  | } | 
|  | }) | 
|  |  | 
|  | t.Run("Parse", func(t *testing.T) { | 
|  | got := Parse(wrapped) | 
|  | if got == nil { | 
|  | t.Fatalf("Parse(%s) = nil, want non-nil", wrapped) | 
|  | } | 
|  | if got.Body != body { | 
|  | t.Errorf("Parse(%s).Body = %q, want %q", wrapped, got.Body, body) | 
|  | } | 
|  | if string(got.Meta) != string(tc.wantMeta) { | 
|  | t.Errorf("Parse(%s).Metadata = %q, want %s", wrapped, got.Meta, tc.wantMeta) | 
|  | } | 
|  | }) | 
|  |  | 
|  | t.Run("ParseAll", func(t *testing.T) { | 
|  | wrappedMultiple := "something" + wrapped + "something else" + wrapped | 
|  | got := ParseAll(wrappedMultiple) | 
|  | want := []*Unwrapped{ | 
|  | { | 
|  | TagContent: TagContent{ | 
|  | Bot:  "test-bot", | 
|  | Kind: "test", | 
|  | Meta: tc.wantMeta, | 
|  | }, | 
|  | Body: body, | 
|  | }, | 
|  | { | 
|  | TagContent: TagContent{ | 
|  | Bot:  "test-bot", | 
|  | Kind: "test", | 
|  | Meta: tc.wantMeta, | 
|  | }, | 
|  | Body: body, | 
|  | }, | 
|  | } | 
|  | if diff := cmp.Diff(want, got); diff != "" { | 
|  | t.Errorf("ParseAll(%s) mismatch (-want +got):\n%s", wrappedMultiple, diff) | 
|  | } | 
|  | }) | 
|  |  | 
|  | t.Run("Strip", func(t *testing.T) { | 
|  | wrappedMultiple := "something" + wrapped + " something else" + wrapped | 
|  | want := "something something else" | 
|  | got := Strip(wrappedMultiple) | 
|  | if got != want { | 
|  | t.Errorf("Strip(%s) = %v, want %v", wrappedMultiple, got, want) | 
|  | } | 
|  | }) | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestWrapperError(t *testing.T) { | 
|  | w := New("test-bot", "test") | 
|  |  | 
|  | wrapped, err := w.Wrap("body <!-- oscar-end --> something", nil) | 
|  | if err == nil { | 
|  | t.Errorf("w.Wrap() = (%s, nil), want error", wrapped) | 
|  | } | 
|  |  | 
|  | inner, err := w.Wrap("body", nil) | 
|  | if err != nil { | 
|  | t.Fatal(err) | 
|  | } | 
|  |  | 
|  | // Can't double-wrap. | 
|  | double, err := w.Wrap(inner, nil) | 
|  | if err == nil { | 
|  | t.Errorf("w.Wrap() = (%s, nil), want error", double) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestWrapperLiteral(t *testing.T) { | 
|  | // Full text by Oscar. | 
|  | comment := | 
|  | `<!-- Generated by Oscar. DO NOT EDIT. {"bot":"test-bot","kind":"test","meta":{"Foo":"foo","Bar":123}} -->this is a comment | 
|  | with multiple lines <!-- and an HTML comment --><!-- oscar-end -->` | 
|  |  | 
|  | t.Run("IsWrapped", func(t *testing.T) { | 
|  | if !Is(comment) { | 
|  | t.Errorf("IsWrapped(%s) = false, want true", comment) | 
|  | } | 
|  | }) | 
|  |  | 
|  | t.Run("ContainsWrapped", func(t *testing.T) { | 
|  | edit := `hello` + comment + `some more stuff` | 
|  | if !Contains(edit) { | 
|  | t.Errorf("ContainsWrapped(%s) = false, want true", edit) | 
|  | } | 
|  | }) | 
|  |  | 
|  | t.Run("Parse", func(t *testing.T) { | 
|  | got := Parse(comment) | 
|  | if got == nil { | 
|  | t.Fatalf("Parse(%s) = nil, want non-nil", comment) | 
|  | } | 
|  | want := &Unwrapped{ | 
|  | TagContent: TagContent{ | 
|  | Bot:  "test-bot", | 
|  | Kind: "test", | 
|  | Meta: json.RawMessage(`{"Foo":"foo","Bar":123}`), | 
|  | }, | 
|  | Body: `this is a comment | 
|  | with multiple lines <!-- and an HTML comment -->`, | 
|  | } | 
|  | if !cmp.Equal(got, want) { | 
|  | t.Errorf("Parse(%s) = %+v, want %+v", comment, got, want) | 
|  | } | 
|  | }) | 
|  |  | 
|  | // Text with multiple edits by Oscar (with different bots and kinds). | 
|  | edited := `a user comment<!-- Generated by Oscar. DO NOT EDIT. {"bot":"test-bot","kind":"test","meta":{"Object:":{"Foo":"foo","Bar":123}}} -->this is a comment<!-- oscar-end --> | 
|  | more user comment<!-- Generated by Oscar. DO NOT EDIT. {"bot":"test-bot2","kind":"test2","meta":{"Text":"hello"}} -->this is another comment<!-- oscar-end -->` | 
|  | t.Run("ParseAll", func(t *testing.T) { | 
|  | got := ParseAll(edited) | 
|  | want := []*Unwrapped{ | 
|  | { | 
|  | TagContent: TagContent{ | 
|  | Bot:  "test-bot", | 
|  | Kind: "test", | 
|  | Meta: json.RawMessage(`{"Object:":{"Foo":"foo","Bar":123}}`), | 
|  | }, | 
|  | Body: `this is a comment`, | 
|  | }, | 
|  | { | 
|  | TagContent: TagContent{ | 
|  | Bot:  "test-bot2", | 
|  | Kind: "test2", | 
|  | Meta: json.RawMessage(`{"Text":"hello"}`), | 
|  | }, | 
|  | Body: `this is another comment`, | 
|  | }, | 
|  | } | 
|  | if diff := cmp.Diff(want, got); diff != "" { | 
|  | t.Errorf("ParseAll(%s) mismatch (-want +got):\n%s", comment, diff) | 
|  | } | 
|  | }) | 
|  |  | 
|  | t.Run("Strip", func(t *testing.T) { | 
|  | got := Strip(edited) | 
|  | want := `a user comment | 
|  | more user comment` | 
|  | if got != want { | 
|  | t.Errorf("Strip(%s) = %s, want %s", edited, got, want) | 
|  | } | 
|  | }) | 
|  | } | 
|  |  | 
|  | func ExampleWrapper() { | 
|  | w := New("test-bot", "test") | 
|  | metadata := &struct { | 
|  | Foo string | 
|  | Bar int | 
|  | }{ | 
|  | Foo: "foo", | 
|  | Bar: 123, | 
|  | } | 
|  |  | 
|  | wrapped, err := w.Wrap("this is a comment", metadata) | 
|  | if err != nil { | 
|  | fmt.Println("Wrap:", err) | 
|  | return | 
|  | } | 
|  | fmt.Println("Wrap:", wrapped) | 
|  |  | 
|  | isWrapped := Is(wrapped) | 
|  | fmt.Println("IsWrapped:", isWrapped) | 
|  |  | 
|  | u := Parse(wrapped) | 
|  | fmt.Printf("Parse: (bot=%s, kind=%s, meta=%s, body=%s)\n", u.Bot, u.Kind, u.Meta, u.Body) | 
|  |  | 
|  | // Output: | 
|  | // Wrap: <!-- Generated by Oscar. DO NOT EDIT. {"bot":"test-bot","kind":"test","meta":{"Foo":"foo","Bar":123}} -->this is a comment<!-- oscar-end --> | 
|  | // IsWrapped: true | 
|  | // Parse: (bot=test-bot, kind=test, meta={"Foo":"foo","Bar":123}, body=this is a comment) | 
|  | } |