<commit_before>package tonic_test

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"testing"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/loopfz/gadgeto/iffy"
	"github.com/loopfz/gadgeto/tonic"
)

var r http.Handler

func errorHook(c *gin.Context, e error) (int, interface{}) {

	if _, ok := e.(tonic.InputError); ok {
		return 400, e.Error()
	}
	return 500, e.Error()
}

func TestMain(m *testing.M) {

	tonic.SetErrorHook(errorHook)

	g := gin.Default()
	g.GET("/simple", tonic.Handler(simpleHandler, 200))
	g.GET("/error", tonic.Handler(errorHandler, 200))
	g.GET("/path/:param", tonic.Handler(pathHandler, 200))
	g.GET("/query", tonic.Handler(queryHandler, 200))
	g.POST("/body", tonic.Handler(bodyHandler, 200))

	r = g

	m.Run()
}

func TestSimple(t *testing.T) {

	tester := iffy.NewTester(t, r)

	tester.AddCall("simple", "GET", "/simple", "").Checkers(iffy.ExpectStatus(200))
	tester.AddCall("simple", "GET", "/simple/", "").Checkers(iffy.ExpectStatus(301))
	tester.AddCall("simple", "GET", "/simple?", "").Checkers(iffy.ExpectStatus(200))
	tester.AddCall("simple", "GET", "/simple", "{}").Checkers(iffy.ExpectStatus(200))
	tester.AddCall("simple", "GET", "/simple?param=useless", "{}").Checkers(iffy.ExpectStatus(200))

	tester.Run()
}

func TestError(t *testing.T) {

	tester := iffy.NewTester(t, r)

	tester.AddCall("error", "GET", "/error", "").Checkers(iffy.ExpectStatus(500))

	tester.Run()
}

func TestPathQuery(t *testing.T) {

	tester := iffy.NewTester(t, r)

	tester.AddCall("path", "GET", "/path/foo", "").Checkers(iffy.ExpectStatus(200), expectString("param", "foo"))

	tester.AddCall("query", "GET", "/query?param=foo", "").Checkers(iffy.ExpectStatus(200), expectString("param", "foo"))
	tester.AddCall("query", "GET", "/query?param=foo&param=bar", "").Checkers(iffy.ExpectStatus(400))
	tester.AddCall("query", "GET", "/query?param=", "").Checkers(iffy.ExpectStatus(200))
	tester.AddCall("query", "GET", "/query", "").Checkers(iffy.ExpectStatus(400))
	tester.AddCall("query", "GET", "/query?param=foo&param-optional=bar", "").Checkers(iffy.ExpectStatus(200), expectString("param-optional", "bar"))
	tester.AddCall("query", "GET", "/query?param=foo&param-int=42", "").Checkers(iffy.ExpectStatus(200), expectInt("param-int", 42))
	tester.AddCall("query", "GET", "/query?param=foo&params=foo&params=bar", "").Checkers(iffy.ExpectStatus(200), expectStringArr("params", "foo", "bar"))
	tester.AddCall("query", "GET", "/query?param=foo&param-bool=true", "").Checkers(iffy.ExpectStatus(200), expectBool("param-bool", true))
	tester.AddCall("query", "GET", "/query?param=foo&param-default=bla", "").Checkers(iffy.ExpectStatus(200), expectString("param-default", "bla"))
	tester.AddCall("query", "GET", "/query?param=foo", "").Checkers(iffy.ExpectStatus(200), expectString("param-default", "default"))
	tester.AddCall("query", "GET", "/query?param=foo&param-ptr=bar", "").Checkers(iffy.ExpectStatus(200), expectString("param-ptr", "bar"))

	now, _ := time.Time{}.Add(87 * time.Hour).MarshalText()

	tester.AddCall("query", "GET", fmt.Sprintf("/query?param=foo&param-complex=%s", now), "").Checkers(iffy.ExpectStatus(200), expectString("param-complex", string(now)))

	tester.Run()
}

