notice

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 16, 2025 License: MIT Imports: 5 Imported by: 2

README

Notice Package

The notice package offers a suite of utilities for crafting clear, structured assertion messages. It simplifies the creation of readable error messages, featuring a header and contextual rows. With a fluent interface, it enables seamless message construction and includes helper functions for formatting and unwrapping errors.

Basic Usage

Create a Message
msg := notice.New("expected values to be equal").
    Want("%s", "abc").
    Have("%s", "xyz")

fmt.Println(msg)
// Output:
// expected values to be equal:
//   want: abc
//   have: xyz
Wrap Errors
ErrMy := errors.New("my error")

msg := notice.New("expected values to be equal").
    Want("%s", "abc").
    Have("%s", "xyz").
    Wrap(ErrMy)

is := errors.Is(msg, ErrMy)
fmt.Println(is)
// Output: true
Add Metadata
msg := notice.New("expected values to be equal").
    Want("%s", "abc").
    Have("%s", "xyz").
    SetData("key", 123)

fmt.Println(msg.GetData("key"))
// Output: value true
}

For more examples see examples_test.go file.

Indenting Lines

lines := notice.Indent(4, ' ', "line1\nline2\nline3")

fmt.Println(lines)
// Output:
//     line1
//     line2
//     line3

Documentation

Overview

Package notice simplifies building structured assertion messages.

Index

Examples

Constants

View Source
const ContinuationHeader = " ---"

ContinuationHeader is a special [Notice.Header] separating notices with the same header.

Example:

header:
  want: want 0
  have: have 0
 ---
  want: want 1
  have: have 1

Variables

View Source
var ErrNotice = errors.New("notice error")

ErrNotice is sentinel error which is automatically wrapped by all instances of Notice unless changed with Notice.Wrap method.

Functions

func Indent

func Indent(n int, r rune, lns string) string

Indent indents lines with n number of runes. Lines are indented only if there are more than one line.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	lines := notice.Indent(4, ' ', "line1\nline2\nline3")

	fmt.Println(lines)
}
Output:

    line1
    line2
    line3

func Join added in v0.6.0

func Join(err ...error) error

Join wraps errors in an instance of multi decorator if it's an error joined with errors.Join.

func Unwrap

func Unwrap(err error) []error

Unwrap unwraps joined errors. Returns nil if err is nil, unwraps only non-nil errors.

Types

type Notice

type Notice struct {
	Header string         // Header message.
	Rows   []Row          // Context rows.
	Data   map[string]any // Any useful data attached to the Notice.
	// contains filtered or unexported fields
}

Notice represents structured notice message consisting of a header and multiple named rows giving context to it.

nolint: errname

func From

func From(err error, prefix ...string) *Notice

From returns instance of Notice if it is in err's tree. If prefix is not empty header will be prefixed with the first element in the slice. If err is not instance of Notice it will create a new one and wrap err.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	var err error
	err = notice.New("expected values to be equal").
		Want("%s", "abc").
		Have("%s", "xyz")

	msg := notice.From(err, "optional prefix").
		Append("my", "%s", "value")

	fmt.Println(msg)
}
Output:

[optional prefix] expected values to be equal:
  want: abc
  have: xyz
    my: value

func New

func New(header string, args ...any) *Notice

New creates a new Notice with the specified header which is constructed using fmt.Sprintf from format and args. By default, the base error is set to ErrNotice.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected values to be equal").
		Want("%s", "abc").
		Have("%s", "xyz")

	fmt.Println(msg)
}
Output:

expected values to be equal:
  want: abc
  have: xyz
Example (FormatedHeader)
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected %s to be equal", "values").
		Want("%s", "abc").
		Have("%s", "xyz")

	fmt.Println(msg)
}
Output:

expected values to be equal:
  want: abc
  have: xyz

func (*Notice) Append

func (msg *Notice) Append(name, format string, args ...any) *Notice

Append appends a new row with the specified name and value build using fmt.Sprintf from format and args. If a row with the same name already exists, it is moved to the end of the [Notice.Order] slice. Implements fluent interface.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected values to be equal").
		Want("%s", "abc").
		Have("%s", "xyz").
		Append("name", "%d", 5)

	fmt.Println(msg)
}
Output:

expected values to be equal:
  want: abc
  have: xyz
  name: 5
Example (ForceNexLine)
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected values to be equal").
		Want("%s", "abc").
		Have("\n%s", "xyz").
		Append("name", "%d", 5)

	fmt.Println(msg)
}
Output:

expected values to be equal:
  want: abc
  have:
        xyz
  name: 5
Example (MultiLine)
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected values to be equal").
		Want("%s", "abc").
		Have("%s", "x\ny\nz").
		Append("name", "%d", 5)

	fmt.Println(msg)
}
Output:

expected values to be equal:
  want: abc
  have:
        x
        y
        z
  name: 5

func (*Notice) AppendRow

func (msg *Notice) AppendRow(desc ...Row) *Notice

AppendRow appends description rows to the message.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	row0 := notice.NewRow("number", "%d", 5)
	row1 := notice.NewRow("string", "%s", "abc")

	msg := notice.New("expected values to be equal").
		Want("%s", "abc").
		Have("%s", "xyz").
		AppendRow(row0, row1)

	fmt.Println(msg)
}
Output:

expected values to be equal:
    want: abc
    have: xyz
  number: 5
  string: abc

func (*Notice) Error

func (msg *Notice) Error() string

Notice returns a formatted string representation of the Notice.

func (*Notice) GetData added in v0.6.0

func (msg *Notice) GetData(key string) (any, bool)

GetData returns data set by Notice.SetData. Returns nil and false if the key was never set.

func (*Notice) Have

func (msg *Notice) Have(format string, args ...any) *Notice

Have uses Append method to append a row with "have" name. If the "have" row already exists it will just replace its value.

func (*Notice) Is

func (msg *Notice) Is(target error) bool

func (*Notice) Prepend

func (msg *Notice) Prepend(name, format string, args ...any) *Notice

Prepend prepends a new row with the specified name and value built using fmt.Sprintf from format and args. If a row with the same name already exists, it is moved to the beginning of the [Notice.Order] slice. Implements fluent interface.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected values to be equal").
		Trail("type.field").
		Want("%s", "abc").
		Have("%s", "xyz").
		Prepend("name", "%d", 5)

	fmt.Println(msg)
}
Output:

expected values to be equal:
  trail: type.field
   name: 5
   want: abc
   have: xyz

func (*Notice) Remove

func (msg *Notice) Remove(name string) *Notice

Remove removes named row.

func (*Notice) SetData added in v0.6.0

func (msg *Notice) SetData(key string, val any) *Notice

SetData sets data. To get it back use Notice.GetData method.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected values to be equal").
		Want("%s", "abc").
		Have("%s", "xyz").
		SetData("key", 123)

	fmt.Println(msg.GetData("key"))
}
Output:

123 true

func (*Notice) SetHeader

func (msg *Notice) SetHeader(header string, args ...any) *Notice

SetHeader sets the header message. Implements fluent interface.

Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected values to be equal").
		Want("%s", "abc").
		Have("%s", "xyz")

	_ = msg.SetHeader("some other %s", "header")

	fmt.Println(msg)
}
Output:

some other header:
  want: abc
  have: xyz

func (*Notice) Trail

func (msg *Notice) Trail(tr string) *Notice

Trail adds trail row if "tr" is not empty string. If the trail row already exists it overwrites it. Implements fluent interface.

Trail examples:

  • Type
  • Type[1].Field
  • Type["key"].Field
Example
package main

import (
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	msg := notice.New("expected values to be equal").
		Trail("type.field").
		Want("%s", "abc").
		Have("%s", "xyz")

	fmt.Println(msg)
}
Output:

expected values to be equal:
  trail: type.field
   want: abc
   have: xyz

func (*Notice) Unwrap added in v0.6.0

func (msg *Notice) Unwrap() error

Unwrap returns wrapped error. By default, it returns ErrNotice unless a different error was specified using Notice.Wrap.

Example
package main

import (
	"errors"
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	ErrMy := errors.New("my error")

	msg := notice.New("expected values to be equal").
		Want("%s", "abc").
		Have("%s", "xyz").
		Wrap(ErrMy)

	fmt.Println(msg.Unwrap())
}
Output:

my error

func (*Notice) Want

func (msg *Notice) Want(format string, args ...any) *Notice

Want uses Append method to append a row with "want" name. If the "want" row already exists it will just replace its value.

func (*Notice) Wrap

func (msg *Notice) Wrap(err error) *Notice

Wrap sets base error with provided one.

Example
package main

import (
	"errors"
	"fmt"

	"github.com/ctx42/testing/pkg/notice"
)

func main() {
	ErrMy := errors.New("my error")

	msg := notice.New("expected values to be equal").
		Want("%s", "abc").
		Have("%s", "xyz").
		Wrap(ErrMy)

	is := errors.Is(msg, ErrMy)
	fmt.Println(is)
}
Output:

true

type Row

type Row struct {
	Name   string
	Format string
	Args   []any
}

Row represents Notice row.

func NewRow

func NewRow(name, format string, args ...any) Row

NewRow is constructor function for Row.

func (Row) PadName added in v0.6.0

func (r Row) PadName(length int) string

PadName left pads row name with spaces to be requested length.

func (Row) String added in v0.6.0

func (r Row) String() string

String returns formated string value.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL