You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
5.6KB

  1. package httptest
  2. import (
  3. "crypto/tls"
  4. "net/http"
  5. "net/http/httptest"
  6. "testing"
  7. "github.com/kataras/iris/v12"
  8. "github.com/kataras/iris/v12/context"
  9. "github.com/kataras/iris/v12/core/router"
  10. "github.com/kataras/iris/v12/i18n"
  11. "github.com/iris-contrib/httpexpect/v2"
  12. )
  13. type (
  14. // OptionSetter sets a configuration field to the configuration
  15. OptionSetter interface {
  16. // Set receives a pointer to the Configuration type and does the job of filling it
  17. Set(c *Configuration)
  18. }
  19. // OptionSet implements the OptionSetter
  20. OptionSet func(c *Configuration)
  21. )
  22. // Set is the func which makes the OptionSet an OptionSetter, this is used mostly
  23. func (o OptionSet) Set(c *Configuration) {
  24. o(c)
  25. }
  26. // Configuration httptest configuration
  27. type Configuration struct {
  28. // URL the base url.
  29. // Defaults to empty string "".
  30. URL string
  31. // Debug if true then debug messages from the httpexpect will be shown when a test runs
  32. // Defaults to false.
  33. Debug bool
  34. // LogLevel sets the application's log level.
  35. // Defaults to "disable" when testing.
  36. LogLevel string
  37. // If true then the underline httpexpect report will be acquired by the NewRequireReporter
  38. // call instead of the default NewAssertReporter.
  39. // Defaults to false.
  40. Strict bool // Note: if more reports are available in the future then add a Reporter interface as a field.
  41. }
  42. // Set implements the OptionSetter for the Configuration itself
  43. func (c Configuration) Set(main *Configuration) {
  44. main.URL = c.URL
  45. main.Debug = c.Debug
  46. if c.LogLevel != "" {
  47. main.LogLevel = c.LogLevel
  48. }
  49. main.Strict = c.Strict
  50. }
  51. var (
  52. // URL if set then it sets the httptest's BaseURL.
  53. // Defaults to empty string "".
  54. URL = func(schemeAndHost string) OptionSet {
  55. return func(c *Configuration) {
  56. c.URL = schemeAndHost
  57. }
  58. }
  59. // Debug if true then debug messages from the httpexpect will be shown when a test runs
  60. // Defaults to false.
  61. Debug = func(val bool) OptionSet {
  62. return func(c *Configuration) {
  63. c.Debug = val
  64. }
  65. }
  66. // LogLevel sets the application's log level.
  67. // Defaults to disabled when testing.
  68. LogLevel = func(level string) OptionSet {
  69. return func(c *Configuration) {
  70. c.LogLevel = level
  71. }
  72. }
  73. // Strict sets the Strict configuration field to "val".
  74. // Applies the NewRequireReporter instead of the default one.
  75. // Use this if you want the test to fail on first error, before all checks have been done.
  76. Strict = func(val bool) OptionSet {
  77. return func(c *Configuration) {
  78. c.Strict = val
  79. }
  80. }
  81. )
  82. // DefaultConfiguration returns the default configuration for the httptest.
  83. func DefaultConfiguration() *Configuration {
  84. return &Configuration{URL: "", Debug: false, LogLevel: "disable"}
  85. }
  86. // New Prepares and returns a new test framework based on the "app".
  87. // Usage:
  88. // httptest.New(t, app)
  89. // With options:
  90. // httptest.New(t, app, httptest.URL(...), httptest.Debug(true), httptest.LogLevel("debug"), httptest.Strict(true))
  91. //
  92. // Example at: https://github.com/kataras/iris/tree/master/_examples/testing/httptest.
  93. func New(t *testing.T, app *iris.Application, setters ...OptionSetter) *httpexpect.Expect {
  94. conf := DefaultConfiguration()
  95. for _, setter := range setters {
  96. setter.Set(conf)
  97. }
  98. // set the logger or disable it (default).
  99. app.Logger().SetLevel(conf.LogLevel)
  100. if err := app.Build(); err != nil {
  101. if conf.LogLevel != "disable" {
  102. app.Logger().Println(err.Error())
  103. return nil
  104. }
  105. }
  106. var reporter httpexpect.Reporter
  107. if conf.Strict {
  108. reporter = httpexpect.NewRequireReporter(t)
  109. } else {
  110. reporter = httpexpect.NewAssertReporter(t)
  111. }
  112. testConfiguration := httpexpect.Config{
  113. BaseURL: conf.URL,
  114. Client: &http.Client{
  115. Transport: httpexpect.NewBinder(app),
  116. Jar: httpexpect.NewJar(),
  117. },
  118. Reporter: reporter,
  119. }
  120. if conf.Debug {
  121. testConfiguration.Printers = []httpexpect.Printer{
  122. httpexpect.NewDebugPrinter(t, true),
  123. }
  124. }
  125. return httpexpect.WithConfig(testConfiguration)
  126. }
  127. // NewInsecure same as New but receives a single host instead of the whole framework.
  128. // Useful for testing running TLS servers.
  129. func NewInsecure(t *testing.T, setters ...OptionSetter) *httpexpect.Expect {
  130. conf := DefaultConfiguration()
  131. for _, setter := range setters {
  132. setter.Set(conf)
  133. }
  134. transport := &http.Transport{
  135. TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // lint:ignore
  136. }
  137. testConfiguration := httpexpect.Config{
  138. BaseURL: conf.URL,
  139. Client: &http.Client{
  140. Transport: transport,
  141. Jar: httpexpect.NewJar(),
  142. },
  143. Reporter: httpexpect.NewAssertReporter(t),
  144. }
  145. if conf.Debug {
  146. testConfiguration.Printers = []httpexpect.Printer{
  147. httpexpect.NewDebugPrinter(t, true),
  148. }
  149. }
  150. return httpexpect.WithConfig(testConfiguration)
  151. }
  152. // Aliases for "net/http/httptest" package. See `Do` package-level function.
  153. var (
  154. NewRecorder = httptest.NewRecorder
  155. NewRequest = httptest.NewRequest
  156. )
  157. // Do is a simple helper which can be used to test handlers individually
  158. // with the "net/http/httptest" package.
  159. // This package contains aliases for `NewRequest` and `NewRecorder` too.
  160. //
  161. // For a more efficient testing please use the `New` function instead.
  162. func Do(w http.ResponseWriter, r *http.Request, handler iris.Handler, irisConfigurators ...iris.Configurator) {
  163. app := new(iris.Application)
  164. app.I18n = i18n.New()
  165. app.Configure(iris.WithConfiguration(iris.DefaultConfiguration()), iris.WithLogLevel("disable"))
  166. app.Configure(irisConfigurators...)
  167. app.HTTPErrorHandler = router.NewDefaultHandler(app.ConfigurationReadOnly(), app.Logger())
  168. app.ContextPool = context.New(func() interface{} {
  169. return context.NewContext(app)
  170. })
  171. ctx := app.ContextPool.Acquire(w, r)
  172. handler(ctx)
  173. app.ContextPool.Release(ctx)
  174. }