diff --git a/assertions/assertions.go b/assertions/assertions.go index 7169007a..f4ed2fcf 100644 --- a/assertions/assertions.go +++ b/assertions/assertions.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cast" + "github.com/tj/go-naturaldate" ) type AssertFunc func(actual interface{}, expected ...interface{}) error @@ -954,7 +955,7 @@ func ShouldEqualTrimSpace(actual interface{}, expected ...interface{}) error { } // ShouldHappenBefore receives exactly 2 time.Time arguments and asserts that the first happens before the second. -// The arguments have to respect the date format RFC3339, as 2006-01-02T15:04:00+07:00 +// The arguments have to respect the date format RFC3339 (ie. 2006-01-02T15:04:00+07:00) or humanize format (ie. now, tomorrow, yesterday, 5 minutes ago) // // Example of testsuite file: // @@ -969,6 +970,13 @@ func ShouldEqualTrimSpace(actual interface{}, expected ...interface{}) error { // script: "echo {{.time}}" // assertions: // - result.systemout ShouldHappenBefore "{{.time_with_5s_after}}" +// - name: test assertion with humanize format +// steps: +// - type: exec +// script: "echo {{.venom.datetime}}" +// assertions: +// - "result.systemout ShouldHappenBefore tomorrow" +// - "result.systemout ShouldHappenBefore '5 minutes from now'" func ShouldHappenBefore(actual interface{}, expected ...interface{}) error { if err := need(1, expected); err != nil { return err @@ -991,7 +999,7 @@ func ShouldHappenBefore(actual interface{}, expected ...interface{}) error { } // ShouldHappenOnOrBefore receives exactly 2 time.Time arguments and asserts that the first happens on or before the second. -// The arguments have to respect the date format RFC3339, as 2006-01-02T15:04:00+07:00 +// The arguments have to respect the date format RFC3339 (ie. 2006-01-02T15:04:00+07:00) or humanize format (ie. now, tomorrow, yesterday, 5 minutes ago) // // Example of testsuite file: // @@ -1006,6 +1014,13 @@ func ShouldHappenBefore(actual interface{}, expected ...interface{}) error { // script: "echo {{.time}}" // assertions: // - result.systemout ShouldHappenOnOrBefore "{{.time_with_5s_after}}" +// - name: test assertion with humanize format +// steps: +// - type: exec +// script: "echo {{.venom.datetime}}" +// assertions: +// - "result.systemout ShouldHappenOnOrBefore tomorrow" +// - "result.systemout ShouldHappenOnOrBefore '5 minutes from now'" func ShouldHappenOnOrBefore(actual interface{}, expected ...interface{}) error { if err := need(1, expected); err != nil { return err @@ -1027,7 +1042,7 @@ func ShouldHappenOnOrBefore(actual interface{}, expected ...interface{}) error { } // ShouldHappenAfter receives exactly 2 time.Time arguments and asserts that the first happens after the second. -// The arguments have to respect the date format RFC3339, as 2006-01-02T15:04:00+07:00 +// The arguments have to respect the date format RFC3339 (ie. 2006-01-02T15:04:00+07:00) or humanize format (ie. now, tomorrow, yesterday, 5 minutes ago) // // Example of testsuite file: // @@ -1042,6 +1057,13 @@ func ShouldHappenOnOrBefore(actual interface{}, expected ...interface{}) error { // script: "echo {{.time}}" // assertions: // - result.systemout ShouldHappenAfter "{{.time_with_5s_before}}" +// - name: test assertion with humanize format +// steps: +// - type: exec +// script: "echo {{.venom.datetime}}" +// assertions: +// - "result.systemout ShouldHappenAfter yesterday" +// - "result.systemout ShouldHappenAfter '5 minutes ago'" func ShouldHappenAfter(actual interface{}, expected ...interface{}) error { if err := need(1, expected); err != nil { return err @@ -1063,7 +1085,7 @@ func ShouldHappenAfter(actual interface{}, expected ...interface{}) error { } // ShouldHappenOnOrAfter receives exactly 2 time.Time arguments and asserts that the first happens on or after the second. -// The arguments have to respect the date format RFC3339, as 2006-01-02T15:04:00+07:00 +// The arguments have to respect the date format RFC3339 (ie. 2006-01-02T15:04:00+07:00) or humanize format (ie. now, tomorrow, yesterday, 5 minutes ago) // // Example of testsuite file: // @@ -1078,6 +1100,13 @@ func ShouldHappenAfter(actual interface{}, expected ...interface{}) error { // script: "echo {{.time}}" // assertions: // - result.systemout ShouldHappenOnOrAfter "{{.time_with_5s_before}}" +// - name: test assertion with humanize format +// steps: +// - type: exec +// script: "echo {{.venom.datetime}}" +// assertions: +// - "result.systemout ShouldHappenOnOrAfter yesterday" +// - "result.systemout ShouldHappenOnOrAfter '5 minutes ago'" func ShouldHappenOnOrAfter(actual interface{}, expected ...interface{}) error { if err := need(1, expected); err != nil { return err @@ -1099,7 +1128,7 @@ func ShouldHappenOnOrAfter(actual interface{}, expected ...interface{}) error { } // ShouldHappenBetween receives exactly 3 time.Time arguments and asserts that the first happens between (not on) the second and third. -// The arguments have to respect the date format RFC3339, as 2006-01-02T15:04:00+07:00 +// The arguments have to respect the date format RFC3339 (ie. 2006-01-02T15:04:00+07:00) or humanize format (ie. yesterday, 5 minutes ago) // // Example of testsuite file: // @@ -1115,6 +1144,13 @@ func ShouldHappenOnOrAfter(actual interface{}, expected ...interface{}) error { // script: "echo {{.time}}" // assertions: // - result.systemout ShouldHappenBetween "{{.time_with_5s_before}}" "{{.time_with_5s_after}}" +// - name: test assertion with humanize format +// steps: +// - type: exec +// script: "echo {{.venom.datetime}}" +// assertions: +// - "result.systemout ShouldHappenBetween yesterday tomorrow" +// - "result.systemout ShouldHappenBetween '5 minutes ago' '5 minutes from now'" func ShouldHappenBetween(actual interface{}, expected ...interface{}) error { if err := need(2, expected); err != nil { return err @@ -1304,14 +1340,21 @@ func getTimeFromString(in interface{}) (time.Time, error) { if t, isTime := in.(time.Time); isTime { return t, nil } + s, err := cast.ToStringE(in) if err != nil { return time.Time{}, errors.Errorf("invalid date provided: %q", in) } t, err := time.Parse(time.RFC3339, s) - if err != nil { - return time.Time{}, errors.Errorf("invalid date RFC3339 provided with %q", in) + if err == nil { + return t, nil } + + t, innerErr := naturaldate.Parse(s, time.Now()) + if innerErr != nil { + return time.Time{}, errors.Errorf("invalid date provided with %q not in RFC3339 format or humanize format", in) + } + return t, nil } diff --git a/assertions/assertions_test.go b/assertions/assertions_test.go index 7cb4aab0..cdba9dd6 100644 --- a/assertions/assertions_test.go +++ b/assertions/assertions_test.go @@ -1183,6 +1183,13 @@ func TestShouldHappenBefore(t *testing.T) { expected: []interface{}{time.Now().Add(1 * time.Second)}, }, }, + { + name: "ok", + args: args{ + actual: time.Now(), + expected: []interface{}{"1 minute from now"}, + }, + }, { name: "ko", args: args{ @@ -1218,6 +1225,13 @@ func TestShouldHappenOnOrBefore(t *testing.T) { expected: []interface{}{time.Now().Add(1 * time.Second)}, }, }, + { + name: "ok", + args: args{ + actual: time.Now(), + expected: []interface{}{"1 minute from now"}, + }, + }, { name: "ko", args: args{ @@ -1253,6 +1267,13 @@ func TestShouldHappenAfter(t *testing.T) { expected: []interface{}{time.Now().Add(-1 * time.Second)}, }, }, + { + name: "ok", + args: args{ + actual: time.Now(), + expected: []interface{}{"1 second ago"}, + }, + }, { name: "ko", args: args{ @@ -1288,6 +1309,13 @@ func TestShouldHappenOnOrAfter(t *testing.T) { expected: []interface{}{time.Now().Add(-1 * time.Second)}, }, }, + { + name: "ok", + args: args{ + actual: time.Now(), + expected: []interface{}{"1 second ago"}, + }, + }, { name: "ko", args: args{ @@ -1346,6 +1374,13 @@ func TestShouldHappenBetween(t *testing.T) { }, wantErr: true, }, + { + name: "ok", + args: args{ + actual: time.Now(), + expected: []interface{}{"1 minute ago", "1 minute from now"}, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/go.mod b/go.mod index c960af7d..1ca3688e 100644 --- a/go.mod +++ b/go.mod @@ -88,6 +88,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/tj/go-naturaldate v1.3.0 github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect diff --git a/go.sum b/go.sum index 88a6b918..e3a8035e 100644 --- a/go.sum +++ b/go.sum @@ -549,6 +549,10 @@ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160 h1:NSWpaDaurcAJY7PkL8Xt0PhZE7qpvbZl5ljd8r6U0bI= +github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= +github.com/tj/go-naturaldate v1.3.0 h1:OgJIPkR/Jk4bFMBLbxZ8w+QUxwjqSvzd9x+yXocY4RI= +github.com/tj/go-naturaldate v1.3.0/go.mod h1:rpUbjivDKiS1BlfMGc2qUKNZ/yxgthOfmytQs8d8hKk= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= diff --git a/tests/assertions/ShouldHappenAfter.yml b/tests/assertions/ShouldHappenAfter.yml index 4b4f0886..4452da20 100644 --- a/tests/assertions/ShouldHappenAfter.yml +++ b/tests/assertions/ShouldHappenAfter.yml @@ -1,11 +1,18 @@ -name: test ShouldHappenAfter - use RFC3339 format +name: test ShouldHappenAfter vars: time_with_5s_before: 2006-01-02T15:04:00+07:00 time: 2006-01-02T15:04:05+07:00 testcases: -- name: test assertion +- name: test assertion with RFC3339 date format steps: - type: exec script: "echo {{.time}}" assertions: - - result.systemout ShouldHappenAfter "{{.time_with_5s_before}}" \ No newline at end of file + - result.systemout ShouldHappenAfter "{{.time_with_5s_before}}" +- name: test assertion with humanize format + steps: + - type: exec + script: "echo {{.venom.datetime}}" + assertions: + - "result.systemout ShouldHappenAfter yesterday" + - "result.systemout ShouldHappenAfter '5 minutes ago'" diff --git a/tests/assertions/ShouldHappenBefore.yml b/tests/assertions/ShouldHappenBefore.yml index 79cc3b6f..1f43399c 100644 --- a/tests/assertions/ShouldHappenBefore.yml +++ b/tests/assertions/ShouldHappenBefore.yml @@ -1,11 +1,18 @@ -name: test ShouldHappenBefore - use RFC3339 format +name: test ShouldHappenBefore vars: time: 2006-01-02T15:04:05+07:00 time_with_5s_after: 2006-01-02T15:04:10+07:00 testcases: -- name: test assertion +- name: test assertion with RFC3339 date format steps: - type: exec script: "echo {{.time}}" assertions: - - result.systemout ShouldHappenBefore "{{.time_with_5s_after}}" \ No newline at end of file + - result.systemout ShouldHappenBefore "{{.time_with_5s_after}}" +- name: test assertion with humanize format + steps: + - type: exec + script: "echo {{.venom.datetime}}" + assertions: + - "result.systemout ShouldHappenBefore tomorrow" + - "result.systemout ShouldHappenBefore '5 minutes from now'" diff --git a/tests/assertions/ShouldHappenBetween.yml b/tests/assertions/ShouldHappenBetween.yml index 98cec74b..4f2f225a 100644 --- a/tests/assertions/ShouldHappenBetween.yml +++ b/tests/assertions/ShouldHappenBetween.yml @@ -1,12 +1,19 @@ -name: test ShouldHappenBetween - use RFC3339 format +name: test ShouldHappenBetween vars: time_with_5s_before: 2006-01-02T15:04:00+07:00 time: 2006-01-02T15:04:05+07:00 time_with_5s_after: 2006-01-02T15:04:10+07:00 testcases: -- name: test assertion +- name: test assertion with RFC3339 date format steps: - type: exec script: "echo {{.time}}" assertions: - - result.systemout ShouldHappenBetween "{{.time_with_5s_before}}" "{{.time_with_5s_after}}" \ No newline at end of file + - result.systemout ShouldHappenBetween "{{.time_with_5s_before}}" "{{.time_with_5s_after}}" +- name: test assertion with humanize format + steps: + - type: exec + script: "echo {{.venom.datetime}}" + assertions: + - "result.systemout ShouldHappenBetween yesterday tomorrow" + - "result.systemout ShouldHappenBetween '5 minutes ago' '5 minutes from now'" diff --git a/tests/assertions/ShouldHappenOnOrAfter.yml b/tests/assertions/ShouldHappenOnOrAfter.yml index 461cf29f..14c009e9 100644 --- a/tests/assertions/ShouldHappenOnOrAfter.yml +++ b/tests/assertions/ShouldHappenOnOrAfter.yml @@ -1,11 +1,18 @@ -name: test ShouldHappenOnOrAfter - use RFC3339 format +name: test ShouldHappenOnOrAfter vars: time_with_5s_before: 2006-01-02T15:04:00+07:00 time: 2006-01-02T15:04:05+07:00 testcases: -- name: test assertion +- name: test assertion with RFC3339 date format steps: - type: exec script: "echo {{.time}}" assertions: - - result.systemout ShouldHappenOnOrAfter "{{.time_with_5s_before}}" \ No newline at end of file + - result.systemout ShouldHappenOnOrAfter "{{.time_with_5s_before}}" +- name: test assertion with humanize format + steps: + - type: exec + script: "echo {{.venom.datetime}}" + assertions: + - "result.systemout ShouldHappenOnOrAfter yesterday" + - "result.systemout ShouldHappenOnOrAfter '5 minutes ago'" diff --git a/tests/assertions/ShouldHappenOnOrBefore.yml b/tests/assertions/ShouldHappenOnOrBefore.yml index ca88b2f9..8b7169bf 100644 --- a/tests/assertions/ShouldHappenOnOrBefore.yml +++ b/tests/assertions/ShouldHappenOnOrBefore.yml @@ -1,11 +1,18 @@ -name: test ShouldHappenOnOrBefore - use RFC3339 format +name: test ShouldHappenOnOrBefore vars: time: 2006-01-02T15:04:05+07:00 time_with_5s_after: 2006-01-02T15:04:10+07:00 testcases: -- name: test assertion +- name: test assertion with RFC3339 date format steps: - type: exec script: "echo {{.time}}" assertions: - - result.systemout ShouldHappenOnOrBefore "{{.time_with_5s_after}}" \ No newline at end of file + - result.systemout ShouldHappenOnOrBefore "{{.time_with_5s_after}}" +- name: test assertion with humanize format + steps: + - type: exec + script: "echo {{.venom.datetime}}" + assertions: + - "result.systemout ShouldHappenOnOrBefore tomorrow" + - "result.systemout ShouldHappenOnOrBefore '5 minutes from now'"