func TestBody(t *testing.T) {

	tester := iffy.NewTester(t, r)

	tester.AddCall("body", "POST", "/body", `{"param": "foo"}`).Checkers(iffy.ExpectStatus(200), expectString("param", "foo"))
	tester.AddCall("body", "POST", "/body", `{}`).Checkers(iffy.ExpectStatus(400))
	tester.AddCall("body", "POST", "/body", `{"param": ""}`).Checkers(iffy.ExpectStatus(400))
	tester.AddCall("body", "POST", "/body", `{"param": "foo", "param-optional": "bar"}`).Checkers(iffy.ExpectStatus(200), expectString("param-optional", "bar"))

	tester.Run()
}

func errorHandler(c *gin.Context) error {
	return errors.New("error")
}

func simpleHandler(c *gin.Context) error {
	return nil
}

type pathIn struct {
	Param string `path:"param" json:"param"`
}

func pathHandler(c *gin.Context, in *pathIn) (*pathIn, error) {
	return in, nil
}

type queryIn struct {
	Param         string    `query:"param, required" json:"param"`
	ParamOptional string    `query:"param-optional" json:"param-optional"`
	Params        []string  `query:"params" json:"params"`
	ParamInt      int       `query:"param-int" json:"param-int"`
	ParamBool     bool      `query:"param-bool" json:"param-bool"`
	ParamDefault  string    `query:"param-default, default=default" json:"param-default"`
	ParamPtr      *string   `query:"param-ptr" json:"param-ptr"`
	ParamComplex  time.Time `query:"param-complex" json:"param-complex"`
}
<commit_msg>Tonic: test for scalar handler output<commit_after>package tonic_test

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"testing"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/loopfz/gadgeto/iffy"
	"github.com/loopfz/gadgeto/tonic"
)

var r http.Handler

func errorHook(c *gin.Context, e error) (int, interface{}) {

	if _, ok := e.(tonic.InputError); ok {
		return 400, e.Error()
	}
	return 500, e.Error()
}

func TestMain(m *testing.M) {

	tonic.SetErrorHook(errorHook)

	g := gin.Default()
	g.GET("/simple", tonic.Handler(simpleHandler, 200))
	g.GET("/scalar", tonic.Handler(scalarHandler, 200))
	g.GET("/error", tonic.Handler(errorHandler, 200))
	g.GET("/path/:param", tonic.Handler(pathHandler, 200))
	g.GET("/query", tonic.Handler(queryHandler, 200))
	g.POST("/body", tonic.Handler(bodyHandler, 200))

	r = g

	m.Run()
}

func TestSimple(t *testing.T) {

	tester := iffy.NewTester(t, r)

	tester.AddCall("simple", "GET", "/simple", "").Checkers(iffy.ExpectStatus(200))
	tester.AddCall("simple", "GET", "/simple/", "").Checkers(iffy.ExpectStatus(301))
	tester.AddCall("simple", "GET", "/simple?", "").Checkers(iffy.ExpectStatus(200))
	tester.AddCall("simple", "GET", "/simple", "{}").Checkers(iffy.ExpectStatus(200))
	tester.AddCall("simple", "GET", "/simple?param=useless", "{}").Checkers(iffy.ExpectStatus(200))

	tester.AddCall("scalar", "GET", "/scalar", "").Checkers(iffy.ExpectStatus(200))

	tester.Run()
}

func TestError(t *testing.T) {

	tester := iffy.NewTester(t, r)

	tester.AddCall("error", "GET", "/error", "").Checkers(iffy.ExpectStatus(500))

	tester.Run()
}

func TestPathQuery(t *testing.T) {

	tester := iffy.NewTester(t, r)

	tester.AddCall("path", "GET", "/path/foo", "").Checkers(iffy.ExpectStatus(200), expectString("param", "foo"))

	tester.AddCall("query", "GET", "/query?param=foo", "").Checkers(iffy.ExpectStatus(200), expectString("param", "foo"))
	tester.AddCall("query", "GET", "/query?param=foo&param=bar", "").Checkers(iffy.ExpectStatus(400))
	tester.AddCall("query", "GET", "/query?param=", "").Checkers(iffy.ExpectStatus(200))
	tester.AddCall("query", "GET", "/query", "").Checkers(iffy.ExpectStatus(400))
	tester.AddCall("query", "GET", "/query?param=foo&param-optional=bar", "").Checkers(iffy.ExpectStatus(200), expectString("param-optional", "bar"))
	tester.AddCall("query", "GET", "/query?param=foo&param-int=42", "").Checkers(iffy.ExpectStatus(200), expectInt("param-int", 42))
	tester.AddCall("query", "GET", "/query?param=foo&params=foo&params=bar", "").Checkers(iffy.ExpectStatus(200), expectStringArr("params", "foo", "bar"))
	tester.AddCall("query", "GET", "/query?param=foo&param-bool=true", "").Checkers(iffy.ExpectStatus(200), expectBool("param-bool", true))
	tester.AddCall("query", "GET", "/query?param=foo&param-default=bla", "").Checkers(iffy.ExpectStatus(200), expectString("param-default", "bla"))
	tester.AddCall("query", "GET", "/query?param=foo", "").Checkers(iffy.ExpectStatus(200), expectString("param-default", "default"))
	tester.AddCall("query", "GET", "/query?param=foo&param-ptr=bar", "").Checkers(iffy.ExpectStatus(200), expectString("param-ptr", "bar"))

	now, _ := time.Time{}.Add(87 * time.Hour).MarshalText()

	tester.AddCall("query", "GET", fmt.Sprintf("/query?param=foo&param-complex=%s", now), "").Checkers(iffy.ExpectStatus(200), expectString("param-complex", string(now)))

	tester.Run()
}

func TestBody(t *testing.T) {

	tester := iffy.NewTester(t, r)

	tester.AddCall("body", "POST", "/body", `{"param": "foo"}`).Checkers(iffy.ExpectStatus(200), expectString("param", "foo"))
	tester.AddCall("body", "POST", "/body", `{}`).Checkers(iffy.ExpectStatus(400))
	tester.AddCall("body", "POST", "/body", `{"param": ""}`).Checkers(iffy.ExpectStatus(400))
	tester.AddCall("body", "POST", "/body", `{"param": "foo", "param-optional": "bar"}`).Checkers(iffy.ExpectStatus(200), expectString("param-optional", "bar"))

	tester.Run()
}

func errorHandler(c *gin.Context) error {
	return errors.New("error")
}

func simpleHandler(c *gin.Context) error {
	return nil
}

func scalarHandler(c *gin.Context) (string, error) {
	return "", nil
}

type pathIn struct {
	Param string `path:"param" json:"param"`
}

func pathHandler(c *gin.Context, in *pathIn) (*pathIn, error) {
	return in, nil
}

type queryIn struct {
	Param         string    `query:"param, required" json:"param"`
	ParamOptional string    `query:"param-optional" json:"param-optional"`
	Params        []string  `query:"params" json:"params"`
	ParamInt      int       `query:"param-int" json:"param-int"`
	ParamBool     bool      `query:"param-bool" json:"param-bool"`
	ParamDefault  string    `query:"param-default, default=default" json:"param-default"`
	ParamPtr      *string   `query:"param-ptr" json:"param-ptr"`
	ParamComplex  time.Time `query:"param-complex" json:"param-complex"`
}

{'fraction_non_alphanumeric': 0.22079575596816975, 'fraction_numerical': 0.021007957559681698, 'mean_word_length': 6.044843049327354, 'pattern_counts': {'":': 8, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2182921', 'n_tokens_mistral': 3616, 'n_tokens_neox': 3423, 'n_words': 571}