pax_global_header00006660000000000000000000000064122730276330014517gustar00rootroot0000000000000052 comment=728b3f160cb397ba18120323ed26777ea872304e goconvey-1.5.0/000077500000000000000000000000001227302763300133535ustar00rootroot00000000000000goconvey-1.5.0/.gitignore000066400000000000000000000001111227302763300153340ustar00rootroot00000000000000.DS_Store examples/output.json webserver/webserver web/server/server goconvey-1.5.0/LICENSE.md000066400000000000000000000024211227302763300147560ustar00rootroot00000000000000Copyright (c) 2013 SmartyStreets, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. NOTE: Various optional and subordinate components carry their own licensing requirements and restrictions. Use of those components is subject to the terms and conditions outlined the respective license of each component. goconvey-1.5.0/README.md000066400000000000000000000067771227302763300146530ustar00rootroot00000000000000GoConvey is awesome Go testing [![GoDoc](https://godoc.org/github.com/smartystreets/goconvey?status.png)](http://godoc.org/github.com/smartystreets/goconvey) ============================== Welcome to GoConvey, a yummy Go testing tool for gophers. Works with `go test`. Use it in the terminal or browser according your viewing pleasure. **[View full feature tour.](http://goconvey.co)** **Features:** - Directly integrates with `go test` - Fully-automatic web UI (works with native Go tests, too) - Huge suite of regression tests - Shows test coverage (Go 1.2+) - Readable, colorized console output (understandable by any manager, IT or not) - Test code generator - Desktop notifications (optional) - Auto-test script automatically runs tests in the terminal - Immediately open problem lines in [Sublime Text](http://www.sublimetext.com) ([some assembly required](https://github.com/asuth/subl-handler)) **Menu:** - [Installation](#installation) - [Quick start](#quick-start) - [Documentation](#documentation) - [Screenshots](#screenshots) - [Contributors](#contributors-thanks) Installation ------------ $ go get -t github.com/smartystreets/goconvey The `-t` flag above ensures that all test dependencies for goconvey are downloaded. [Quick start](https://github.com/smartystreets/goconvey/wiki#get-going-in-25-seconds) ----------- Make a test, for example: ```go func TestSpec(t *testing.T) { var x int // Only pass t into top-level Convey calls Convey("Given some integer with a starting value", t, func() { x = 1 Convey("When the integer is incremented", func() { x++ Convey("The value should be greater by one", func() { So(x, ShouldEqual, 2) }) }) }) } ``` #### [In the browser](https://github.com/smartystreets/goconvey/wiki/Web-UI) Start up the GoConvey web server at your project's path: $ $GOPATH/bin/goconvey Then open your browser to: http://localhost:8080 There you have it. As long as GoConvey is running, test results will automatically update in your browser window. The design is responsive, so you can squish the browser real tight if you need to put it beside your code. The [web UI](https://github.com/smartystreets/goconvey/wiki/Web-UI) supports traditional Go tests, so use it even if you're not using GoConvey tests. #### [In the terminal](https://github.com/smartystreets/goconvey/wiki/Execution) Just do what you do best: $ go test Or if you want the output to include the story: $ go test -v [Documentation](https://github.com/smartystreets/goconvey/wiki) ----------- Check out the - [GoConvey wiki](https://github.com/smartystreets/goconvey/wiki), - [![GoDoc](https://godoc.org/github.com/smartystreets/goconvey?status.png)](http://godoc.org/github.com/smartystreets/goconvey) - and the *_test.go files scattered throughout this project. [Screenshots](http://goconvey.co) ----------- For web UI and terminal screenshots, check out [the full feature tour](http://goconvey.co). Contributions ------------- You can get started on the [guidelines page](https://github.com/smartystreets/goconvey/wiki/For-Contributors) found in our wiki. Contributors (Thanks!) ---------------------- We appreciate everyone's contributions to the project! Please see the [contributor graphs](https://github.com/smartystreets/goconvey/graphs/contributors) provided by GitHub for all the credits. GoConvey is brought to you by [SmartyStreets](https://github.com/smartystreets); in particular: - [Michael Whatcott](https://github.com/mdwhatcott) - [Matt Holt](https://github.com/mholt) goconvey-1.5.0/assertions/000077500000000000000000000000001227302763300155455ustar00rootroot00000000000000goconvey-1.5.0/assertions/collections.go000066400000000000000000000057411227302763300204210ustar00rootroot00000000000000package assertions import ( "fmt" "reflect" "github.com/jacobsa/oglematchers" ) // ShouldContain receives exactly two parameters. The first is a slice and the // second is a proposed member. Membership is determined using ShouldEqual. func ShouldContain(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } if matchError := oglematchers.Contains(expected[0]).Matches(actual); matchError != nil { typeName := reflect.TypeOf(actual) if fmt.Sprintf("%v", matchError) == "which is not a slice or array" { return fmt.Sprintf(shouldHaveBeenAValidCollection, typeName) } return fmt.Sprintf(shouldHaveContained, typeName, expected[0]) } return success } // ShouldNotContain receives exactly two parameters. The first is a slice and the // second is a proposed member. Membership is determinied using ShouldEqual. func ShouldNotContain(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } typeName := reflect.TypeOf(actual) if matchError := oglematchers.Contains(expected[0]).Matches(actual); matchError != nil { if fmt.Sprintf("%v", matchError) == "which is not a slice or array" { return fmt.Sprintf(shouldHaveBeenAValidCollection, typeName) } return success } return fmt.Sprintf(shouldNotHaveContained, typeName, expected[0]) } // ShouldBeIn receives at least 2 parameters. The first is a proposed member of the collection // that is passed in either as the second parameter, or of the collection that is comprised // of all the remaining parameters. This assertion ensures that the proposed member is in // the collection (using ShouldEqual). func ShouldBeIn(actual interface{}, expected ...interface{}) string { if fail := atLeast(1, expected); fail != success { return fail } if len(expected) == 1 { return shouldBeIn(actual, expected[0]) } return shouldBeIn(actual, expected) } func shouldBeIn(actual interface{}, expected interface{}) string { if matchError := oglematchers.Contains(actual).Matches(expected); matchError != nil { return fmt.Sprintf(shouldHaveBeenIn, actual, reflect.TypeOf(expected)) } return success } // ShouldNotBeIn receives at least 2 parameters. The first is a proposed member of the collection // that is passed in either as the second parameter, or of the collection that is comprised // of all the remaining parameters. This assertion ensures that the proposed member is NOT in // the collection (using ShouldEqual). func ShouldNotBeIn(actual interface{}, expected ...interface{}) string { if fail := atLeast(1, expected); fail != success { return fail } if len(expected) == 1 { return shouldNotBeIn(actual, expected[0]) } return shouldNotBeIn(actual, expected) } func shouldNotBeIn(actual interface{}, expected interface{}) string { if matchError := oglematchers.Contains(actual).Matches(expected); matchError == nil { return fmt.Sprintf(shouldNotHaveBeenIn, actual, reflect.TypeOf(expected)) } return success } goconvey-1.5.0/assertions/collections_test.go000066400000000000000000000044431227302763300214560ustar00rootroot00000000000000package assertions import "testing" func TestShouldContain(t *testing.T) { fail(t, so([]int{}, ShouldContain), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so([]int{}, ShouldContain, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") fail(t, so(Thing1{}, ShouldContain, 1), "You must provide a valid container (was assertions.Thing1)!") fail(t, so(nil, ShouldContain, 1), "You must provide a valid container (was )!") fail(t, so([]int{1}, ShouldContain, 2), "Expected the container ([]int) to contain: '2' (but it didn't)!") pass(t, so([]int{1}, ShouldContain, 1)) pass(t, so([]int{1, 2, 3}, ShouldContain, 2)) } func TestShouldNotContain(t *testing.T) { fail(t, so([]int{}, ShouldNotContain), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so([]int{}, ShouldNotContain, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") fail(t, so(Thing1{}, ShouldNotContain, 1), "You must provide a valid container (was assertions.Thing1)!") fail(t, so(nil, ShouldNotContain, 1), "You must provide a valid container (was )!") fail(t, so([]int{1}, ShouldNotContain, 1), "Expected the container ([]int) NOT to contain: '1' (but it did)!") fail(t, so([]int{1, 2, 3}, ShouldNotContain, 2), "Expected the container ([]int) NOT to contain: '2' (but it did)!") pass(t, so([]int{1}, ShouldNotContain, 2)) } func TestShouldBeIn(t *testing.T) { fail(t, so(4, ShouldBeIn), shouldHaveProvidedCollectionMembers) container := []int{1, 2, 3, 4} pass(t, so(4, ShouldBeIn, container)) pass(t, so(4, ShouldBeIn, 1, 2, 3, 4)) fail(t, so(4, ShouldBeIn, 1, 2, 3), "Expected '4' to be in the container ([]interface {}, but it wasn't)!") fail(t, so(4, ShouldBeIn, []int{1, 2, 3}), "Expected '4' to be in the container ([]int, but it wasn't)!") } func TestShouldNotBeIn(t *testing.T) { fail(t, so(4, ShouldNotBeIn), shouldHaveProvidedCollectionMembers) container := []int{1, 2, 3, 4} pass(t, so(42, ShouldNotBeIn, container)) pass(t, so(42, ShouldNotBeIn, 1, 2, 3, 4)) fail(t, so(2, ShouldNotBeIn, 1, 2, 3), "Expected '2' NOT to be in the container ([]interface {}, but it was)!") fail(t, so(2, ShouldNotBeIn, []int{1, 2, 3}), "Expected '2' NOT to be in the container ([]int, but it was)!") } goconvey-1.5.0/assertions/doc.go000066400000000000000000000002501227302763300166360ustar00rootroot00000000000000// Package assertions contains the implementations for all assertions which // are referenced in the convey package for use with the So(...) method. package assertions goconvey-1.5.0/assertions/equality.go000066400000000000000000000212341227302763300177330ustar00rootroot00000000000000package assertions import ( "errors" "fmt" "math" "reflect" "strings" "github.com/jacobsa/oglematchers" ) // default acceptable delta for ShouldAlmostEqual var defaultDelta = 0.0000000001 // ShouldEqual receives exactly two parameters and does an equality check. func ShouldEqual(actual interface{}, expected ...interface{}) string { if message := need(1, expected); message != success { return message } return shouldEqual(actual, expected[0]) } func shouldEqual(actual, expected interface{}) (message string) { defer func() { if r := recover(); r != nil { message = serializer.serialize(expected, actual, fmt.Sprintf(shouldHaveBeenEqual, expected, actual)) return } }() if matchError := oglematchers.Equals(expected).Matches(actual); matchError != nil { message = serializer.serialize(expected, actual, fmt.Sprintf(shouldHaveBeenEqual, expected, actual)) return } return success } // ShouldNotEqual receives exactly two parameters and does an inequality check. func ShouldNotEqual(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } else if ShouldEqual(actual, expected[0]) == success { return fmt.Sprintf(shouldNotHaveBeenEqual, actual, expected[0]) } return success } // ShouldAlmostEqual makes sure that two parameters are close enough to being equal. // The acceptable delta may be specified with a third argument, // or a very small default delta will be used. func ShouldAlmostEqual(actual interface{}, expected ...interface{}) string { actualFloat, expectedFloat, deltaFloat, err := cleanAlmostEqualInput(actual, expected...) if err != "" { return err } if math.Abs(actualFloat-expectedFloat) <= deltaFloat { return success } else { return fmt.Sprintf(shouldHaveBeenAlmostEqual, actualFloat, expectedFloat) } } // ShouldNotAlmostEqual is the inverse of ShouldAlmostEqual func ShouldNotAlmostEqual(actual interface{}, expected ...interface{}) string { actualFloat, expectedFloat, deltaFloat, err := cleanAlmostEqualInput(actual, expected...) if err != "" { return err } if math.Abs(actualFloat-expectedFloat) > deltaFloat { return success } else { return fmt.Sprintf(shouldHaveNotBeenAlmostEqual, actualFloat, expectedFloat) } } func cleanAlmostEqualInput(actual interface{}, expected ...interface{}) (float64, float64, float64, string) { deltaFloat := 0.0000000001 if len(expected) == 0 { return 0.0, 0.0, 0.0, "This assertion requires exactly one comparison value and an optional delta (you provided neither)" } else if len(expected) == 2 { delta, err := getFloat(expected[1]) if err != nil { return 0.0, 0.0, 0.0, "delta must be a numerical type" } deltaFloat = delta } else if len(expected) > 2 { return 0.0, 0.0, 0.0, "This assertion requires exactly one comparison value and an optional delta (you provided more values)" } actualFloat, err := getFloat(actual) if err != nil { return 0.0, 0.0, 0.0, err.Error() } expectedFloat, err := getFloat(expected[0]) if err != nil { return 0.0, 0.0, 0.0, err.Error() } return actualFloat, expectedFloat, deltaFloat, "" } // returns the float value of any real number, or error if it is not a numerical type func getFloat(num interface{}) (float64, error) { numValue := reflect.ValueOf(num) numKind := numValue.Kind() if numKind == reflect.Int || numKind == reflect.Int8 || numKind == reflect.Int16 || numKind == reflect.Int32 || numKind == reflect.Int64 { return float64(numValue.Int()), nil } else if numKind == reflect.Uint || numKind == reflect.Uint8 || numKind == reflect.Uint16 || numKind == reflect.Uint32 || numKind == reflect.Uint64 { return float64(numValue.Uint()), nil } else if numKind == reflect.Float32 || numKind == reflect.Float64 { return numValue.Float(), nil } else { return 0.0, errors.New("must be a numerical type, but was " + numKind.String()) } } // ShouldResemble receives exactly two parameters and does a deep equal check (see reflect.DeepEqual) func ShouldResemble(actual interface{}, expected ...interface{}) string { if message := need(1, expected); message != success { return message } if matchError := oglematchers.DeepEquals(expected[0]).Matches(actual); matchError != nil { return serializer.serialize(expected[0], actual, fmt.Sprintf(shouldHaveResembled, expected[0], actual)) } return success } // ShouldNotResemble receives exactly two parameters and does an inverse deep equal check (see reflect.DeepEqual) func ShouldNotResemble(actual interface{}, expected ...interface{}) string { if message := need(1, expected); message != success { return message } else if ShouldResemble(actual, expected[0]) == success { return fmt.Sprintf(shouldNotHaveResembled, actual, expected[0]) } return success } // ShouldPointTo receives exactly two parameters and checks to see that they point to the same address. func ShouldPointTo(actual interface{}, expected ...interface{}) string { if message := need(1, expected); message != success { return message } return shouldPointTo(actual, expected[0]) } func shouldPointTo(actual, expected interface{}) string { actualValue := reflect.ValueOf(actual) expectedValue := reflect.ValueOf(expected) if ShouldNotBeNil(actual) != success { return fmt.Sprintf(shouldHaveBeenNonNilPointer, "first", "nil") } else if ShouldNotBeNil(expected) != success { return fmt.Sprintf(shouldHaveBeenNonNilPointer, "second", "nil") } else if actualValue.Kind() != reflect.Ptr { return fmt.Sprintf(shouldHaveBeenNonNilPointer, "first", "not") } else if expectedValue.Kind() != reflect.Ptr { return fmt.Sprintf(shouldHaveBeenNonNilPointer, "second", "not") } else if ShouldEqual(actualValue.Pointer(), expectedValue.Pointer()) != success { actualAddress := reflect.ValueOf(actual).Pointer() expectedAddress := reflect.ValueOf(expected).Pointer() return serializer.serialize(expectedAddress, actualAddress, fmt.Sprintf(shouldHavePointedTo, actual, actualAddress, expected, expectedAddress)) } return success } // ShouldNotPointTo receives exactly two parameters and checks to see that they point to different addresess. func ShouldNotPointTo(actual interface{}, expected ...interface{}) string { if message := need(1, expected); message != success { return message } compare := ShouldPointTo(actual, expected[0]) if strings.HasPrefix(compare, shouldBePointers) { return compare } else if compare == success { return fmt.Sprintf(shouldNotHavePointedTo, actual, expected[0], reflect.ValueOf(actual).Pointer()) } return success } // ShouldBeNil receives a single parameter and ensures that it is nil. func ShouldBeNil(actual interface{}, expected ...interface{}) string { if fail := need(0, expected); fail != success { return fail } else if actual == nil { return success } else if interfaceHasNilValue(actual) { return success } return fmt.Sprintf(shouldHaveBeenNil, actual) } func interfaceHasNilValue(actual interface{}) bool { value := reflect.ValueOf(actual) kind := value.Kind() nilable := kind == reflect.Slice || kind == reflect.Chan || kind == reflect.Func || kind == reflect.Ptr || kind == reflect.Map // Careful: reflect.Value.IsNil() will panic unless it's an interface, chan, map, func, slice, or ptr // Reference: http://golang.org/pkg/reflect/#Value.IsNil return nilable && value.IsNil() } // ShouldNotBeNil receives a single parameter and ensures that it is not nil. func ShouldNotBeNil(actual interface{}, expected ...interface{}) string { if fail := need(0, expected); fail != success { return fail } else if ShouldBeNil(actual) == success { return fmt.Sprintf(shouldNotHaveBeenNil, actual) } return success } // ShouldBeTrue receives a single parameter and ensures that it is true. func ShouldBeTrue(actual interface{}, expected ...interface{}) string { if fail := need(0, expected); fail != success { return fail } else if actual != true { return fmt.Sprintf(shouldHaveBeenTrue, actual) } return success } // ShouldBeFalse receives a single parameter and ensures that it is false. func ShouldBeFalse(actual interface{}, expected ...interface{}) string { if fail := need(0, expected); fail != success { return fail } else if actual != false { return fmt.Sprintf(shouldHaveBeenFalse, actual) } return success } // ShouldBeZeroValue receives a single parameter and ensures that it is // the Go equivalent of the default value, or "zero" value. func ShouldBeZeroValue(actual interface{}, expected ...interface{}) string { if fail := need(0, expected); fail != success { return fail } zeroVal := reflect.Zero(reflect.TypeOf(actual)).Interface() if !reflect.DeepEqual(zeroVal, actual) { return serializer.serialize(zeroVal, actual, fmt.Sprintf(shouldHaveBeenZeroValue, actual)) } return success } goconvey-1.5.0/assertions/equality_test.go000066400000000000000000000262001227302763300207700ustar00rootroot00000000000000package assertions import ( "fmt" "reflect" "testing" ) func TestShouldEqual(t *testing.T) { serializer = newFakeSerializer() fail(t, so(1, ShouldEqual), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(1, ShouldEqual, 1, 2), "This assertion requires exactly 1 comparison values (you provided 2).") fail(t, so(1, ShouldEqual, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") pass(t, so(1, ShouldEqual, 1)) fail(t, so(1, ShouldEqual, 2), "2|1|Expected: '2' Actual: '1' (Should be equal)") pass(t, so(true, ShouldEqual, true)) fail(t, so(true, ShouldEqual, false), "false|true|Expected: 'false' Actual: 'true' (Should be equal)") pass(t, so("hi", ShouldEqual, "hi")) fail(t, so("hi", ShouldEqual, "bye"), "bye|hi|Expected: 'bye' Actual: 'hi' (Should be equal)") pass(t, so(42, ShouldEqual, uint(42))) fail(t, so(Thing1{"hi"}, ShouldEqual, Thing1{}), "{}|{hi}|Expected: '{}' Actual: '{hi}' (Should be equal)") fail(t, so(Thing1{"hi"}, ShouldEqual, Thing1{"hi"}), "{hi}|{hi}|Expected: '{hi}' Actual: '{hi}' (Should be equal)") fail(t, so(&Thing1{"hi"}, ShouldEqual, &Thing1{"hi"}), "&{hi}|&{hi}|Expected: '&{hi}' Actual: '&{hi}' (Should be equal)") fail(t, so(Thing1{}, ShouldEqual, Thing2{}), "{}|{}|Expected: '{}' Actual: '{}' (Should be equal)") } func TestShouldNotEqual(t *testing.T) { fail(t, so(1, ShouldNotEqual), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(1, ShouldNotEqual, 1, 2), "This assertion requires exactly 1 comparison values (you provided 2).") fail(t, so(1, ShouldNotEqual, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") pass(t, so(1, ShouldNotEqual, 2)) fail(t, so(1, ShouldNotEqual, 1), "Expected '1' to NOT equal '1' (but it did)!") pass(t, so(true, ShouldNotEqual, false)) fail(t, so(true, ShouldNotEqual, true), "Expected 'true' to NOT equal 'true' (but it did)!") pass(t, so("hi", ShouldNotEqual, "bye")) fail(t, so("hi", ShouldNotEqual, "hi"), "Expected 'hi' to NOT equal 'hi' (but it did)!") pass(t, so(&Thing1{"hi"}, ShouldNotEqual, &Thing1{"hi"})) pass(t, so(Thing1{"hi"}, ShouldNotEqual, Thing1{"hi"})) pass(t, so(Thing1{}, ShouldNotEqual, Thing1{})) pass(t, so(Thing1{}, ShouldNotEqual, Thing2{})) } func TestShouldAlmostEqual(t *testing.T) { fail(t, so(1, ShouldAlmostEqual), "This assertion requires exactly one comparison value and an optional delta (you provided neither)") fail(t, so(1, ShouldAlmostEqual, 1, 2, 3), "This assertion requires exactly one comparison value and an optional delta (you provided more values)") // with the default delta pass(t, so(1, ShouldAlmostEqual, .99999999999999)) pass(t, so(1.3612499999999996, ShouldAlmostEqual, 1.36125)) pass(t, so(0.7285312499999999, ShouldAlmostEqual, 0.72853125)) fail(t, so(1, ShouldAlmostEqual, .99), "Expected '1' to almost equal '0.99' (but it didn't)!") // with a different delta pass(t, so(100.0, ShouldAlmostEqual, 110.0, 10.0)) fail(t, so(100.0, ShouldAlmostEqual, 111.0, 10.5), "Expected '100' to almost equal '111' (but it didn't)!") // ints should work pass(t, so(100, ShouldAlmostEqual, 100.0)) fail(t, so(100, ShouldAlmostEqual, 99.0), "Expected '100' to almost equal '99' (but it didn't)!") // float32 should work pass(t, so(float64(100.0), ShouldAlmostEqual, float32(100.0))) fail(t, so(float32(100.0), ShouldAlmostEqual, 99.0, float32(0.1)), "Expected '100' to almost equal '99' (but it didn't)!") } func TestShouldNotAlmostEqual(t *testing.T) { fail(t, so(1, ShouldNotAlmostEqual), "This assertion requires exactly one comparison value and an optional delta (you provided neither)") fail(t, so(1, ShouldNotAlmostEqual, 1, 2, 3), "This assertion requires exactly one comparison value and an optional delta (you provided more values)") // with the default delta fail(t, so(1, ShouldNotAlmostEqual, .99999999999999), "Expected '1' to NOT almost equal '0.99999999999999' (but it did)!") fail(t, so(1.3612499999999996, ShouldNotAlmostEqual, 1.36125), "Expected '1.3612499999999996' to NOT almost equal '1.36125' (but it did)!") pass(t, so(1, ShouldNotAlmostEqual, .99)) // with a different delta fail(t, so(100.0, ShouldNotAlmostEqual, 110.0, 10.0), "Expected '100' to NOT almost equal '110' (but it did)!") pass(t, so(100.0, ShouldNotAlmostEqual, 111.0, 10.5)) // ints should work fail(t, so(100, ShouldNotAlmostEqual, 100.0), "Expected '100' to NOT almost equal '100' (but it did)!") pass(t, so(100, ShouldNotAlmostEqual, 99.0)) // float32 should work fail(t, so(float64(100.0), ShouldNotAlmostEqual, float32(100.0)), "Expected '100' to NOT almost equal '100' (but it did)!") pass(t, so(float32(100.0), ShouldNotAlmostEqual, 99.0, float32(0.1))) } func TestShouldResemble(t *testing.T) { serializer = newFakeSerializer() fail(t, so(Thing1{"hi"}, ShouldResemble), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(Thing1{"hi"}, ShouldResemble, Thing1{"hi"}, Thing1{"hi"}), "This assertion requires exactly 1 comparison values (you provided 2).") pass(t, so(Thing1{"hi"}, ShouldResemble, Thing1{"hi"})) fail(t, so(Thing1{"hi"}, ShouldResemble, Thing1{"bye"}), "{bye}|{hi}|Expected: '{bye}' Actual: '{hi}' (Should resemble)!") } func TestShouldNotResemble(t *testing.T) { fail(t, so(Thing1{"hi"}, ShouldNotResemble), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(Thing1{"hi"}, ShouldNotResemble, Thing1{"hi"}, Thing1{"hi"}), "This assertion requires exactly 1 comparison values (you provided 2).") pass(t, so(Thing1{"hi"}, ShouldNotResemble, Thing1{"bye"})) fail(t, so(Thing1{"hi"}, ShouldNotResemble, Thing1{"hi"}), "Expected '{hi}' to NOT resemble '{hi}' (but it did)!") } func TestShouldPointTo(t *testing.T) { serializer = newFakeSerializer() t1 := &Thing1{} t2 := t1 t3 := &Thing1{} pointer1 := reflect.ValueOf(t1).Pointer() pointer3 := reflect.ValueOf(t3).Pointer() fail(t, so(t1, ShouldPointTo), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(t1, ShouldPointTo, t2, t3), "This assertion requires exactly 1 comparison values (you provided 2).") pass(t, so(t1, ShouldPointTo, t2)) fail(t, so(t1, ShouldPointTo, t3), fmt.Sprintf( "%v|%v|Expected '&{}' (address: '%v') and '&{}' (address: '%v') to be the same address (but their weren't)!", pointer3, pointer1, pointer1, pointer3)) t4 := Thing1{} t5 := t4 fail(t, so(t4, ShouldPointTo, t5), "Both arguments should be pointers (the first was not)!") fail(t, so(&t4, ShouldPointTo, t5), "Both arguments should be pointers (the second was not)!") fail(t, so(nil, ShouldPointTo, nil), "Both arguments should be pointers (the first was nil)!") fail(t, so(&t4, ShouldPointTo, nil), "Both arguments should be pointers (the second was nil)!") } func TestShouldNotPointTo(t *testing.T) { t1 := &Thing1{} t2 := t1 t3 := &Thing1{} pointer1 := reflect.ValueOf(t1).Pointer() fail(t, so(t1, ShouldNotPointTo), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(t1, ShouldNotPointTo, t2, t3), "This assertion requires exactly 1 comparison values (you provided 2).") pass(t, so(t1, ShouldNotPointTo, t3)) fail(t, so(t1, ShouldNotPointTo, t2), fmt.Sprintf("Expected '&{}' and '&{}' to be different references (but they matched: '%v')!", pointer1)) t4 := Thing1{} t5 := t4 fail(t, so(t4, ShouldNotPointTo, t5), "Both arguments should be pointers (the first was not)!") fail(t, so(&t4, ShouldNotPointTo, t5), "Both arguments should be pointers (the second was not)!") fail(t, so(nil, ShouldNotPointTo, nil), "Both arguments should be pointers (the first was nil)!") fail(t, so(&t4, ShouldNotPointTo, nil), "Both arguments should be pointers (the second was nil)!") } func TestShouldBeNil(t *testing.T) { fail(t, so(nil, ShouldBeNil, nil, nil, nil), "This assertion requires exactly 0 comparison values (you provided 3).") fail(t, so(nil, ShouldBeNil, nil), "This assertion requires exactly 0 comparison values (you provided 1).") pass(t, so(nil, ShouldBeNil)) fail(t, so(1, ShouldBeNil), "Expected: nil Actual: '1'") var thing Thinger pass(t, so(thing, ShouldBeNil)) thing = &Thing{} fail(t, so(thing, ShouldBeNil), "Expected: nil Actual: '&{}'") var thingOne *Thing1 pass(t, so(thingOne, ShouldBeNil)) var nilSlice []int = nil pass(t, so(nilSlice, ShouldBeNil)) var nilMap map[string]string = nil pass(t, so(nilMap, ShouldBeNil)) var nilChannel chan int = nil pass(t, so(nilChannel, ShouldBeNil)) var nilFunc func() = nil pass(t, so(nilFunc, ShouldBeNil)) var nilInterface interface{} = nil pass(t, so(nilInterface, ShouldBeNil)) } func TestShouldNotBeNil(t *testing.T) { fail(t, so(nil, ShouldNotBeNil, nil, nil, nil), "This assertion requires exactly 0 comparison values (you provided 3).") fail(t, so(nil, ShouldNotBeNil, nil), "This assertion requires exactly 0 comparison values (you provided 1).") fail(t, so(nil, ShouldNotBeNil), "Expected '' to NOT be nil (but it was)!") pass(t, so(1, ShouldNotBeNil)) var thing Thinger fail(t, so(thing, ShouldNotBeNil), "Expected '' to NOT be nil (but it was)!") thing = &Thing{} pass(t, so(thing, ShouldNotBeNil)) } func TestShouldBeTrue(t *testing.T) { fail(t, so(true, ShouldBeTrue, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") fail(t, so(true, ShouldBeTrue, 1), "This assertion requires exactly 0 comparison values (you provided 1).") fail(t, so(false, ShouldBeTrue), "Expected: true Actual: false") fail(t, so(1, ShouldBeTrue), "Expected: true Actual: 1") pass(t, so(true, ShouldBeTrue)) } func TestShouldBeFalse(t *testing.T) { fail(t, so(false, ShouldBeFalse, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") fail(t, so(false, ShouldBeFalse, 1), "This assertion requires exactly 0 comparison values (you provided 1).") fail(t, so(true, ShouldBeFalse), "Expected: false Actual: true") fail(t, so(1, ShouldBeFalse), "Expected: false Actual: 1") pass(t, so(false, ShouldBeFalse)) } func TestShouldBeZeroValue(t *testing.T) { serializer = newFakeSerializer() fail(t, so(0, ShouldBeZeroValue, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") fail(t, so(false, ShouldBeZeroValue, true), "This assertion requires exactly 0 comparison values (you provided 1).") fail(t, so(1, ShouldBeZeroValue), "0|1|'1' should have been the zero value") //"Expected: (zero value) Actual: 1") fail(t, so(true, ShouldBeZeroValue), "false|true|'true' should have been the zero value") //"Expected: (zero value) Actual: true") fail(t, so("123", ShouldBeZeroValue), "|123|'123' should have been the zero value") //"Expected: (zero value) Actual: 123") fail(t, so(" ", ShouldBeZeroValue), "| |' ' should have been the zero value") //"Expected: (zero value) Actual: ") fail(t, so([]string{"Nonempty"}, ShouldBeZeroValue), "[]|[Nonempty]|'[Nonempty]' should have been the zero value") //"Expected: (zero value) Actual: [Nonempty]") pass(t, so(0, ShouldBeZeroValue)) pass(t, so(false, ShouldBeZeroValue)) pass(t, so("", ShouldBeZeroValue)) pass(t, so(struct{}{}, ShouldBeZeroValue)) } goconvey-1.5.0/assertions/filter.go000066400000000000000000000007351227302763300173660ustar00rootroot00000000000000package assertions import "fmt" const ( success = "" needExactValues = "This assertion requires exactly %d comparison values (you provided %d)." ) func need(needed int, expected []interface{}) string { if len(expected) != needed { return fmt.Sprintf(needExactValues, needed, len(expected)) } return success } func atLeast(minimum int, expected []interface{}) string { if len(expected) < 1 { return shouldHaveProvidedCollectionMembers } return success } goconvey-1.5.0/assertions/init.go000066400000000000000000000001351227302763300170360ustar00rootroot00000000000000package assertions var serializer Serializer func init() { serializer = newSerializer() } goconvey-1.5.0/assertions/messages.go000066400000000000000000000127201227302763300177050ustar00rootroot00000000000000package assertions const ( // equality shouldHaveBeenEqual = "Expected: '%v'\nActual: '%v'\n(Should be equal)" shouldNotHaveBeenEqual = "Expected '%v'\nto NOT equal '%v'\n(but it did)!" shouldHaveBeenAlmostEqual = "Expected '%v' to almost equal '%v' (but it didn't)!" shouldHaveNotBeenAlmostEqual = "Expected '%v' to NOT almost equal '%v' (but it did)!" shouldHaveResembled = "Expected: '%v'\nActual: '%v'\n(Should resemble)!" shouldNotHaveResembled = "Expected '%v'\nto NOT resemble '%v'\n(but it did)!" shouldBePointers = "Both arguments should be pointers " shouldHaveBeenNonNilPointer = shouldBePointers + "(the %s was %s)!" shouldHavePointedTo = "Expected '%v' (address: '%v') and '%v' (address: '%v') to be the same address (but their weren't)!" shouldNotHavePointedTo = "Expected '%v' and '%v' to be different references (but they matched: '%v')!" shouldHaveBeenNil = "Expected: nil\nActual: '%v'" shouldNotHaveBeenNil = "Expected '%v' to NOT be nil (but it was)!" shouldHaveBeenTrue = "Expected: true\nActual: %v" shouldHaveBeenFalse = "Expected: false\nActual: %v" shouldHaveBeenZeroValue = "'%v' should have been the zero value" //"Expected: (zero value)\nActual: %v" ) const ( // quantity comparisons shouldHaveBeenGreater = "Expected '%v' to be greater than '%v' (but it wasn't)!" shouldHaveBeenGreaterOrEqual = "Expected '%v' to be greater than or equal to '%v' (but it wasn't)!" shouldHaveBeenLess = "Expected '%v' to be less than '%v' (but it wasn't)!" shouldHaveBeenLessOrEqual = "Expected '%v' to be less than or equal to '%v' (but it wasn't)!" shouldHaveBeenBetween = "Expected '%v' to be between '%v' and '%v' (but it wasn't)!" shouldNotHaveBeenBetween = "Expected '%v' NOT to be between '%v' and '%v' (but it was)!" shouldHaveDifferentUpperAndLower = "The lower and upper bounds must be different values (they were both '%v')." shouldHaveBeenBetweenOrEqual = "Expected '%v' to be between '%v' and '%v' or equal to one of them (but it wasn't)!" shouldNotHaveBeenBetweenOrEqual = "Expected '%v' NOT to be between '%v' and '%v' or equal to one of them (but it was)!" ) const ( // collections shouldHaveContained = "Expected the container (%v) to contain: '%v' (but it didn't)!" shouldNotHaveContained = "Expected the container (%v) NOT to contain: '%v' (but it did)!" shouldHaveBeenIn = "Expected '%v' to be in the container (%v, but it wasn't)!" shouldNotHaveBeenIn = "Expected '%v' NOT to be in the container (%v, but it was)!" shouldHaveBeenAValidCollection = "You must provide a valid container (was %v)!" shouldHaveProvidedCollectionMembers = "This assertion requires at least 1 comparison value (you provided 0)." ) const ( // strings shouldHaveStartedWith = "Expected '%v'\nto start with '%v'\n(but it didn't)!" shouldNotHaveStartedWith = "Expected '%v'\nNOT to start with '%v'\n(but it did)!" shouldHaveEndedWith = "Expected '%v'\nto end with '%v'\n(but it didn't)!" shouldNotHaveEndedWith = "Expected '%v'\nNOT to end with '%v'\n(but it did)!" shouldBothBeStrings = "Both arguments to this assertion must be strings (you provided %v and %v)." shouldBeString = "The argument to this assertion must be a string (you provided %v)." shouldHaveContainedSubstring = "Expected '%s' to contain substring '%s' (but it didn't)!" shouldNotHaveContainedSubstring = "Expected '%s' NOT to contain substring '%s' (but it didn't)!" shouldHaveBeenBlank = "Expected '%s' to be blank (but it wasn't)!" shouldNotHaveBeenBlank = "Expected value to NOT be blank (but it was)!" ) const ( // panics shouldUseVoidNiladicFunction = "You must provide a void, niladic function as the first argument!" shouldHavePanickedWith = "Expected func() to panic with '%v' (but it panicked with '%v')!" shouldHavePanicked = "Expected func() to panic (but it didn't)!" shouldNotHavePanicked = "Expected func() NOT to panic (but it did)!" shouldNotHavePanickedWith = "Expected func() NOT to panic with '%v' (but it did)!" ) const ( // type checking shouldHaveBeenA = "Expected '%v' to be: '%v' (but was: '%v')!" shouldNotHaveBeenA = "Expected '%v' to NOT be: '%v' (but it was)!" ) const ( // time comparisons shouldUseTimes = "You must provide time instances as arguments to this assertion." shouldUseTimeSlice = "You must provide a slice of time instances as the first argument to this assertion." shouldUseDurationAndTime = "You must provide a duration and a time as arguments to this assertion." shouldHaveHappenedBefore = "Expected '%v' to happen before '%v' (it happened '%v' after)!" shouldHaveHappenedAfter = "Expected '%v' to happen after '%v' (it happened '%v' before)!" shouldHaveHappenedBetween = "Expected '%v' to happen between '%v' and '%v' (it happened '%v' outside threshold)!" shouldNotHaveHappenedOnOrBetween = "Expected '%v' to NOT happen on or between '%v' and '%v' (but it did)!" // format params: incorrect-index, previous-index, previous-time, incorrect-index, incorrect-time shouldHaveBeenChronological = "The 'Time' at index [%d] should have happened after the previous one (but it didn't!):\n [%d]: %s\n [%d]: %s (see, it happened before!)" ) goconvey-1.5.0/assertions/panic.go000066400000000000000000000047071227302763300171760ustar00rootroot00000000000000package assertions import "fmt" // ShouldPanic receives a void, niladic function and expects to recover a panic. func ShouldPanic(actual interface{}, expected ...interface{}) (message string) { if fail := need(0, expected); fail != success { return fail } action, _ := actual.(func()) if action == nil { message = shouldUseVoidNiladicFunction return } defer func() { recovered := recover() if recovered == nil { message = shouldHavePanicked } else { message = success } }() action() return } // ShouldNotPanic receives a void, niladic function and expects to execute the function without any panic. func ShouldNotPanic(actual interface{}, expected ...interface{}) (message string) { if fail := need(0, expected); fail != success { return fail } action, _ := actual.(func()) if action == nil { message = shouldUseVoidNiladicFunction return } defer func() { recovered := recover() if recovered != nil { message = shouldNotHavePanicked } else { message = success } }() action() return } // ShouldPanicWith receives a void, niladic function and expects to recover a panic with the second argument as the content. func ShouldPanicWith(actual interface{}, expected ...interface{}) (message string) { if fail := need(1, expected); fail != success { return fail } action, _ := actual.(func()) if action == nil { message = shouldUseVoidNiladicFunction return } defer func() { recovered := recover() if recovered == nil { message = shouldHavePanicked } else { if equal := ShouldEqual(recovered, expected[0]); equal != success { message = serializer.serialize(expected[0], recovered, fmt.Sprintf(shouldHavePanickedWith, expected[0], recovered)) } else { message = success } } }() action() return } // ShouldNotPanicWith receives a void, niladic function and expects to recover a panic whose content differs from the second argument. func ShouldNotPanicWith(actual interface{}, expected ...interface{}) (message string) { if fail := need(1, expected); fail != success { return fail } action, _ := actual.(func()) if action == nil { message = shouldUseVoidNiladicFunction return } defer func() { recovered := recover() if recovered == nil { message = success } else { if equal := ShouldEqual(recovered, expected[0]); equal == success { message = fmt.Sprintf(shouldNotHavePanickedWith, expected[0]) } else { message = success } } }() action() return } goconvey-1.5.0/assertions/panic_test.go000066400000000000000000000047601227302763300202340ustar00rootroot00000000000000package assertions import "testing" func TestShouldPanic(t *testing.T) { fail(t, so(func() {}, ShouldPanic, 1), "This assertion requires exactly 0 comparison values (you provided 1).") fail(t, so(func() {}, ShouldPanic, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") fail(t, so(1, ShouldPanic), shouldUseVoidNiladicFunction) fail(t, so(func(i int) {}, ShouldPanic), shouldUseVoidNiladicFunction) fail(t, so(func() int { panic("hi") }, ShouldPanic), shouldUseVoidNiladicFunction) fail(t, so(func() {}, ShouldPanic), shouldHavePanicked) pass(t, so(func() { panic("hi") }, ShouldPanic)) } func TestShouldNotPanic(t *testing.T) { fail(t, so(func() {}, ShouldNotPanic, 1), "This assertion requires exactly 0 comparison values (you provided 1).") fail(t, so(func() {}, ShouldNotPanic, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") fail(t, so(1, ShouldNotPanic), shouldUseVoidNiladicFunction) fail(t, so(func(i int) {}, ShouldNotPanic), shouldUseVoidNiladicFunction) fail(t, so(func() { panic("hi") }, ShouldNotPanic), shouldNotHavePanicked) pass(t, so(func() {}, ShouldNotPanic)) } func TestShouldPanicWith(t *testing.T) { fail(t, so(func() {}, ShouldPanicWith), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(func() {}, ShouldPanicWith, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") fail(t, so(1, ShouldPanicWith, 1), shouldUseVoidNiladicFunction) fail(t, so(func(i int) {}, ShouldPanicWith, "hi"), shouldUseVoidNiladicFunction) fail(t, so(func() {}, ShouldPanicWith, "bye"), shouldHavePanicked) fail(t, so(func() { panic("hi") }, ShouldPanicWith, "bye"), "bye|hi|Expected func() to panic with 'bye' (but it panicked with 'hi')!") pass(t, so(func() { panic("hi") }, ShouldPanicWith, "hi")) } func TestShouldNotPanicWith(t *testing.T) { fail(t, so(func() {}, ShouldNotPanicWith), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(func() {}, ShouldNotPanicWith, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") fail(t, so(1, ShouldNotPanicWith, 1), shouldUseVoidNiladicFunction) fail(t, so(func(i int) {}, ShouldNotPanicWith, "hi"), shouldUseVoidNiladicFunction) fail(t, so(func() { panic("hi") }, ShouldNotPanicWith, "hi"), "Expected func() NOT to panic with 'hi' (but it did)!") pass(t, so(func() {}, ShouldNotPanicWith, "bye")) pass(t, so(func() { panic("hi") }, ShouldNotPanicWith, "bye")) } goconvey-1.5.0/assertions/quantity.go000066400000000000000000000115121227302763300177520ustar00rootroot00000000000000package assertions import ( "fmt" "github.com/jacobsa/oglematchers" ) // ShouldBeGreaterThan receives exactly two parameters and ensures that the first is greater than the second. func ShouldBeGreaterThan(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } if matchError := oglematchers.GreaterThan(expected[0]).Matches(actual); matchError != nil { return fmt.Sprintf(shouldHaveBeenGreater, actual, expected[0]) } return success } // ShouldBeGreaterThanOrEqualTo receives exactly two parameters and ensures that the first is greater than or equal to the second. func ShouldBeGreaterThanOrEqualTo(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } else if matchError := oglematchers.GreaterOrEqual(expected[0]).Matches(actual); matchError != nil { return fmt.Sprintf(shouldHaveBeenGreaterOrEqual, actual, expected[0]) } return success } // ShouldBeLessThan receives exactly two parameters and ensures that the first is less than the second. func ShouldBeLessThan(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } else if matchError := oglematchers.LessThan(expected[0]).Matches(actual); matchError != nil { return fmt.Sprintf(shouldHaveBeenLess, actual, expected[0]) } return success } // ShouldBeLessThan receives exactly two parameters and ensures that the first is less than or equal to the second. func ShouldBeLessThanOrEqualTo(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } else if matchError := oglematchers.LessOrEqual(expected[0]).Matches(actual); matchError != nil { return fmt.Sprintf(shouldHaveBeenLess, actual, expected[0]) } return success } // ShouldBeBetween receives exactly three parameters: an actual value, a lower bound, and an upper bound. // It ensures that the actual value is between both bounds (but not equal to either of them). func ShouldBeBetween(actual interface{}, expected ...interface{}) string { if fail := need(2, expected); fail != success { return fail } lower, upper, fail := deriveBounds(expected) if fail != success { return fail } else if !isBetween(actual, lower, upper) { return fmt.Sprintf(shouldHaveBeenBetween, actual, lower, upper) } return success } // ShouldNotBeBetween receives exactly three parameters: an actual value, a lower bound, and an upper bound. // It ensures that the actual value is NOT between both bounds. func ShouldNotBeBetween(actual interface{}, expected ...interface{}) string { if fail := need(2, expected); fail != success { return fail } lower, upper, fail := deriveBounds(expected) if fail != success { return fail } else if isBetween(actual, lower, upper) { return fmt.Sprintf(shouldNotHaveBeenBetween, actual, lower, upper) } return success } func deriveBounds(values []interface{}) (lower interface{}, upper interface{}, fail string) { lower = values[0] upper = values[1] if ShouldNotEqual(lower, upper) != success { return nil, nil, fmt.Sprintf(shouldHaveDifferentUpperAndLower, lower) } else if ShouldBeLessThan(lower, upper) != success { lower, upper = upper, lower } return lower, upper, success } func isBetween(value, lower, upper interface{}) bool { if ShouldBeGreaterThan(value, lower) != success { return false } else if ShouldBeLessThan(value, upper) != success { return false } return true } // ShouldBeBetweenOrEqual receives exactly three parameters: an actual value, a lower bound, and an upper bound. // It ensures that the actual value is between both bounds or equal to one of them. func ShouldBeBetweenOrEqual(actual interface{}, expected ...interface{}) string { if fail := need(2, expected); fail != success { return fail } lower, upper, fail := deriveBounds(expected) if fail != success { return fail } else if !isBetweenOrEqual(actual, lower, upper) { return fmt.Sprintf(shouldHaveBeenBetweenOrEqual, actual, lower, upper) } return success } // ShouldNotBeBetweenOrEqual receives exactly three parameters: an actual value, a lower bound, and an upper bound. // It ensures that the actual value is nopt between the bounds nor equal to either of them. func ShouldNotBeBetweenOrEqual(actual interface{}, expected ...interface{}) string { if fail := need(2, expected); fail != success { return fail } lower, upper, fail := deriveBounds(expected) if fail != success { return fail } else if isBetweenOrEqual(actual, lower, upper) { return fmt.Sprintf(shouldNotHaveBeenBetweenOrEqual, actual, lower, upper) } return success } func isBetweenOrEqual(value, lower, upper interface{}) bool { if ShouldBeGreaterThanOrEqualTo(value, lower) != success { return false } else if ShouldBeLessThanOrEqualTo(value, upper) != success { return false } return true } goconvey-1.5.0/assertions/quantity_test.go000066400000000000000000000205611227302763300210150ustar00rootroot00000000000000package assertions import "testing" func TestShouldBeGreaterThan(t *testing.T) { fail(t, so(1, ShouldBeGreaterThan), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(1, ShouldBeGreaterThan, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).") pass(t, so(1, ShouldBeGreaterThan, 0)) pass(t, so(1.1, ShouldBeGreaterThan, 1)) pass(t, so(1, ShouldBeGreaterThan, uint(0))) pass(t, so("b", ShouldBeGreaterThan, "a")) fail(t, so(0, ShouldBeGreaterThan, 1), "Expected '0' to be greater than '1' (but it wasn't)!") fail(t, so(1, ShouldBeGreaterThan, 1.1), "Expected '1' to be greater than '1.1' (but it wasn't)!") fail(t, so(uint(0), ShouldBeGreaterThan, 1.1), "Expected '0' to be greater than '1.1' (but it wasn't)!") fail(t, so("a", ShouldBeGreaterThan, "b"), "Expected 'a' to be greater than 'b' (but it wasn't)!") } func TestShouldBeGreaterThanOrEqual(t *testing.T) { fail(t, so(1, ShouldBeGreaterThanOrEqualTo), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(1, ShouldBeGreaterThanOrEqualTo, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).") pass(t, so(1, ShouldBeGreaterThanOrEqualTo, 1)) pass(t, so(1.1, ShouldBeGreaterThanOrEqualTo, 1.1)) pass(t, so(1, ShouldBeGreaterThanOrEqualTo, uint(1))) pass(t, so("b", ShouldBeGreaterThanOrEqualTo, "b")) pass(t, so(1, ShouldBeGreaterThanOrEqualTo, 0)) pass(t, so(1.1, ShouldBeGreaterThanOrEqualTo, 1)) pass(t, so(1, ShouldBeGreaterThanOrEqualTo, uint(0))) pass(t, so("b", ShouldBeGreaterThanOrEqualTo, "a")) fail(t, so(0, ShouldBeGreaterThanOrEqualTo, 1), "Expected '0' to be greater than or equal to '1' (but it wasn't)!") fail(t, so(1, ShouldBeGreaterThanOrEqualTo, 1.1), "Expected '1' to be greater than or equal to '1.1' (but it wasn't)!") fail(t, so(uint(0), ShouldBeGreaterThanOrEqualTo, 1.1), "Expected '0' to be greater than or equal to '1.1' (but it wasn't)!") fail(t, so("a", ShouldBeGreaterThanOrEqualTo, "b"), "Expected 'a' to be greater than or equal to 'b' (but it wasn't)!") } func TestShouldBeLessThan(t *testing.T) { fail(t, so(1, ShouldBeLessThan), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(1, ShouldBeLessThan, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).") pass(t, so(0, ShouldBeLessThan, 1)) pass(t, so(1, ShouldBeLessThan, 1.1)) pass(t, so(uint(0), ShouldBeLessThan, 1)) pass(t, so("a", ShouldBeLessThan, "b")) fail(t, so(1, ShouldBeLessThan, 0), "Expected '1' to be less than '0' (but it wasn't)!") fail(t, so(1.1, ShouldBeLessThan, 1), "Expected '1.1' to be less than '1' (but it wasn't)!") fail(t, so(1.1, ShouldBeLessThan, uint(0)), "Expected '1.1' to be less than '0' (but it wasn't)!") fail(t, so("b", ShouldBeLessThan, "a"), "Expected 'b' to be less than 'a' (but it wasn't)!") } func TestShouldBeLessThanOrEqualTo(t *testing.T) { fail(t, so(1, ShouldBeLessThanOrEqualTo), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(1, ShouldBeLessThanOrEqualTo, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).") pass(t, so(1, ShouldBeLessThanOrEqualTo, 1)) pass(t, so(1.1, ShouldBeLessThanOrEqualTo, 1.1)) pass(t, so(uint(1), ShouldBeLessThanOrEqualTo, 1)) pass(t, so("b", ShouldBeLessThanOrEqualTo, "b")) pass(t, so(0, ShouldBeLessThanOrEqualTo, 1)) pass(t, so(1, ShouldBeLessThanOrEqualTo, 1.1)) pass(t, so(uint(0), ShouldBeLessThanOrEqualTo, 1)) pass(t, so("a", ShouldBeLessThanOrEqualTo, "b")) fail(t, so(1, ShouldBeLessThanOrEqualTo, 0), "Expected '1' to be less than '0' (but it wasn't)!") fail(t, so(1.1, ShouldBeLessThanOrEqualTo, 1), "Expected '1.1' to be less than '1' (but it wasn't)!") fail(t, so(1.1, ShouldBeLessThanOrEqualTo, uint(0)), "Expected '1.1' to be less than '0' (but it wasn't)!") fail(t, so("b", ShouldBeLessThanOrEqualTo, "a"), "Expected 'b' to be less than 'a' (but it wasn't)!") } func TestShouldBeBetween(t *testing.T) { fail(t, so(1, ShouldBeBetween), "This assertion requires exactly 2 comparison values (you provided 0).") fail(t, so(1, ShouldBeBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") fail(t, so(4, ShouldBeBetween, 1, 1), "The lower and upper bounds must be different values (they were both '1').") fail(t, so(7, ShouldBeBetween, 8, 12), "Expected '7' to be between '8' and '12' (but it wasn't)!") fail(t, so(8, ShouldBeBetween, 8, 12), "Expected '8' to be between '8' and '12' (but it wasn't)!") pass(t, so(9, ShouldBeBetween, 8, 12)) pass(t, so(10, ShouldBeBetween, 8, 12)) pass(t, so(11, ShouldBeBetween, 8, 12)) fail(t, so(12, ShouldBeBetween, 8, 12), "Expected '12' to be between '8' and '12' (but it wasn't)!") fail(t, so(13, ShouldBeBetween, 8, 12), "Expected '13' to be between '8' and '12' (but it wasn't)!") pass(t, so(1, ShouldBeBetween, 2, 0)) fail(t, so(-1, ShouldBeBetween, 2, 0), "Expected '-1' to be between '0' and '2' (but it wasn't)!") } func TestShouldNotBeBetween(t *testing.T) { fail(t, so(1, ShouldNotBeBetween), "This assertion requires exactly 2 comparison values (you provided 0).") fail(t, so(1, ShouldNotBeBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") fail(t, so(4, ShouldNotBeBetween, 1, 1), "The lower and upper bounds must be different values (they were both '1').") pass(t, so(7, ShouldNotBeBetween, 8, 12)) pass(t, so(8, ShouldNotBeBetween, 8, 12)) fail(t, so(9, ShouldNotBeBetween, 8, 12), "Expected '9' NOT to be between '8' and '12' (but it was)!") fail(t, so(10, ShouldNotBeBetween, 8, 12), "Expected '10' NOT to be between '8' and '12' (but it was)!") fail(t, so(11, ShouldNotBeBetween, 8, 12), "Expected '11' NOT to be between '8' and '12' (but it was)!") pass(t, so(12, ShouldNotBeBetween, 8, 12)) pass(t, so(13, ShouldNotBeBetween, 8, 12)) pass(t, so(-1, ShouldNotBeBetween, 2, 0)) fail(t, so(1, ShouldNotBeBetween, 2, 0), "Expected '1' NOT to be between '0' and '2' (but it was)!") } func TestShouldBeBetweenOrEqual(t *testing.T) { fail(t, so(1, ShouldBeBetweenOrEqual), "This assertion requires exactly 2 comparison values (you provided 0).") fail(t, so(1, ShouldBeBetweenOrEqual, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") fail(t, so(4, ShouldBeBetweenOrEqual, 1, 1), "The lower and upper bounds must be different values (they were both '1').") fail(t, so(7, ShouldBeBetweenOrEqual, 8, 12), "Expected '7' to be between '8' and '12' or equal to one of them (but it wasn't)!") pass(t, so(8, ShouldBeBetweenOrEqual, 8, 12)) pass(t, so(9, ShouldBeBetweenOrEqual, 8, 12)) pass(t, so(10, ShouldBeBetweenOrEqual, 8, 12)) pass(t, so(11, ShouldBeBetweenOrEqual, 8, 12)) pass(t, so(12, ShouldBeBetweenOrEqual, 8, 12)) fail(t, so(13, ShouldBeBetweenOrEqual, 8, 12), "Expected '13' to be between '8' and '12' or equal to one of them (but it wasn't)!") pass(t, so(1, ShouldBeBetweenOrEqual, 2, 0)) fail(t, so(-1, ShouldBeBetweenOrEqual, 2, 0), "Expected '-1' to be between '0' and '2' or equal to one of them (but it wasn't)!") } func TestShouldNotBeBetweenOrEqual(t *testing.T) { fail(t, so(1, ShouldNotBeBetweenOrEqual), "This assertion requires exactly 2 comparison values (you provided 0).") fail(t, so(1, ShouldNotBeBetweenOrEqual, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") fail(t, so(4, ShouldNotBeBetweenOrEqual, 1, 1), "The lower and upper bounds must be different values (they were both '1').") pass(t, so(7, ShouldNotBeBetweenOrEqual, 8, 12)) fail(t, so(8, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '8' NOT to be between '8' and '12' or equal to one of them (but it was)!") fail(t, so(9, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '9' NOT to be between '8' and '12' or equal to one of them (but it was)!") fail(t, so(10, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '10' NOT to be between '8' and '12' or equal to one of them (but it was)!") fail(t, so(11, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '11' NOT to be between '8' and '12' or equal to one of them (but it was)!") fail(t, so(12, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '12' NOT to be between '8' and '12' or equal to one of them (but it was)!") pass(t, so(13, ShouldNotBeBetweenOrEqual, 8, 12)) pass(t, so(-1, ShouldNotBeBetweenOrEqual, 2, 0)) fail(t, so(1, ShouldNotBeBetweenOrEqual, 2, 0), "Expected '1' NOT to be between '0' and '2' or equal to one of them (but it was)!") } goconvey-1.5.0/assertions/serializer.go000066400000000000000000000012031227302763300202410ustar00rootroot00000000000000package assertions import ( "encoding/json" "fmt" "github.com/smartystreets/goconvey/reporting" ) type Serializer interface { serialize(expected, actual interface{}, message string) string } type failureSerializer struct{} func (self *failureSerializer) serialize(expected, actual interface{}, message string) string { view := reporting.FailureView{ Message: message, Expected: fmt.Sprintf("%v", expected), Actual: fmt.Sprintf("%v", actual), } serialized, err := json.Marshal(view) if err != nil { return message } return string(serialized) } func newSerializer() *failureSerializer { return &failureSerializer{} } goconvey-1.5.0/assertions/serializer_test.go000066400000000000000000000012371227302763300213070ustar00rootroot00000000000000package assertions import ( "encoding/json" "fmt" "testing" "github.com/smartystreets/goconvey/reporting" ) func TestSerializerCreatesSerializedVersionOfAssertionResult(t *testing.T) { thing1 := Thing1{"Hi"} thing2 := Thing2{"Bye"} message := "Super-hip failure message." serializer := newSerializer() actualResult := serializer.serialize(thing1, thing2, message) expectedResult, _ := json.Marshal(reporting.FailureView{ Message: message, Expected: fmt.Sprintf("%v", thing1), Actual: fmt.Sprintf("%v", thing2), }) if actualResult != string(expectedResult) { t.Errorf("\nExpected: %s\nActual: %s", string(expectedResult), actualResult) } } goconvey-1.5.0/assertions/strings.go000066400000000000000000000122231227302763300175650ustar00rootroot00000000000000package assertions import ( "fmt" "reflect" "strings" ) // ShouldStartWith receives exactly 2 string parameters and ensures that the first starts with the second. func ShouldStartWith(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } value, valueIsString := actual.(string) prefix, prefixIsString := expected[0].(string) if !valueIsString || !prefixIsString { return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) } return shouldStartWith(value, prefix) } func shouldStartWith(value, prefix string) string { if !strings.HasPrefix(value, prefix) { return serializer.serialize(prefix, value[:len(prefix)]+"...", fmt.Sprintf(shouldHaveStartedWith, value, prefix)) } return success } // ShouldNotStartWith receives exactly 2 string parameters and ensures that the first does not start with the second. func ShouldNotStartWith(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } value, valueIsString := actual.(string) prefix, prefixIsString := expected[0].(string) if !valueIsString || !prefixIsString { return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) } return shouldNotStartWith(value, prefix) } func shouldNotStartWith(value, prefix string) string { if strings.HasPrefix(value, prefix) { if value == "" { value = "" } if prefix == "" { prefix = "" } return fmt.Sprintf(shouldNotHaveStartedWith, value, prefix) } return success } // ShouldEndWith receives exactly 2 string parameters and ensures that the first ends with the second. func ShouldEndWith(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } value, valueIsString := actual.(string) suffix, suffixIsString := expected[0].(string) if !valueIsString || !suffixIsString { return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) } return shouldEndWith(value, suffix) } func shouldEndWith(value, suffix string) string { if !strings.HasSuffix(value, suffix) { return serializer.serialize(suffix, "..."+value[len(value)-len(suffix):], fmt.Sprintf(shouldHaveEndedWith, value, suffix)) } return success } // ShouldEndWith receives exactly 2 string parameters and ensures that the first does not end with the second. func ShouldNotEndWith(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } value, valueIsString := actual.(string) suffix, suffixIsString := expected[0].(string) if !valueIsString || !suffixIsString { return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) } return shouldNotEndWith(value, suffix) } func shouldNotEndWith(value, suffix string) string { if strings.HasSuffix(value, suffix) { if value == "" { value = "" } if suffix == "" { suffix = "" } return fmt.Sprintf(shouldNotHaveEndedWith, value, suffix) } return success } // ShouldContainSubstring receives exactly 2 string parameters and ensures that the first contains the second as a substring. func ShouldContainSubstring(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } long, longOk := actual.(string) short, shortOk := expected[0].(string) if !longOk || !shortOk { return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) } if !strings.Contains(long, short) { return serializer.serialize(expected[0], actual, fmt.Sprintf(shouldHaveContainedSubstring, long, short)) } return success } // ShouldNotContainSubstring receives exactly 2 string parameters and ensures that the first does NOT contain the second as a substring. func ShouldNotContainSubstring(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } long, longOk := actual.(string) short, shortOk := expected[0].(string) if !longOk || !shortOk { return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) } if strings.Contains(long, short) { return fmt.Sprintf(shouldNotHaveContainedSubstring, long, short) } return success } // ShouldBeBlank receives exactly 1 string parameter and ensures that it is equal to "". func ShouldBeBlank(actual interface{}, expected ...interface{}) string { if fail := need(0, expected); fail != success { return fail } value, ok := actual.(string) if !ok { return fmt.Sprintf(shouldBeString, reflect.TypeOf(actual)) } if value != "" { return serializer.serialize("", value, fmt.Sprintf(shouldHaveBeenBlank, value)) } return success } // ShouldNotBeBlank receives exactly 1 string parameter and ensures that it is equal to "". func ShouldNotBeBlank(actual interface{}, expected ...interface{}) string { if fail := need(0, expected); fail != success { return fail } value, ok := actual.(string) if !ok { return fmt.Sprintf(shouldBeString, reflect.TypeOf(actual)) } if value == "" { return shouldNotHaveBeenBlank } return success } goconvey-1.5.0/assertions/strings_test.go000066400000000000000000000115341227302763300206300ustar00rootroot00000000000000package assertions import "testing" func TestShouldStartWith(t *testing.T) { serializer = newFakeSerializer() fail(t, so("", ShouldStartWith), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so("", ShouldStartWith, "asdf", "asdf"), "This assertion requires exactly 1 comparison values (you provided 2).") pass(t, so("", ShouldStartWith, "")) pass(t, so("superman", ShouldStartWith, "super")) fail(t, so("superman", ShouldStartWith, "bat"), "bat|sup...|Expected 'superman' to start with 'bat' (but it didn't)!") fail(t, so("superman", ShouldStartWith, "man"), "man|sup...|Expected 'superman' to start with 'man' (but it didn't)!") fail(t, so(1, ShouldStartWith, 2), "Both arguments to this assertion must be strings (you provided int and int).") } func TestShouldNotStartWith(t *testing.T) { fail(t, so("", ShouldNotStartWith), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so("", ShouldNotStartWith, "asdf", "asdf"), "This assertion requires exactly 1 comparison values (you provided 2).") fail(t, so("", ShouldNotStartWith, ""), "Expected '' NOT to start with '' (but it did)!") fail(t, so("superman", ShouldNotStartWith, "super"), "Expected 'superman' NOT to start with 'super' (but it did)!") pass(t, so("superman", ShouldNotStartWith, "bat")) pass(t, so("superman", ShouldNotStartWith, "man")) fail(t, so(1, ShouldNotStartWith, 2), "Both arguments to this assertion must be strings (you provided int and int).") } func TestShouldEndWith(t *testing.T) { serializer = newFakeSerializer() fail(t, so("", ShouldEndWith), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so("", ShouldEndWith, "", ""), "This assertion requires exactly 1 comparison values (you provided 2).") pass(t, so("", ShouldEndWith, "")) pass(t, so("superman", ShouldEndWith, "man")) fail(t, so("superman", ShouldEndWith, "super"), "super|...erman|Expected 'superman' to end with 'super' (but it didn't)!") fail(t, so("superman", ShouldEndWith, "blah"), "blah|...rman|Expected 'superman' to end with 'blah' (but it didn't)!") fail(t, so(1, ShouldEndWith, 2), "Both arguments to this assertion must be strings (you provided int and int).") } func TestShouldNotEndWith(t *testing.T) { fail(t, so("", ShouldNotEndWith), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so("", ShouldNotEndWith, "", ""), "This assertion requires exactly 1 comparison values (you provided 2).") fail(t, so("", ShouldNotEndWith, ""), "Expected '' NOT to end with '' (but it did)!") fail(t, so("superman", ShouldNotEndWith, "man"), "Expected 'superman' NOT to end with 'man' (but it did)!") pass(t, so("superman", ShouldNotEndWith, "super")) fail(t, so(1, ShouldNotEndWith, 2), "Both arguments to this assertion must be strings (you provided int and int).") } func TestShouldContainSubstring(t *testing.T) { serializer = newFakeSerializer() fail(t, so("asdf", ShouldContainSubstring), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so("asdf", ShouldContainSubstring, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") fail(t, so(123, ShouldContainSubstring, 23), "Both arguments to this assertion must be strings (you provided int and int).") pass(t, so("asdf", ShouldContainSubstring, "sd")) fail(t, so("qwer", ShouldContainSubstring, "sd"), "sd|qwer|Expected 'qwer' to contain substring 'sd' (but it didn't)!") } func TestShouldNotContainSubstring(t *testing.T) { fail(t, so("asdf", ShouldNotContainSubstring), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so("asdf", ShouldNotContainSubstring, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") fail(t, so(123, ShouldNotContainSubstring, 23), "Both arguments to this assertion must be strings (you provided int and int).") pass(t, so("qwer", ShouldNotContainSubstring, "sd")) fail(t, so("asdf", ShouldNotContainSubstring, "sd"), "Expected 'asdf' NOT to contain substring 'sd' (but it didn't)!") } func TestShouldBeBlank(t *testing.T) { serializer = newFakeSerializer() fail(t, so("", ShouldBeBlank, "adsf"), "This assertion requires exactly 0 comparison values (you provided 1).") fail(t, so(1, ShouldBeBlank), "The argument to this assertion must be a string (you provided int).") fail(t, so("asdf", ShouldBeBlank), "|asdf|Expected 'asdf' to be blank (but it wasn't)!") pass(t, so("", ShouldBeBlank)) } func TestShouldNotBeBlank(t *testing.T) { fail(t, so("", ShouldNotBeBlank, "adsf"), "This assertion requires exactly 0 comparison values (you provided 1).") fail(t, so(1, ShouldNotBeBlank), "The argument to this assertion must be a string (you provided int).") fail(t, so("", ShouldNotBeBlank), "Expected value to NOT be blank (but it was)!") pass(t, so("asdf", ShouldNotBeBlank)) } goconvey-1.5.0/assertions/time.go000066400000000000000000000144351227302763300170410ustar00rootroot00000000000000package assertions import ( "fmt" "time" ) // ShouldHappenBefore receives exactly 2 time.Time arguments and asserts that the first happens before the second. func ShouldHappenBefore(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } actualTime, firstOk := actual.(time.Time) expectedTime, secondOk := expected[0].(time.Time) if !firstOk || !secondOk { return shouldUseTimes } if !actualTime.Before(expectedTime) { return fmt.Sprintf(shouldHaveHappenedBefore, actualTime, expectedTime, actualTime.Sub(expectedTime)) } return success } // ShouldHappenOnOrBefore receives exactly 2 time.Time arguments and asserts that the first happens on or before the second. func ShouldHappenOnOrBefore(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } actualTime, firstOk := actual.(time.Time) expectedTime, secondOk := expected[0].(time.Time) if !firstOk || !secondOk { return shouldUseTimes } if actualTime.Equal(expectedTime) { return success } return ShouldHappenBefore(actualTime, expectedTime) } // ShouldHappenAfter receives exactly 2 time.Time arguments and asserts that the first happens after the second. func ShouldHappenAfter(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } actualTime, firstOk := actual.(time.Time) expectedTime, secondOk := expected[0].(time.Time) if !firstOk || !secondOk { return shouldUseTimes } if !actualTime.After(expectedTime) { return fmt.Sprintf(shouldHaveHappenedAfter, actualTime, expectedTime, expectedTime.Sub(actualTime)) } return success } // ShouldHappenOnOrAfter receives exactly 2 time.Time arguments and asserts that the first happens on or after the second. func ShouldHappenOnOrAfter(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } actualTime, firstOk := actual.(time.Time) expectedTime, secondOk := expected[0].(time.Time) if !firstOk || !secondOk { return shouldUseTimes } if actualTime.Equal(expectedTime) { return success } return ShouldHappenAfter(actualTime, expectedTime) } // ShouldHappenBetween receives exactly 3 time.Time arguments and asserts that the first happens between (not on) the second and third. func ShouldHappenBetween(actual interface{}, expected ...interface{}) string { if fail := need(2, expected); fail != success { return fail } actualTime, firstOk := actual.(time.Time) min, secondOk := expected[0].(time.Time) max, thirdOk := expected[1].(time.Time) if !firstOk || !secondOk || !thirdOk { return shouldUseTimes } if !actualTime.After(min) { return fmt.Sprintf(shouldHaveHappenedBetween, actualTime, min, max, min.Sub(actualTime)) } if !actualTime.Before(max) { return fmt.Sprintf(shouldHaveHappenedBetween, actualTime, min, max, actualTime.Sub(max)) } return success } // ShouldHappenOnOrBetween receives exactly 3 time.Time arguments and asserts that the first happens between or on the second and third. func ShouldHappenOnOrBetween(actual interface{}, expected ...interface{}) string { if fail := need(2, expected); fail != success { return fail } actualTime, firstOk := actual.(time.Time) min, secondOk := expected[0].(time.Time) max, thirdOk := expected[1].(time.Time) if !firstOk || !secondOk || !thirdOk { return shouldUseTimes } if actualTime.Equal(min) || actualTime.Equal(max) { return success } return ShouldHappenBetween(actualTime, min, max) } // ShouldNotHappenOnOrBetween receives exactly 3 time.Time arguments and asserts that the first // does NOT happen between or on the second or third. func ShouldNotHappenOnOrBetween(actual interface{}, expected ...interface{}) string { if fail := need(2, expected); fail != success { return fail } actualTime, firstOk := actual.(time.Time) min, secondOk := expected[0].(time.Time) max, thirdOk := expected[1].(time.Time) if !firstOk || !secondOk || !thirdOk { return shouldUseTimes } if actualTime.Equal(min) || actualTime.Equal(max) { return fmt.Sprintf(shouldNotHaveHappenedOnOrBetween, actualTime, min, max) } if actualTime.After(min) && actualTime.Before(max) { return fmt.Sprintf(shouldNotHaveHappenedOnOrBetween, actualTime, min, max) } return success } // ShouldHappenWithin receives a time.Time, a time.Duration, and a time.Time (3 arguments) // and asserts that the first time.Time happens within or on the duration specified relative to // the other time.Time. func ShouldHappenWithin(actual interface{}, expected ...interface{}) string { if fail := need(2, expected); fail != success { return fail } actualTime, firstOk := actual.(time.Time) tolerance, secondOk := expected[0].(time.Duration) threshold, thirdOk := expected[1].(time.Time) if !firstOk || !secondOk || !thirdOk { return shouldUseDurationAndTime } min := threshold.Add(-tolerance) max := threshold.Add(tolerance) return ShouldHappenOnOrBetween(actualTime, min, max) } // ShouldNotHappenWithin receives a time.Time, a time.Duration, and a time.Time (3 arguments) // and asserts that the first time.Time does NOT happen within or on the duration specified relative to // the other time.Time. func ShouldNotHappenWithin(actual interface{}, expected ...interface{}) string { if fail := need(2, expected); fail != success { return fail } actualTime, firstOk := actual.(time.Time) tolerance, secondOk := expected[0].(time.Duration) threshold, thirdOk := expected[1].(time.Time) if !firstOk || !secondOk || !thirdOk { return shouldUseDurationAndTime } min := threshold.Add(-tolerance) max := threshold.Add(tolerance) return ShouldNotHappenOnOrBetween(actualTime, min, max) } // ShouldBeChronological receives a []time.Time slice and asserts that the are // in chronological order starting with the first time.Time as the earliest. func ShouldBeChronological(actual interface{}, expected ...interface{}) string { if fail := need(0, expected); fail != success { return fail } times, ok := actual.([]time.Time) if !ok { return shouldUseTimeSlice } var previous time.Time for i, current := range times { if i > 0 && current.Before(previous) { return fmt.Sprintf(shouldHaveBeenChronological, i, i-1, previous.String(), i, current.String()) } previous = current } return "" } goconvey-1.5.0/assertions/time_test.go000066400000000000000000000247661227302763300201100ustar00rootroot00000000000000package assertions import ( "fmt" "testing" "time" ) func TestShouldHappenBefore(t *testing.T) { fail(t, so(0, ShouldHappenBefore), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(0, ShouldHappenBefore, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") fail(t, so(0, ShouldHappenBefore, 1), shouldUseTimes) fail(t, so(0, ShouldHappenBefore, time.Now()), shouldUseTimes) fail(t, so(time.Now(), ShouldHappenBefore, 0), shouldUseTimes) fail(t, so(january3, ShouldHappenBefore, january1), fmt.Sprintf("Expected '%s' to happen before '%s' (it happened '48h0m0s' after)!", pretty(january3), pretty(january1))) fail(t, so(january3, ShouldHappenBefore, january3), fmt.Sprintf("Expected '%s' to happen before '%s' (it happened '0' after)!", pretty(january3), pretty(january3))) pass(t, so(january1, ShouldHappenBefore, january3)) } func TestShouldHappenOnOrBefore(t *testing.T) { fail(t, so(0, ShouldHappenOnOrBefore), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(0, ShouldHappenOnOrBefore, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") fail(t, so(0, ShouldHappenOnOrBefore, 1), shouldUseTimes) fail(t, so(0, ShouldHappenOnOrBefore, time.Now()), shouldUseTimes) fail(t, so(time.Now(), ShouldHappenOnOrBefore, 0), shouldUseTimes) fail(t, so(january3, ShouldHappenOnOrBefore, january1), fmt.Sprintf("Expected '%s' to happen before '%s' (it happened '48h0m0s' after)!", pretty(january3), pretty(january1))) pass(t, so(january3, ShouldHappenOnOrBefore, january3)) pass(t, so(january1, ShouldHappenOnOrBefore, january3)) } func TestShouldHappenAfter(t *testing.T) { fail(t, so(0, ShouldHappenAfter), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(0, ShouldHappenAfter, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") fail(t, so(0, ShouldHappenAfter, 1), shouldUseTimes) fail(t, so(0, ShouldHappenAfter, time.Now()), shouldUseTimes) fail(t, so(time.Now(), ShouldHappenAfter, 0), shouldUseTimes) fail(t, so(january1, ShouldHappenAfter, january2), fmt.Sprintf("Expected '%s' to happen after '%s' (it happened '24h0m0s' before)!", pretty(january1), pretty(january2))) fail(t, so(january1, ShouldHappenAfter, january1), fmt.Sprintf("Expected '%s' to happen after '%s' (it happened '0' before)!", pretty(january1), pretty(january1))) pass(t, so(january3, ShouldHappenAfter, january1)) } func TestShouldHappenOnOrAfter(t *testing.T) { fail(t, so(0, ShouldHappenOnOrAfter), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(0, ShouldHappenOnOrAfter, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") fail(t, so(0, ShouldHappenOnOrAfter, 1), shouldUseTimes) fail(t, so(0, ShouldHappenOnOrAfter, time.Now()), shouldUseTimes) fail(t, so(time.Now(), ShouldHappenOnOrAfter, 0), shouldUseTimes) fail(t, so(january1, ShouldHappenOnOrAfter, january2), fmt.Sprintf("Expected '%s' to happen after '%s' (it happened '24h0m0s' before)!", pretty(january1), pretty(january2))) pass(t, so(january1, ShouldHappenOnOrAfter, january1)) pass(t, so(january3, ShouldHappenOnOrAfter, january1)) } func TestShouldHappenBetween(t *testing.T) { fail(t, so(0, ShouldHappenBetween), "This assertion requires exactly 2 comparison values (you provided 0).") fail(t, so(0, ShouldHappenBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") fail(t, so(0, ShouldHappenBetween, 1, 2), shouldUseTimes) fail(t, so(0, ShouldHappenBetween, time.Now(), time.Now()), shouldUseTimes) fail(t, so(time.Now(), ShouldHappenBetween, 0, time.Now()), shouldUseTimes) fail(t, so(time.Now(), ShouldHappenBetween, time.Now(), 9), shouldUseTimes) fail(t, so(january1, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january1), pretty(january2), pretty(january4))) fail(t, so(january2, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '0' outside threshold)!", pretty(january2), pretty(january2), pretty(january4))) pass(t, so(january3, ShouldHappenBetween, january2, january4)) fail(t, so(january4, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '0' outside threshold)!", pretty(january4), pretty(january2), pretty(january4))) fail(t, so(january5, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january5), pretty(january2), pretty(january4))) } func TestShouldHappenOnOrBetween(t *testing.T) { fail(t, so(0, ShouldHappenOnOrBetween), "This assertion requires exactly 2 comparison values (you provided 0).") fail(t, so(0, ShouldHappenOnOrBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") fail(t, so(0, ShouldHappenOnOrBetween, 1, time.Now()), shouldUseTimes) fail(t, so(0, ShouldHappenOnOrBetween, time.Now(), 1), shouldUseTimes) fail(t, so(time.Now(), ShouldHappenOnOrBetween, 0, 1), shouldUseTimes) fail(t, so(january1, ShouldHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january1), pretty(january2), pretty(january4))) pass(t, so(january2, ShouldHappenOnOrBetween, january2, january4)) pass(t, so(january3, ShouldHappenOnOrBetween, january2, january4)) pass(t, so(january4, ShouldHappenOnOrBetween, january2, january4)) fail(t, so(january5, ShouldHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january5), pretty(january2), pretty(january4))) } func TestShouldNotHappenOnOrBetween(t *testing.T) { fail(t, so(0, ShouldNotHappenOnOrBetween), "This assertion requires exactly 2 comparison values (you provided 0).") fail(t, so(0, ShouldNotHappenOnOrBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") fail(t, so(0, ShouldNotHappenOnOrBetween, 1, time.Now()), shouldUseTimes) fail(t, so(0, ShouldNotHappenOnOrBetween, time.Now(), 1), shouldUseTimes) fail(t, so(time.Now(), ShouldNotHappenOnOrBetween, 0, 1), shouldUseTimes) pass(t, so(january1, ShouldNotHappenOnOrBetween, january2, january4)) fail(t, so(january2, ShouldNotHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january2), pretty(january2), pretty(january4))) fail(t, so(january3, ShouldNotHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january3), pretty(january2), pretty(january4))) fail(t, so(january4, ShouldNotHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january4), pretty(january2), pretty(january4))) pass(t, so(january5, ShouldNotHappenOnOrBetween, january2, january4)) } func TestShouldHappenWithin(t *testing.T) { fail(t, so(0, ShouldHappenWithin), "This assertion requires exactly 2 comparison values (you provided 0).") fail(t, so(0, ShouldHappenWithin, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") fail(t, so(0, ShouldHappenWithin, 1, 2), shouldUseDurationAndTime) fail(t, so(0, ShouldHappenWithin, oneDay, time.Now()), shouldUseDurationAndTime) fail(t, so(time.Now(), ShouldHappenWithin, 0, time.Now()), shouldUseDurationAndTime) fail(t, so(january1, ShouldHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january1), pretty(january2), pretty(january4))) pass(t, so(january2, ShouldHappenWithin, oneDay, january3)) pass(t, so(january3, ShouldHappenWithin, oneDay, january3)) pass(t, so(january4, ShouldHappenWithin, oneDay, january3)) fail(t, so(january5, ShouldHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january5), pretty(january2), pretty(january4))) } func TestShouldNotHappenWithin(t *testing.T) { fail(t, so(0, ShouldNotHappenWithin), "This assertion requires exactly 2 comparison values (you provided 0).") fail(t, so(0, ShouldNotHappenWithin, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") fail(t, so(0, ShouldNotHappenWithin, 1, 2), shouldUseDurationAndTime) fail(t, so(0, ShouldNotHappenWithin, oneDay, time.Now()), shouldUseDurationAndTime) fail(t, so(time.Now(), ShouldNotHappenWithin, 0, time.Now()), shouldUseDurationAndTime) pass(t, so(january1, ShouldNotHappenWithin, oneDay, january3)) fail(t, so(january2, ShouldNotHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january2), pretty(january2), pretty(january4))) fail(t, so(january3, ShouldNotHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january3), pretty(january2), pretty(january4))) fail(t, so(january4, ShouldNotHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january4), pretty(january2), pretty(january4))) pass(t, so(january5, ShouldNotHappenWithin, oneDay, january3)) } func TestShouldBeChronological(t *testing.T) { fail(t, so(0, ShouldBeChronological, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") fail(t, so(0, ShouldBeChronological), shouldUseTimeSlice) fail(t, so([]time.Time{january5, january1}, ShouldBeChronological), "The 'Time' at index [1] should have happened after the previous one (but it didn't!):\n [0]: 2013-01-05 00:00:00 +0000 UTC\n [1]: 2013-01-01 00:00:00 +0000 UTC (see, it happened before!)") pass(t, so([]time.Time{january1, january2, january3, january4, january5}, ShouldBeChronological)) } const layout = "2006-01-02 15:04" var january1, _ = time.Parse(layout, "2013-01-01 00:00") var january2, _ = time.Parse(layout, "2013-01-02 00:00") var january3, _ = time.Parse(layout, "2013-01-03 00:00") var january4, _ = time.Parse(layout, "2013-01-04 00:00") var january5, _ = time.Parse(layout, "2013-01-05 00:00") var oneDay, _ = time.ParseDuration("24h0m0s") var twoDays, _ = time.ParseDuration("48h0m0s") func pretty(t time.Time) string { return fmt.Sprintf("%v", t) } goconvey-1.5.0/assertions/type.go000066400000000000000000000020041227302763300170510ustar00rootroot00000000000000package assertions import ( "fmt" "reflect" ) // ShouldHaveSameTypeAs receives exactly two parameters and compares their underlying types for equality. func ShouldHaveSameTypeAs(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } first := reflect.TypeOf(actual) second := reflect.TypeOf(expected[0]) if equal := ShouldEqual(first, second); equal != success { return serializer.serialize(second, first, fmt.Sprintf(shouldHaveBeenA, actual, second, first)) } return success } // ShouldNotHaveSameTypeAs receives exactly two parameters and compares their underlying types for inequality. func ShouldNotHaveSameTypeAs(actual interface{}, expected ...interface{}) string { if fail := need(1, expected); fail != success { return fail } first := reflect.TypeOf(actual) second := reflect.TypeOf(expected[0]) if equal := ShouldEqual(first, second); equal == success { return fmt.Sprintf(shouldNotHaveBeenA, actual, second) } return success } goconvey-1.5.0/assertions/type_test.go000066400000000000000000000023171227302763300201170ustar00rootroot00000000000000package assertions import "testing" func TestShouldHaveSameTypeAs(t *testing.T) { serializer = newFakeSerializer() fail(t, so(1, ShouldHaveSameTypeAs), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(1, ShouldHaveSameTypeAs, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") fail(t, so(nil, ShouldHaveSameTypeAs, 0), "int||Expected '' to be: 'int' (but was: '')!") fail(t, so(1, ShouldHaveSameTypeAs, "asdf"), "string|int|Expected '1' to be: 'string' (but was: 'int')!") pass(t, so(1, ShouldHaveSameTypeAs, 0)) pass(t, so(nil, ShouldHaveSameTypeAs, nil)) } func TestShouldNotHaveSameTypeAs(t *testing.T) { fail(t, so(1, ShouldNotHaveSameTypeAs), "This assertion requires exactly 1 comparison values (you provided 0).") fail(t, so(1, ShouldNotHaveSameTypeAs, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") fail(t, so(1, ShouldNotHaveSameTypeAs, 0), "Expected '1' to NOT be: 'int' (but it was)!") fail(t, so(nil, ShouldNotHaveSameTypeAs, nil), "Expected '' to NOT be: '' (but it was)!") pass(t, so(nil, ShouldNotHaveSameTypeAs, 0)) pass(t, so(1, ShouldNotHaveSameTypeAs, "asdf")) } goconvey-1.5.0/assertions/utilities_for_test.go000066400000000000000000000027401227302763300220170ustar00rootroot00000000000000package assertions import ( "fmt" "path" "runtime" "strings" "testing" ) func pass(t *testing.T, result string) { if result != success { _, file, line, _ := runtime.Caller(1) base := path.Base(file) t.Errorf("Expectation should have passed but failed (see %s: line %d): '%s'", base, line, result) } } func fail(t *testing.T, actual string, expected string) { actual = format(actual) expected = format(expected) if actual != expected { if actual == "" { actual = "(empty)" } _, file, line, _ := runtime.Caller(1) base := path.Base(file) t.Errorf("Expectation should have failed but passed (see %s: line %d). \nExpected: %s\nActual: %s\n", base, line, expected, actual) } } func format(message string) string { message = strings.Replace(message, "\n", " ", -1) for strings.Contains(message, " ") { message = strings.Replace(message, " ", " ", -1) } return message } func so(actual interface{}, assert func(interface{}, ...interface{}) string, expected ...interface{}) string { return assert(actual, expected...) } type Thing1 struct { a string } type Thing2 struct { a string } type Thinger interface { Hi() } type Thing struct{} func (self *Thing) Hi() {} /******** FakeSerialzier ********/ type fakeSerializer struct{} func (self *fakeSerializer) serialize(expected, actual interface{}, message string) string { return fmt.Sprintf("%v|%v|%s", expected, actual, message) } func newFakeSerializer() *fakeSerializer { return &fakeSerializer{} } goconvey-1.5.0/convey/000077500000000000000000000000001227302763300146565ustar00rootroot00000000000000goconvey-1.5.0/convey/assertions.go000066400000000000000000000052321227302763300174010ustar00rootroot00000000000000package convey import "github.com/smartystreets/goconvey/assertions" var ( ShouldEqual = assertions.ShouldEqual ShouldNotEqual = assertions.ShouldNotEqual ShouldAlmostEqual = assertions.ShouldAlmostEqual ShouldNotAlmostEqual = assertions.ShouldNotAlmostEqual ShouldResemble = assertions.ShouldResemble ShouldNotResemble = assertions.ShouldNotResemble ShouldPointTo = assertions.ShouldPointTo ShouldNotPointTo = assertions.ShouldNotPointTo ShouldBeNil = assertions.ShouldBeNil ShouldNotBeNil = assertions.ShouldNotBeNil ShouldBeTrue = assertions.ShouldBeTrue ShouldBeFalse = assertions.ShouldBeFalse ShouldBeZeroValue = assertions.ShouldBeZeroValue ShouldBeGreaterThan = assertions.ShouldBeGreaterThan ShouldBeGreaterThanOrEqualTo = assertions.ShouldBeGreaterThanOrEqualTo ShouldBeLessThan = assertions.ShouldBeLessThan ShouldBeLessThanOrEqualTo = assertions.ShouldBeLessThanOrEqualTo ShouldBeBetween = assertions.ShouldBeBetween ShouldNotBeBetween = assertions.ShouldNotBeBetween ShouldContain = assertions.ShouldContain ShouldNotContain = assertions.ShouldNotContain ShouldBeIn = assertions.ShouldBeIn ShouldNotBeIn = assertions.ShouldNotBeIn ShouldStartWith = assertions.ShouldStartWith ShouldNotStartWith = assertions.ShouldNotStartWith ShouldEndWith = assertions.ShouldEndWith ShouldNotEndWith = assertions.ShouldNotEndWith ShouldBeBlank = assertions.ShouldBeBlank ShouldNotBeBlank = assertions.ShouldNotBeBlank ShouldContainSubstring = assertions.ShouldContainSubstring ShouldNotContainSubstring = assertions.ShouldNotContainSubstring ShouldPanic = assertions.ShouldPanic ShouldNotPanic = assertions.ShouldNotPanic ShouldPanicWith = assertions.ShouldPanicWith ShouldNotPanicWith = assertions.ShouldNotPanicWith ShouldHaveSameTypeAs = assertions.ShouldHaveSameTypeAs ShouldNotHaveSameTypeAs = assertions.ShouldNotHaveSameTypeAs ShouldHappenBefore = assertions.ShouldHappenBefore ShouldHappenOnOrBefore = assertions.ShouldHappenOnOrBefore ShouldHappenAfter = assertions.ShouldHappenAfter ShouldHappenOnOrAfter = assertions.ShouldHappenOnOrAfter ShouldHappenBetween = assertions.ShouldHappenBetween ShouldHappenOnOrBetween = assertions.ShouldHappenOnOrBetween ShouldNotHappenOnOrBetween = assertions.ShouldNotHappenOnOrBetween ShouldHappenWithin = assertions.ShouldHappenWithin ShouldNotHappenWithin = assertions.ShouldNotHappenWithin ShouldBeChronological = assertions.ShouldBeChronological ) goconvey-1.5.0/convey/context.go000066400000000000000000000053771227302763300167050ustar00rootroot00000000000000package convey import ( "runtime" "sync" "github.com/smartystreets/goconvey/execution" "github.com/smartystreets/goconvey/reporting" ) // SuiteContext magically handles all coordination of reporter, runners as they handle calls // to Convey, So, and the like. It does this via runtime call stack inspection, making sure // that each test function has its own runner and reporter, and routes all live registrations // to the appropriate runner/reporter. type SuiteContext struct { runners map[string]execution.Runner reporters map[string]reporting.Reporter lock sync.Mutex } func (self *SuiteContext) Run(entry *execution.Registration) { key := resolveTestPackageAndFunctionName() if self.currentRunner() != nil { panic(execution.ExtraGoTest) } reporter := buildReporter() runner := execution.NewRunner() runner.UpgradeReporter(reporter) self.lock.Lock() self.runners[key] = runner self.reporters[key] = reporter self.lock.Unlock() runner.Begin(entry) runner.Run() self.lock.Lock() delete(self.runners, key) delete(self.reporters, key) self.lock.Unlock() } func (self *SuiteContext) CurrentRunner() execution.Runner { runner := self.currentRunner() if runner == nil { panic(execution.MissingGoTest) } return runner } func (self *SuiteContext) currentRunner() execution.Runner { self.lock.Lock() defer self.lock.Unlock() return self.runners[resolveTestPackageAndFunctionName()] } func (self *SuiteContext) CurrentReporter() reporting.Reporter { self.lock.Lock() defer self.lock.Unlock() return self.reporters[resolveTestPackageAndFunctionName()] } func NewSuiteContext() *SuiteContext { self := new(SuiteContext) self.runners = make(map[string]execution.Runner) self.reporters = make(map[string]reporting.Reporter) return self } // resolveTestPackageAndFunctionName traverses the call stack in reverse, looking for // the go testing harnass call ("testing.tRunner") and then grabs the very next entry, // which represents the package under test and the test function name. Voila! func resolveTestPackageAndFunctionName() string { var callerId uintptr callers := runtime.Callers(0, callStack) for y := callers; y > 0; y-- { callerId, _, _, _ = runtime.Caller(y) packageAndTestFunctionName := runtime.FuncForPC(callerId).Name() if packageAndTestFunctionName == goTestHarness { callerId, _, _, _ = runtime.Caller(y - 1) name := runtime.FuncForPC(callerId).Name() return name } } panic("Can't resolve test method name! Are you calling Convey() from a `*_test.go` file and a `Test*` method (because you should be)?") } const maxStackDepth = 100 // This had better be enough... const goTestHarness = "testing.tRunner" // I hope this doesn't change... var callStack []uintptr = make([]uintptr, maxStackDepth, maxStackDepth) goconvey-1.5.0/convey/doc.go000066400000000000000000000064701227302763300157610ustar00rootroot00000000000000// Package convey contains all of the public-facing entry points to this project. // This means that it should never be required of the user to import any other // packages from this project as they serve internal purposes. package convey import ( "github.com/smartystreets/goconvey/execution" "github.com/smartystreets/goconvey/reporting" ) // Convey is the method intended for use when declaring the scopes // of a specification. Each scope has a description and a func() // which may contain other calls to Convey(), Reset() or Should-style // assertions. Convey calls can be nested as far as you see fit. // // IMPORTANT NOTE: The top-level Convey() within a Test method // must conform to the following signature: // // Convey(description string, t *testing.T, action func()) // // All other calls should like like this (no need to pass in *testing.T): // // Convey(description string, action func()) // // Don't worry, the goconvey will panic if you get it wrong so you can fix it. // // See the examples package for, well, examples. func Convey(items ...interface{}) { entry := discover(items) register(entry) } // SkipConvey is analagous to Convey except that the scope is not executed // (which means that child scopes defined within this scope are not run either). // The reporter will be notified that this step was skipped. func SkipConvey(items ...interface{}) { entry := discover(items) entry.Action = execution.NewSkippedAction(skipReport) register(entry) } func register(entry *execution.Registration) { if entry.IsTopLevel() { suites.Run(entry) } else { suites.CurrentRunner().Register(entry) } } func skipReport() { suites.CurrentReporter().Report(reporting.NewSkipReport()) } // Reset registers a cleanup function to be run after each Convey() // in the same scope. See the examples package for a simple use case. func Reset(action func()) { suites.CurrentRunner().RegisterReset(execution.NewAction(action)) } // So is the means by which assertions are made against the system under test. // The majority of exported names in the assertions package begin with the word // 'Should' and describe how the first argument (actual) should compare with any // of the final (expected) arguments. How many final arguments are accepted // depends on the particular assertion that is passed in as the assert argument. // See the examples package for use cases and the assertions package for // documentation on specific assertion methods. func So(actual interface{}, assert assertion, expected ...interface{}) { if result := assert(actual, expected...); result == assertionSuccess { suites.CurrentReporter().Report(reporting.NewSuccessReport()) } else { suites.CurrentReporter().Report(reporting.NewFailureReport(result)) } } // SkipSo is analagous to So except that the assertion that would have been passed // to So is not executed and the reporter is notified that the assertion was skipped. func SkipSo(stuff ...interface{}) { skipReport() } // assertion is an alias for a function with a signature that the convey.So() // method can handle. Any future or custom assertions should conform to this // method signature. The return value should be an empty string if the assertion // passes and a well-formed failure message if not. type assertion func(actual interface{}, expected ...interface{}) string const assertionSuccess = "" goconvey-1.5.0/convey/isolated_execution_test.go000066400000000000000000000077161227302763300221460ustar00rootroot00000000000000package convey import ( "strconv" "testing" "github.com/smartystreets/goconvey/execution" ) func TestSingleScope(t *testing.T) { output := prepare() Convey("hi", t, func() { output += "done" }) expectEqual(t, "done", output) } func TestSingleScopeWithMultipleConveys(t *testing.T) { output := prepare() Convey("1", t, func() { output += "1" }) Convey("2", t, func() { output += "2" }) expectEqual(t, "12", output) } func TestNestedScopes(t *testing.T) { output := prepare() Convey("a", t, func() { output += "a " Convey("bb", func() { output += "bb " Convey("ccc", func() { output += "ccc | " }) }) }) expectEqual(t, "a bb ccc | ", output) } func TestNestedScopesWithIsolatedExecution(t *testing.T) { output := prepare() Convey("a", t, func() { output += "a " Convey("aa", func() { output += "aa " Convey("aaa", func() { output += "aaa | " }) Convey("aaa1", func() { output += "aaa1 | " }) }) Convey("ab", func() { output += "ab " Convey("abb", func() { output += "abb | " }) }) }) expectEqual(t, "a aa aaa | a aa aaa1 | a ab abb | ", output) } func TestSingleScopeWithConveyAndNestedReset(t *testing.T) { output := prepare() Convey("1", t, func() { output += "1" Reset(func() { output += "a" }) }) expectEqual(t, "1a", output) } func TestSingleScopeWithMultipleRegistrationsAndReset(t *testing.T) { output := prepare() Convey("reset after each nested convey", t, func() { Convey("first output", func() { output += "1" }) Convey("second output", func() { output += "2" }) Reset(func() { output += "a" }) }) expectEqual(t, "1a2a", output) } func TestSingleScopeWithMultipleRegistrationsAndMultipleResets(t *testing.T) { output := prepare() Convey("each reset is run at end of each nested convey", t, func() { Convey("1", func() { output += "1" }) Convey("2", func() { output += "2" }) Reset(func() { output += "a" }) Reset(func() { output += "b" }) }) expectEqual(t, "1ab2ab", output) } func TestPanicAtHigherLevelScopePreventsChildScopesFromRunning(t *testing.T) { output := prepare() Convey("This step panics", t, func() { Convey("this should NOT be executed", func() { output += "1" }) panic("Hi") }) expectEqual(t, "", output) } func TestPanicInChildScopeDoes_NOT_PreventExecutionOfSiblingScopes(t *testing.T) { output := prepare() Convey("This is the parent", t, func() { Convey("This step panics", func() { panic("Hi") output += "1" }) Convey("This sibling should execute", func() { output += "2" }) }) expectEqual(t, "2", output) } func TestResetsAreAlwaysExecutedAfterScopePanics(t *testing.T) { output := prepare() Convey("This is the parent", t, func() { Convey("This step panics", func() { panic("Hi") output += "1" }) Convey("This sibling step does not panic", func() { output += "a" Reset(func() { output += "b" }) }) Reset(func() { output += "2" }) }) expectEqual(t, "2ab2", output) } func TestSkipTopLevel(t *testing.T) { output := prepare() SkipConvey("hi", t, func() { output += "This shouldn't be executed!" }) expectEqual(t, "", output) } func TestSkipNestedLevel(t *testing.T) { output := prepare() Convey("hi", t, func() { output += "yes" SkipConvey("bye", func() { output += "no" }) }) expectEqual(t, "yes", output) } func TestSkipNestedLevelSkipsAllChildLevels(t *testing.T) { output := prepare() Convey("hi", t, func() { output += "yes" SkipConvey("bye", func() { output += "no" Convey("byebye", func() { output += "no-no" }) }) }) expectEqual(t, "yes", output) } func TestIterativeConveys(t *testing.T) { output := prepare() Convey("Test", t, func() { for x := 0; x < 10; x++ { y := strconv.Itoa(x) Convey(y, func() { output += y }) } }) expectEqual(t, "0123456789", output) } func prepare() string { testReporter = execution.NewNilReporter() return "" } goconvey-1.5.0/convey/parsing.go000066400000000000000000000021631227302763300166520ustar00rootroot00000000000000package convey import ( "github.com/smartystreets/goconvey/execution" "github.com/smartystreets/goconvey/gotest" ) func discover(items []interface{}) *execution.Registration { ensureEnough(items) name := parseName(items) test := parseGoTest(items) action := parseAction(items, test) return execution.NewRegistration(name, action, test) } func ensureEnough(items []interface{}) { if len(items) < 2 { panic(parseError) } } func parseName(items []interface{}) string { if name, parsed := items[0].(string); parsed { return name } panic(parseError) } func parseGoTest(items []interface{}) gotest.T { if test, parsed := items[1].(gotest.T); parsed { return test } return nil } func parseAction(items []interface{}, test gotest.T) *execution.Action { var index = 1 if test != nil { index = 2 } if action, parsed := items[index].(func()); parsed { return execution.NewAction(action) } if items[index] == nil { return execution.NewSkippedAction(skipReport) } panic(parseError) } const parseError = "You must provide a name (string), then a *testing.T (if in outermost scope), and then an action (func())." goconvey-1.5.0/convey/reporting_hooks_test.go000066400000000000000000000126071227302763300214660ustar00rootroot00000000000000package convey import ( "fmt" "path" "runtime" "strconv" "strings" "testing" "github.com/smartystreets/goconvey/gotest" "github.com/smartystreets/goconvey/reporting" ) func TestSingleScopeReported(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { So(1, ShouldEqual, 1) }) expectEqual(t, "Begin|A|Success|Exit|End", myReporter.wholeStory()) } func TestNestedScopeReported(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { Convey("B", func() { So(1, ShouldEqual, 1) }) }) expectEqual(t, "Begin|A|B|Success|Exit|Exit|End", myReporter.wholeStory()) } func TestFailureReported(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { So(1, ShouldBeNil) }) expectEqual(t, "Begin|A|Failure|Exit|End", myReporter.wholeStory()) } func TestComparisonFailureDeserializedAndReported(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { So("hi", ShouldEqual, "bye") }) expectEqual(t, "Begin|A|Failure(bye/hi)|Exit|End", myReporter.wholeStory()) } func TestNestedFailureReported(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { Convey("B", func() { So(2, ShouldBeNil) }) }) expectEqual(t, "Begin|A|B|Failure|Exit|Exit|End", myReporter.wholeStory()) } func TestSuccessAndFailureReported(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { So(1, ShouldBeNil) So(nil, ShouldBeNil) }) expectEqual(t, "Begin|A|Failure|Success|Exit|End", myReporter.wholeStory()) } func TestIncompleteActionReportedAsSkipped(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { Convey("B", nil) }) expectEqual(t, "Begin|A|B|Skipped|Exit|Exit|End", myReporter.wholeStory()) } func TestSkippedConveyReportedAsSkipped(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { SkipConvey("B", func() { So(1, ShouldEqual, 1) }) }) expectEqual(t, "Begin|A|B|Skipped|Exit|Exit|End", myReporter.wholeStory()) } func TestMultipleSkipsAreReported(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { Convey("0", func() { So(nil, ShouldBeNil) }) SkipConvey("1", func() {}) SkipConvey("2", func() {}) Convey("3", nil) Convey("4", nil) Convey("5", func() { So(nil, ShouldBeNil) }) }) expected := "Begin" + "|A|0|Success|Exit|Exit" + "|A|1|Skipped|Exit|Exit" + "|A|2|Skipped|Exit|Exit" + "|A|3|Skipped|Exit|Exit" + "|A|4|Skipped|Exit|Exit" + "|A|5|Success|Exit|Exit" + "|End" expectEqual(t, expected, myReporter.wholeStory()) } func TestSkippedAssertionIsNotReported(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { SkipSo(1, ShouldEqual, 1) }) expectEqual(t, "Begin|A|Skipped|Exit|End", myReporter.wholeStory()) } func TestMultipleSkippedAssertionsAreNotReported(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { SkipSo(1, ShouldEqual, 1) So(1, ShouldEqual, 1) SkipSo(1, ShouldEqual, 1) }) expectEqual(t, "Begin|A|Skipped|Success|Skipped|Exit|End", myReporter.wholeStory()) } func TestErrorByManualPanicReported(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { panic("Gopher alert!") }) expectEqual(t, "Begin|A|Error|Exit|End", myReporter.wholeStory()) } func TestIterativeConveysReported(t *testing.T) { myReporter, test := setupFakeReporter() Convey("A", test, func() { for x := 0; x < 3; x++ { Convey(strconv.Itoa(x), func() { So(x, ShouldEqual, x) }) } }) expectEqual(t, "Begin|A|0|Success|Exit|Exit|A|1|Success|Exit|Exit|A|2|Success|Exit|Exit|End", myReporter.wholeStory()) } func expectEqual(t *testing.T, expected interface{}, actual interface{}) { if expected != actual { _, file, line, _ := runtime.Caller(1) t.Errorf("Expected '%v' to be '%v' but it wasn't. See '%s' at line %d.", actual, expected, path.Base(file), line) } } func setupFakeReporter() (*fakeReporter, *fakeGoTest) { myReporter := new(fakeReporter) myReporter.calls = []string{} testReporter = myReporter return myReporter, new(fakeGoTest) } type fakeReporter struct { calls []string } func (self *fakeReporter) BeginStory(story *reporting.StoryReport) { self.calls = append(self.calls, "Begin") } func (self *fakeReporter) Enter(scope *reporting.ScopeReport) { self.calls = append(self.calls, scope.Title) } func (self *fakeReporter) Report(report *reporting.AssertionResult) { if report.Error != nil { self.calls = append(self.calls, "Error") } else if report.Failure != "" { message := "Failure" if report.Expected != "" || report.Actual != "" { message += fmt.Sprintf("(%s/%s)", report.Expected, report.Actual) } self.calls = append(self.calls, message) } else if report.Skipped { self.calls = append(self.calls, "Skipped") } else { self.calls = append(self.calls, "Success") } } func (self *fakeReporter) Exit() { self.calls = append(self.calls, "Exit") } func (self *fakeReporter) EndStory() { self.calls = append(self.calls, "End") } func (self *fakeReporter) wholeStory() string { return strings.Join(self.calls, "|") } //////////////////////////////// type fakeGoTest struct{} func (self *fakeGoTest) Fail() {} func (self *fakeGoTest) Fatalf(format string, args ...interface{}) {} var test gotest.T = &fakeGoTest{} goconvey-1.5.0/convey/story_conventions_test.go000066400000000000000000000051421227302763300220530ustar00rootroot00000000000000package convey import ( "fmt" "strings" "testing" "github.com/smartystreets/goconvey/execution" ) func TestMissingTopLevelGoTestReferenceCausesPanic(t *testing.T) { output := map[string]bool{} defer expectEqual(t, false, output["good"]) defer requireGoTestReference(t) Convey("Hi", func() { output["bad"] = true // this shouldn't happen }) } func requireGoTestReference(t *testing.T) { err := recover() if err == nil { t.Error("We should have recovered a panic here (because of a missing *testing.T reference)!") } else { expectEqual(t, execution.MissingGoTest, err) } } func TestMissingTopLevelGoTestReferenceAfterGoodExample(t *testing.T) { output := map[string]bool{} defer func() { expectEqual(t, true, output["good"]) expectEqual(t, false, output["bad"]) }() defer requireGoTestReference(t) Convey("Good example", t, func() { output["good"] = true }) Convey("Bad example", func() { output["bad"] = true // shouldn't happen }) } func TestExtraReferencePanics(t *testing.T) { output := map[string]bool{} defer func() { err := recover() if err == nil { t.Error("We should have recovered a panic here (because of an extra *testing.T reference)!") } else if !strings.HasPrefix(fmt.Sprintf("%v", err), execution.ExtraGoTest) { t.Error("Should have panicked with the 'extra go test' error!") } if output["bad"] { t.Error("We should NOT have run the bad example!") } }() Convey("Good example", t, func() { Convey("Bad example - passing in *testing.T a second time!", t, func() { output["bad"] = true // shouldn't happen }) }) } func TestParseRegistrationMissingRequiredElements(t *testing.T) { defer func() { if r := recover(); r != nil { if r != "You must provide a name (string), then a *testing.T (if in outermost scope), and then an action (func())." { t.Errorf("Incorrect panic message.") } } }() Convey() t.Errorf("goTest should have panicked in Convey(...) and then recovered in the defer func().") } func TestParseRegistration_MissingNameString(t *testing.T) { defer func() { if r := recover(); r != nil { if r != parseError { t.Errorf("Incorrect panic message.") } } }() action := func() {} Convey(action) t.Errorf("goTest should have panicked in Convey(...) and then recovered in the defer func().") } func TestParseRegistration_MissingActionFunc(t *testing.T) { defer func() { if r := recover(); r != nil { if r != parseError { t.Errorf("Incorrect panic message: '%s'", r) } } }() Convey("Hi there", 12345) t.Errorf("goTest should have panicked in Convey(...) and then recovered in the defer func().") } goconvey-1.5.0/convey/wiring.go000066400000000000000000000023731227302763300165110ustar00rootroot00000000000000package convey import ( "os" "github.com/smartystreets/goconvey/reporting" ) func init() { parseFlags() suites = NewSuiteContext() } // parseFlags parses the command line args manually because the go test tool, // which shares the same process space with this code, already defines // the -v argument (verbosity) and we can't feed in a custom flag to old-style // go test packages (like -json, which I would prefer). So, we use the timeout // flag with a value of -42 to request json output. My deepest sympothies. func parseFlags() { verbose = flagFound(verboseEnabledValue) json = flagFound(jsonEnabledValue) } func flagFound(flagValue string) bool { for _, arg := range os.Args { if arg == flagValue { return true } } return false } func buildReporter() reporting.Reporter { if testReporter != nil { return testReporter } else if json { return reporting.BuildJsonReporter() } else if verbose { return reporting.BuildStoryReporter() } else { return reporting.BuildDotReporter() } } var ( suites *SuiteContext // only set by internal tests testReporter reporting.Reporter ) var ( json bool verbose bool ) const verboseEnabledValue = "-test.v=true" const jsonEnabledValue = "-test.timeout=-42s" // HACK! (see parseFlags() above) goconvey-1.5.0/deps_test.go000066400000000000000000000005341227302763300156760ustar00rootroot00000000000000// The purpose of this file is to make sure the dependencies are pulled in when // `go get -t` is invoked for the first time. Because it is in a *_test.go file // it prevents all of the flags from dependencies from leaking into the goconvey // binary. package main import ( _ "github.com/jacobsa/oglematchers" _ "github.com/jacobsa/ogletest" ) goconvey-1.5.0/examples/000077500000000000000000000000001227302763300151715ustar00rootroot00000000000000goconvey-1.5.0/examples/assertion_examples_test.go000066400000000000000000000061001227302763300224610ustar00rootroot00000000000000package examples import ( "testing" "time" . "github.com/smartystreets/goconvey/convey" ) func TestAssertions(t *testing.T) { Convey("All assertions should be accessible", t, func() { Convey("Equality assertions should be accessible", func() { thing1a := thing{a: "asdf"} thing1b := thing{a: "asdf"} thing2 := thing{a: "qwer"} So(1, ShouldEqual, 1) So(1, ShouldNotEqual, 2) So(1, ShouldAlmostEqual, 1.000000000000001) So(1, ShouldNotAlmostEqual, 2, 0.5) So(thing1a, ShouldResemble, thing1b) So(thing1a, ShouldNotResemble, thing2) So(&thing1a, ShouldPointTo, &thing1a) So(&thing1a, ShouldNotPointTo, &thing1b) So(nil, ShouldBeNil) So(1, ShouldNotBeNil) So(true, ShouldBeTrue) So(false, ShouldBeFalse) So(0, ShouldBeZeroValue) }) Convey("Numeric comparison assertions should be accessible", func() { So(1, ShouldBeGreaterThan, 0) So(1, ShouldBeGreaterThanOrEqualTo, 1) So(1, ShouldBeLessThan, 2) So(1, ShouldBeLessThanOrEqualTo, 1) So(1, ShouldBeBetween, 0, 2) So(1, ShouldNotBeBetween, 2, 4) }) Convey("Container assertions should be accessible", func() { So([]int{1, 2, 3}, ShouldContain, 2) So([]int{1, 2, 3}, ShouldNotContain, 4) So(1, ShouldBeIn, []int{1, 2, 3}) So(4, ShouldNotBeIn, []int{1, 2, 3}) }) Convey("String assertions should be accessible", func() { So("asdf", ShouldStartWith, "a") So("asdf", ShouldNotStartWith, "z") So("asdf", ShouldEndWith, "df") So("asdf", ShouldNotEndWith, "as") So("", ShouldBeBlank) So("asdf", ShouldNotBeBlank) So("asdf", ShouldContainSubstring, "sd") So("asdf", ShouldNotContainSubstring, "af") }) Convey("Panic recovery assertions should be accessible", func() { So(panics, ShouldPanic) So(func() {}, ShouldNotPanic) So(panics, ShouldPanicWith, "Goofy Gophers!") So(panics, ShouldNotPanicWith, "Guileless Gophers!") }) Convey("Type-checking assertions should be accessible", func() { So(1, ShouldHaveSameTypeAs, 0) So(1, ShouldNotHaveSameTypeAs, "1") }) Convey("Time assertions should be accessible", func() { january1, _ := time.Parse(timeLayout, "2013-01-01 00:00") january2, _ := time.Parse(timeLayout, "2013-01-02 00:00") january3, _ := time.Parse(timeLayout, "2013-01-03 00:00") january4, _ := time.Parse(timeLayout, "2013-01-04 00:00") january5, _ := time.Parse(timeLayout, "2013-01-05 00:00") oneDay, _ := time.ParseDuration("24h0m0s") So(january1, ShouldHappenBefore, january4) So(january1, ShouldHappenOnOrBefore, january1) So(january2, ShouldHappenAfter, january1) So(january2, ShouldHappenOnOrAfter, january2) So(january3, ShouldHappenBetween, january2, january5) So(january3, ShouldHappenOnOrBetween, january3, january5) So(january1, ShouldNotHappenOnOrBetween, january2, january5) So(january2, ShouldHappenWithin, oneDay, january3) So(january5, ShouldNotHappenWithin, oneDay, january1) So([]time.Time{january1, january2}, ShouldBeChronological) }) }) } type thing struct { a string } func panics() { panic("Goofy Gophers!") } const timeLayout = "2006-01-02 15:04" goconvey-1.5.0/examples/bowling_game.go000066400000000000000000000020171227302763300201520ustar00rootroot00000000000000package examples type Game struct { rolls []int rollIndex int } func NewGame() *Game { game := Game{} game.rolls = make([]int, 21) return &game } func (self *Game) Roll(pins int) { self.rolls[self.rollIndex] = pins self.rollIndex++ } func (self *Game) Score() int { sum, throw, frame := 0, 0, 0 for ; frame < 10; frame++ { if self.isStrike(throw) { sum += self.strikeBonus(throw) throw += 1 } else if self.isSpare(throw) { sum += self.spareBonus(throw) throw += 2 } else { sum += self.currentFrame(throw) throw += 2 } } return sum } func (self *Game) isStrike(throw int) bool { return self.rolls[throw] == 10 } func (self *Game) isSpare(throw int) bool { return self.rolls[throw]+self.rolls[throw+1] == 10 } func (self *Game) strikeBonus(throw int) int { return 10 + self.rolls[throw+1] + self.rolls[throw+2] } func (self *Game) spareBonus(throw int) int { return 10 + self.rolls[throw+2] } func (self *Game) currentFrame(throw int) int { return self.rolls[throw] + self.rolls[throw+1] } goconvey-1.5.0/examples/bowling_game_test.go000066400000000000000000000034311227302763300212120ustar00rootroot00000000000000/* Reference: http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata See the very first link (which happens to be the very first word of the first paragraph) on the page for a tutorial. */ package examples import ( "testing" . "github.com/smartystreets/goconvey/convey" ) func TestScoring(t *testing.T) { Convey("Subject: Bowling Game Scoring", t, func() { var game *Game // Whatever you do, don't do this: game := NewGame() // Otherwise nested closures won't reference the correct instance Convey("Given a fresh score card", func() { game = NewGame() Convey("When all gutter balls are thrown", func() { game.rollMany(20, 0) Convey("The score should be zero", func() { So(game.Score(), ShouldEqual, 0) }) }) Convey("When all throws knock down only one pin", func() { game.rollMany(20, 1) Convey("The score should be 20", func() { So(game.Score(), ShouldEqual, 20) }) }) Convey("When a spare is thrown", func() { game.rollSpare() game.Roll(3) game.rollMany(17, 0) Convey("The score should include a spare bonus.", func() { So(game.Score(), ShouldEqual, 16) }) }) Convey("When a strike is thrown", func() { game.rollStrike() game.Roll(3) game.Roll(4) game.rollMany(16, 0) Convey("The score should include a strike bonus.", func() { So(game.Score(), ShouldEqual, 24) }) }) Convey("When all strikes are thrown", func() { game.rollMany(21, 10) Convey("The score should be 300.", func() { So(game.Score(), ShouldEqual, 300) }) }) }) }) } func (self *Game) rollMany(times, pins int) { for x := 0; x < times; x++ { self.Roll(pins) } } func (self *Game) rollSpare() { self.Roll(5) self.Roll(5) } func (self *Game) rollStrike() { self.Roll(10) } goconvey-1.5.0/examples/doc.go000066400000000000000000000004701227302763300162660ustar00rootroot00000000000000// Package examples contains, well, examples of how to use goconvey to // specify behavior of a system under test. It contains a well-known example // by Robert C. Martin called "Bowling Game Kata" as well as another very // trivial example that demonstrates Reset() and some of the assertions. package examples goconvey-1.5.0/examples/simple_example_test.go000066400000000000000000000014561227302763300215710ustar00rootroot00000000000000package examples import ( "testing" . "github.com/smartystreets/goconvey/convey" ) func TestSpec(t *testing.T) { Convey("Subject: Integer incrementation and decrementation", t, func() { var x int Convey("Given a starting integer value", func() { x = 42 Convey("When incremented", func() { x++ Convey("The value should be greater by one", func() { So(x, ShouldEqual, 43) }) Convey("The value should NOT be what it used to be", func() { So(x, ShouldNotEqual, 42) }) }) Convey("When decremented", func() { x-- Convey("The value should be lesser by one", func() { So(x, ShouldEqual, 41) }) Convey("The value should NOT be what it used to be", func() { So(x, ShouldNotEqual, 42) }) }) Reset(func() { x = 0 }) }) }) } goconvey-1.5.0/execution/000077500000000000000000000000001227302763300153565ustar00rootroot00000000000000goconvey-1.5.0/execution/action.go000066400000000000000000000011461227302763300171640ustar00rootroot00000000000000package execution import "github.com/smartystreets/goconvey/gotest" func (self *Action) Invoke() { self.action() } type Action struct { action func() name string } func NewAction(action func()) *Action { return &Action{action: action, name: functionName(action)} } func NewSkippedAction(action func()) *Action { self := &Action{} // The choice to use the filename and line number as the action name // reflects the need for something unique but also that corresponds // in a determinist way to the action itself. self.name = gotest.FormatExternalFileAndLine() self.action = action return self } goconvey-1.5.0/execution/doc.go000066400000000000000000000005251227302763300164540ustar00rootroot00000000000000// Package execution contains internal functionality for executing // specifications in an isolated fashion as well as calling reporting // hooks at important points in the process. Although this package has // exported names is not intended for public consumption. See the // examples package for how to use this project. package execution goconvey-1.5.0/execution/nil.go000066400000000000000000000010171227302763300164660ustar00rootroot00000000000000package execution import "github.com/smartystreets/goconvey/reporting" func NewNilReporter() *nilReporter { self := nilReporter{} return &self } func (self *nilReporter) BeginStory(story *reporting.StoryReport) {} func (self *nilReporter) Enter(scope *reporting.ScopeReport) {} func (self *nilReporter) Report(report *reporting.AssertionResult) {} func (self *nilReporter) Exit() {} func (self *nilReporter) EndStory() {} type nilReporter struct{} goconvey-1.5.0/execution/registration.go000066400000000000000000000010371227302763300204200ustar00rootroot00000000000000package execution import "github.com/smartystreets/goconvey/gotest" type Registration struct { Situation string Action *Action Test gotest.T File string Line int } func (self *Registration) IsTopLevel() bool { return self.Test != nil } func NewRegistration(situation string, action *Action, test gotest.T) *Registration { file, line, _ := gotest.ResolveExternalCaller() self := &Registration{} self.Situation = situation self.Action = action self.Test = test self.File = file self.Line = line return self } goconvey-1.5.0/execution/runner.go000066400000000000000000000057521227302763300172270ustar00rootroot00000000000000package execution import ( "fmt" "github.com/smartystreets/goconvey/gotest" "github.com/smartystreets/goconvey/reporting" ) type Runner interface { Begin(entry *Registration) Register(entry *Registration) RegisterReset(action *Action) UpgradeReporter(out reporting.Reporter) Run() } func (self *runner) Begin(entry *Registration) { self.ensureStoryCanBegin() self.out.BeginStory(reporting.NewStoryReport(entry.Test)) self.Register(entry) } func (self *runner) ensureStoryCanBegin() { if self.awaitingNewStory { self.awaitingNewStory = false } else { panic(fmt.Sprintf("%s (See %s)", ExtraGoTest, gotest.FormatExternalFileAndLine())) } } func (self *runner) Register(entry *Registration) { self.ensureStoryAlreadyStarted() parentAction := self.link(entry.Action) parent := self.accessScope(parentAction) child := newScope(entry, self.out) parent.adopt(child) } func (self *runner) ensureStoryAlreadyStarted() { if self.awaitingNewStory { panic(MissingGoTest) } } func (self *runner) link(action *Action) string { _, _, parentAction := gotest.ResolveExternalCaller() childAction := action.name self.linkTo(topLevel, parentAction) self.linkTo(parentAction, childAction) return parentAction } func (self *runner) linkTo(value, name string) { if self.chain[name] == "" { self.chain[name] = value } } func (self *runner) accessScope(current string) *scope { if self.chain[current] == topLevel { return self.top } breadCrumbs := self.trail(current) return self.follow(breadCrumbs) } func (self *runner) trail(start string) []string { breadCrumbs := []string{start, self.chain[start]} for { next := self.chain[last(breadCrumbs)] if next == topLevel { break } else { breadCrumbs = append(breadCrumbs, next) } } return breadCrumbs[:len(breadCrumbs)-1] } func (self *runner) follow(trail []string) *scope { var accessed = self.top for x := len(trail) - 1; x >= 0; x-- { accessed = accessed.children[trail[x]] } return accessed } func (self *runner) RegisterReset(action *Action) { parentAction := self.link(action) parent := self.accessScope(parentAction) parent.registerReset(action) } func (self *runner) Run() { for !self.top.visited() { self.top.visit() } self.out.EndStory() self.awaitingNewStory = true } type runner struct { top *scope chain map[string]string out reporting.Reporter awaitingNewStory bool } func NewRunner() *runner { self := runner{} self.out = NewNilReporter() self.top = newScope(NewRegistration(topLevel, NewAction(func() {}), nil), self.out) self.chain = make(map[string]string) self.awaitingNewStory = true return &self } func (self *runner) UpgradeReporter(out reporting.Reporter) { self.out = out } const topLevel = "TOP" const MissingGoTest = `Top-level calls to Convey(...) need a reference to the *testing.T. Hint: Convey("description here", t, func() { /* notice that the second argument was the *testing.T (t)! */ }) ` const ExtraGoTest = `Only the top-level call to Convey(...) needs a reference to the *testing.T.` goconvey-1.5.0/execution/scope.go000066400000000000000000000041641227302763300170230ustar00rootroot00000000000000package execution import ( "fmt" "strings" "github.com/smartystreets/goconvey/reporting" ) func (parent *scope) adopt(child *scope) { if parent.hasChild(child) { return } parent.birthOrder = append(parent.birthOrder, child) parent.children[child.name] = child } func (parent *scope) hasChild(child *scope) bool { for _, ordered := range parent.birthOrder { if ordered.name == child.name && ordered.title == child.title { return true } } return false } func (self *scope) registerReset(action *Action) { self.resets[action.name] = action } func (self *scope) visited() bool { return self.panicked || self.child >= len(self.birthOrder) } func (parent *scope) visit() { defer parent.exit() parent.enter() parent.action.Invoke() parent.visitChildren() } func (parent *scope) enter() { parent.reporter.Enter(parent.report) } func (parent *scope) visitChildren() { if len(parent.birthOrder) == 0 { parent.cleanup() } else { parent.visitChild() } } func (parent *scope) visitChild() { child := parent.birthOrder[parent.child] child.visit() if child.visited() { parent.cleanup() parent.child++ } } func (parent *scope) cleanup() { for _, reset := range parent.resets { reset.Invoke() } } func (parent *scope) exit() { if problem := recover(); problem != nil { if strings.HasPrefix(fmt.Sprintf("%v", problem), ExtraGoTest) { panic(problem) } parent.panicked = true parent.reporter.Report(reporting.NewErrorReport(problem)) } parent.reporter.Exit() } func newScope(entry *Registration, reporter reporting.Reporter) *scope { self := &scope{} self.reporter = reporter self.name = entry.Action.name self.title = entry.Situation self.action = entry.Action self.children = make(map[string]*scope) self.birthOrder = []*scope{} self.resets = make(map[string]*Action) self.report = reporting.NewScopeReport(self.title, self.name) return self } type scope struct { name string title string action *Action children map[string]*scope birthOrder []*scope child int resets map[string]*Action panicked bool reporter reporting.Reporter report *reporting.ScopeReport } goconvey-1.5.0/execution/utils.go000066400000000000000000000004561227302763300170520ustar00rootroot00000000000000package execution import ( "reflect" "runtime" ) func functionName(action func()) string { return runtime.FuncForPC(functionId(action)).Name() } func functionId(action func()) uintptr { return reflect.ValueOf(action).Pointer() } func last(group []string) string { return group[len(group)-1] } goconvey-1.5.0/goconvey.go000066400000000000000000000063761227302763300155470ustar00rootroot00000000000000// This executable provides an HTTP server that watches for file system changes // to .go files within the working directory (and all nested go packages). // Navigating to the configured host and port will show a web UI showing the // results of running `go test` in each go package. package main import ( "flag" "fmt" "log" "net/http" "os" "path/filepath" "runtime" "time" "github.com/smartystreets/goconvey/web/server/api" "github.com/smartystreets/goconvey/web/server/contract" exec "github.com/smartystreets/goconvey/web/server/executor" parse "github.com/smartystreets/goconvey/web/server/parser" "github.com/smartystreets/goconvey/web/server/system" watch "github.com/smartystreets/goconvey/web/server/watcher" ) func init() { quarterSecond, _ := time.ParseDuration("250ms") flag.IntVar(&port, "port", 8080, "The port at which to serve http.") flag.StringVar(&host, "host", "127.0.0.1", "The host at which to serve http.") flag.DurationVar(&nap, "poll", quarterSecond, "The interval to wait between polling the file system for changes (default: 250ms).") flag.IntVar(&packages, "packages", 10, "The number of packages to test in parallel. Higher == faster but more costly in terms of computing. (default: 10)") flag.StringVar(&gobin, "gobin", "go", "The path to the 'go' binary (default: search on the PATH)") log.SetOutput(os.Stdout) log.SetFlags(log.LstdFlags | log.Lshortfile) } func main() { flag.Parse() log.Printf("Initial configuration: [host: %s] [port: %d] [poll %v]\n", host, port, nap) monitor, server := wireup() go monitor.ScanForever() serveHTTP(server) } func serveHTTP(server contract.Server) { serveStaticResources() serveAjaxMethods(server) activateServer() } func serveStaticResources() { _, file, _, _ := runtime.Caller(0) here := filepath.Dir(file) static := filepath.Join(here, "/web/client") http.Handle("/", http.FileServer(http.Dir(static))) } func serveAjaxMethods(server contract.Server) { http.HandleFunc("/watch", server.Watch) http.HandleFunc("/ignore", server.Ignore) http.HandleFunc("/reinstate", server.Reinstate) http.HandleFunc("/latest", server.Results) http.HandleFunc("/execute", server.Execute) http.HandleFunc("/status", server.Status) http.HandleFunc("/status/poll", server.LongPollStatus) } func activateServer() { log.Printf("Serving HTTP at: http://%s:%d\n", host, port) err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil) if err != nil { fmt.Println(err) } } func wireup() (*contract.Monitor, contract.Server) { log.Println("Constructing components...") working, err := os.Getwd() if err != nil { panic(err) } fs := system.NewFileSystem() shell := system.NewShell(gobin) watcher := watch.NewWatcher(fs, shell) watcher.Adjust(working) parser := parse.NewParser(parse.ParsePackageResults) tester := exec.NewConcurrentTester(shell) tester.SetBatchSize(packages) statusNotif := make(chan bool, 1) executor := exec.NewExecutor(tester, parser, statusNotif) server := api.NewHTTPServer(watcher, executor, statusNotif) scanner := watch.NewScanner(fs, watcher) monitor := contract.NewMonitor(scanner, watcher, executor, server, sleeper) return monitor, server } func sleeper() { time.Sleep(nap) } var ( port int host string gobin string nap time.Duration packages int ) goconvey-1.5.0/gotest/000077500000000000000000000000001227302763300146605ustar00rootroot00000000000000goconvey-1.5.0/gotest/gotest.go000066400000000000000000000006341227302763300165170ustar00rootroot00000000000000// Package gotest contains internal functionality. Although this package // contains one or more exported names it is not intended for public // consumption. See the examples package for how to use this project. package gotest // This interface allows us to pass the *testing.T struct // throughout the internals of this tool without ever // having to import the "testing" package. type T interface { Fail() } goconvey-1.5.0/gotest/utils.go000066400000000000000000000014041227302763300163460ustar00rootroot00000000000000package gotest import ( "fmt" "runtime" "strings" ) func FormatExternalFileAndLine() string { file, line, _ := ResolveExternalCaller() if line == -1 { return "" // panic? } return fmt.Sprintf("%s:%d", file, line) } func ResolveExternalCaller() (file string, line int, name string) { var caller_id uintptr callers := runtime.Callers(0, callStack) for x := 0; x < callers; x++ { caller_id, file, line, _ = runtime.Caller(x) if strings.HasSuffix(file, "test.go") { name = runtime.FuncForPC(caller_id).Name() return } } file, line, name = "", -1, "" return // panic? } const maxStackDepth = 100 // This had better be enough... var callStack []uintptr = make([]uintptr, maxStackDepth, maxStackDepth) goconvey-1.5.0/printing/000077500000000000000000000000001227302763300152055ustar00rootroot00000000000000goconvey-1.5.0/printing/console.go000066400000000000000000000003171227302763300171770ustar00rootroot00000000000000package printing import ( "fmt" "io" ) type console struct{} func (self *console) Write(p []byte) (n int, err error) { return fmt.Print(string(p)) } func NewConsole() io.Writer { return &console{} } goconvey-1.5.0/printing/doc.go000066400000000000000000000003761227302763300163070ustar00rootroot00000000000000// Package printing contains internal functionality related // to console reporting and output. Although this package has // exported names is not intended for public consumption. See the // examples package for how to use this project. package printing goconvey-1.5.0/printing/printer.go000066400000000000000000000021541227302763300172210ustar00rootroot00000000000000package printing import ( "fmt" "io" "strings" ) func (self *Printer) Println(message string, values ...interface{}) { formatted := self.format(message, values...) + newline self.out.Write([]byte(formatted)) } func (self *Printer) Print(message string, values ...interface{}) { formatted := self.format(message, values...) self.out.Write([]byte(formatted)) } func (self *Printer) Insert(text string) { self.out.Write([]byte(text)) } func (self *Printer) format(message string, values ...interface{}) string { formatted := self.prefix + fmt.Sprintf(message, values...) indented := strings.Replace(formatted, newline, newline+self.prefix, -1) return strings.TrimRight(indented, space) } func (self *Printer) Indent() { self.prefix += pad } func (self *Printer) Dedent() { if len(self.prefix) >= padLength { self.prefix = self.prefix[:len(self.prefix)-padLength] } } const newline = "\n" const space = " " const pad = space + space const padLength = len(pad) type Printer struct { out io.Writer prefix string } func NewPrinter(out io.Writer) *Printer { self := Printer{} self.out = out return &self } goconvey-1.5.0/printing/printer_test.go000066400000000000000000000052141227302763300202600ustar00rootroot00000000000000package printing import "testing" func TestPrint(t *testing.T) { file := newMemoryFile() printer := NewPrinter(file) const expected = "Hello, World!" printer.Print(expected) if file.buffer != expected { t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) } } func TestPrintln(t *testing.T) { file := newMemoryFile() printer := NewPrinter(file) const expected = "Hello, World!" printer.Println(expected) if file.buffer != expected+"\n" { t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) } } func TestPrintIndented(t *testing.T) { file := newMemoryFile() printer := NewPrinter(file) const message = "Hello, World!\nGoodbye, World!" const expected = " Hello, World!\n Goodbye, World!" printer.Indent() printer.Print(message) if file.buffer != expected { t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) } } func TestPrintDedented(t *testing.T) { file := newMemoryFile() printer := NewPrinter(file) const expected = "Hello, World!\nGoodbye, World!" printer.Indent() printer.Dedent() printer.Print(expected) if file.buffer != expected { t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) } } func TestPrintlnIndented(t *testing.T) { file := newMemoryFile() printer := NewPrinter(file) const message = "Hello, World!\nGoodbye, World!" const expected = " Hello, World!\n Goodbye, World!\n" printer.Indent() printer.Println(message) if file.buffer != expected { t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) } } func TestPrintlnDedented(t *testing.T) { file := newMemoryFile() printer := NewPrinter(file) const expected = "Hello, World!\nGoodbye, World!" printer.Indent() printer.Dedent() printer.Println(expected) if file.buffer != expected+"\n" { t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) } } func TestDedentTooFarShouldNotPanic(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error("Should not have panicked!") } }() file := newMemoryFile() printer := NewPrinter(file) printer.Dedent() t.Log("Getting to this point without panicking means we passed.") } func TestInsert(t *testing.T) { file := newMemoryFile() printer := NewPrinter(file) printer.Indent() printer.Print("Hi") printer.Insert(" there") printer.Dedent() expected := " Hi there" if file.buffer != expected { t.Errorf("Should have written '%s' but instead wrote '%s'.", expected, file.buffer) } } type memoryFile struct { buffer string } func (self *memoryFile) Write(p []byte) (n int, err error) { self.buffer += string(p) return len(p), nil } func newMemoryFile() *memoryFile { self := memoryFile{} return &self } goconvey-1.5.0/reporting/000077500000000000000000000000001227302763300153645ustar00rootroot00000000000000goconvey-1.5.0/reporting/assertion_report.go000066400000000000000000000052321227302763300213170ustar00rootroot00000000000000package reporting import ( "encoding/json" "fmt" "runtime" "strings" "github.com/smartystreets/goconvey/gotest" ) type FailureView struct { Message string Expected string Actual string } type AssertionResult struct { File string Line int Expected string Actual string Failure string Error interface{} StackTrace string Skipped bool } func NewFailureReport(failure string) *AssertionResult { report := &AssertionResult{} report.File, report.Line = caller() report.StackTrace = stackTrace() parseFailure(failure, report) return report } func parseFailure(failure string, report *AssertionResult) { view := &FailureView{} err := json.Unmarshal([]byte(failure), view) if err == nil { report.Failure = view.Message report.Expected = view.Expected report.Actual = view.Actual } else { report.Failure = failure } } func NewErrorReport(err interface{}) *AssertionResult { report := &AssertionResult{} report.File, report.Line = caller() report.StackTrace = fullStackTrace() report.Error = fmt.Sprintf("%v", err) return report } func NewSuccessReport() *AssertionResult { report := &AssertionResult{} report.File, report.Line = caller() report.StackTrace = fullStackTrace() return report } func NewSkipReport() *AssertionResult { report := &AssertionResult{} report.File, report.Line = caller() report.StackTrace = fullStackTrace() report.Skipped = true return report } func caller() (file string, line int) { file, line, _ = gotest.ResolveExternalCaller() return } func stackTrace() string { buffer := make([]byte, 1024*64) runtime.Stack(buffer, false) formatted := strings.Trim(string(buffer), string([]byte{0})) return removeInternalEntries(formatted) } func fullStackTrace() string { buffer := make([]byte, 1024*64) runtime.Stack(buffer, true) formatted := strings.Trim(string(buffer), string([]byte{0})) return removeInternalEntries(formatted) } func removeInternalEntries(stack string) string { lines := strings.Split(stack, newline) filtered := []string{} for _, line := range lines { if !isExternal(line) { filtered = append(filtered, line) } } return strings.Join(filtered, newline) } func isExternal(line string) bool { for _, p := range internalPackages { if strings.Contains(line, p) { return true } } return false } // NOTE: any new packages that host goconvey packages will need to be added here! // An alternative is to scan the goconvey directory and then exclude stuff like // the examples package but that's nasty too. var internalPackages = []string{ "goconvey/assertions", "goconvey/convey", "goconvey/execution", "goconvey/gotest", "goconvey/printing", "goconvey/reporting", } goconvey-1.5.0/reporting/doc.go000066400000000000000000000004001227302763300164520ustar00rootroot00000000000000// Package reporting contains internal functionality related // to console reporting and output. Although this package has // exported names is not intended for public consumption. See the // examples package for how to use this project. package reporting goconvey-1.5.0/reporting/dot.go000066400000000000000000000014401227302763300165000ustar00rootroot00000000000000package reporting // TODO: Under unit test import ( "fmt" "github.com/smartystreets/goconvey/printing" ) func (self *dot) BeginStory(story *StoryReport) {} func (self *dot) Enter(scope *ScopeReport) {} func (self *dot) Report(report *AssertionResult) { if report.Error != nil { fmt.Print(redColor) self.out.Insert(dotError) } else if report.Failure != "" { fmt.Print(yellowColor) self.out.Insert(dotFailure) } else if report.Skipped { fmt.Print(yellowColor) self.out.Insert(dotSkip) } else { fmt.Print(greenColor) self.out.Insert(dotSuccess) } fmt.Print(resetColor) } func (self *dot) Exit() {} func (self *dot) EndStory() {} func NewDotReporter(out *printing.Printer) *dot { self := dot{} self.out = out return &self } type dot struct { out *printing.Printer } goconvey-1.5.0/reporting/gotest.go000066400000000000000000000011671227302763300172250ustar00rootroot00000000000000package reporting import "github.com/smartystreets/goconvey/gotest" func (self *gotestReporter) BeginStory(story *StoryReport) { self.test = story.Test } func (self *gotestReporter) Enter(scope *ScopeReport) {} func (self *gotestReporter) Report(r *AssertionResult) { if !passed(r) { self.test.Fail() } } func (self *gotestReporter) Exit() {} func (self *gotestReporter) EndStory() { self.test = nil } func NewGoTestReporter() *gotestReporter { self := gotestReporter{} return &self } type gotestReporter struct { test gotest.T } func passed(r *AssertionResult) bool { return r.Error == nil && r.Failure == "" } goconvey-1.5.0/reporting/gotest_test.go000066400000000000000000000026241227302763300202630ustar00rootroot00000000000000package reporting import "testing" func TestReporterReceivesSuccessfulReport(t *testing.T) { reporter := NewGoTestReporter() test := &fakeTest{} reporter.BeginStory(NewStoryReport(test)) reporter.Report(NewSuccessReport()) if test.failed { t.Errorf("Should have have marked test as failed--the report reflected success.") } } func TestReporterReceivesFailureReport(t *testing.T) { reporter := NewGoTestReporter() test := &fakeTest{} reporter.BeginStory(NewStoryReport(test)) reporter.Report(NewFailureReport("This is a failure.")) if !test.failed { t.Errorf("Test should have been marked as failed (but it wasn't).") } } func TestReporterReceivesErrorReport(t *testing.T) { reporter := NewGoTestReporter() test := &fakeTest{} reporter.BeginStory(NewStoryReport(test)) reporter.Report(NewErrorReport("This is an error.")) if !test.failed { t.Errorf("Test should have been marked as failed (but it wasn't).") } } func TestReporterIsResetAtTheEndOfTheStory(t *testing.T) { defer catch(t) reporter := NewGoTestReporter() test := &fakeTest{} reporter.BeginStory(NewStoryReport(test)) reporter.EndStory() reporter.Report(NewSuccessReport()) } func catch(t *testing.T) { if r := recover(); r != nil { t.Log("Getting to this point means we've passed (because we caught a panic appropriately).") } } type fakeTest struct { failed bool } func (self *fakeTest) Fail() { self.failed = true } goconvey-1.5.0/reporting/init.go000066400000000000000000000035531227302763300166640ustar00rootroot00000000000000package reporting import ( "fmt" "os" "strings" "github.com/smartystreets/goconvey/printing" ) func init() { if !isXterm() { monochrome() } if isWindows() { success, failure, error_ = dotSuccess, dotFailure, dotError } } func BuildJsonReporter() Reporter { out := printing.NewPrinter(printing.NewConsole()) return NewReporters( NewGoTestReporter(), NewJsonReporter(out)) } func BuildDotReporter() Reporter { out := printing.NewPrinter(printing.NewConsole()) return NewReporters( NewGoTestReporter(), NewDotReporter(out), NewProblemReporter(out)) } func BuildStoryReporter() Reporter { out := printing.NewPrinter(printing.NewConsole()) return NewReporters( NewGoTestReporter(), NewStoryReporter(out), NewProblemReporter(out)) } var ( newline = "\n" success = "✔" failure = "✘" error_ = "🔥" skip = "⚠" dotSuccess = "." dotFailure = "x" dotError = "E" dotSkip = "S" errorTemplate = "* %s \nLine %d: - %v \n%s\n" failureTemplate = "* %s \nLine %d:\n%s\n" ) var ( greenColor = "\033[32m" yellowColor = "\033[33m" redColor = "\033[31m" resetColor = "\033[0m" ) // QuiteMode disables all console output symbols. This is only meant to be used // for tests that are internal to goconvey where the output is distracting or // otherwise not needed in the test output. func QuietMode() { success, failure, error_, skip, dotSuccess, dotFailure, dotError, dotSkip = "", "", "", "", "", "", "", "" } func monochrome() { greenColor, yellowColor, redColor, resetColor = "", "", "", "" } func isXterm() bool { env := fmt.Sprintf("%v", os.Environ()) return strings.Contains(env, " TERM=isXterm") || strings.Contains(env, " TERM=xterm") } // There has got to be a better way... func isWindows() bool { return os.PathSeparator == '\\' && os.PathListSeparator == ';' } goconvey-1.5.0/reporting/json.go000066400000000000000000000037341227302763300166730ustar00rootroot00000000000000// TODO: under unit test package reporting import ( "bytes" "encoding/json" "strings" "github.com/smartystreets/goconvey/printing" ) func (self *JsonReporter) BeginStory(story *StoryReport) {} func (self *JsonReporter) Enter(scope *ScopeReport) { if _, found := self.index[scope.ID]; !found { self.registerScope(scope) } self.current = self.index[scope.ID] self.depth++ } func (self *JsonReporter) registerScope(scope *ScopeReport) { next := newScopeResult(scope.Title, self.depth, scope.File, scope.Line) self.scopes = append(self.scopes, next) self.index[scope.ID] = next } func (self *JsonReporter) Report(report *AssertionResult) { self.current.Assertions = append(self.current.Assertions, report) } func (self *JsonReporter) Exit() { self.depth-- } func (self *JsonReporter) EndStory() { self.report() self.reset() } func (self *JsonReporter) report() { self.out.Print(OpenJson + "\n") scopes := []string{} for _, scope := range self.scopes { serialized, err := json.Marshal(scope) if err != nil { self.out.Println(jsonMarshalFailure) panic(err) } var buffer bytes.Buffer json.Indent(&buffer, serialized, "", " ") scopes = append(scopes, buffer.String()) } self.out.Print(strings.Join(scopes, ",") + ",\n") self.out.Print(CloseJson + "\n") } func (self *JsonReporter) reset() { self.scopes = []*ScopeResult{} self.index = map[string]*ScopeResult{} self.depth = 0 } func NewJsonReporter(out *printing.Printer) *JsonReporter { self := &JsonReporter{} self.out = out self.reset() return self } type JsonReporter struct { out *printing.Printer current *ScopeResult index map[string]*ScopeResult scopes []*ScopeResult depth int } const OpenJson = ">>>>>" // "⌦" const CloseJson = "<<<<<" // "⌫" const jsonMarshalFailure = ` GOCONVEY_JSON_MARSHALL_FAILURE: There was an error when attempting to convert test results to JSON. Please file a bug report and reference the code that caused this failure if possible. Here's the panic: ` goconvey-1.5.0/reporting/problems.go000066400000000000000000000027611227302763300175440ustar00rootroot00000000000000package reporting import ( "fmt" "github.com/smartystreets/goconvey/printing" ) func (self *problem) BeginStory(story *StoryReport) {} func (self *problem) Enter(scope *ScopeReport) {} func (self *problem) Report(report *AssertionResult) { if report.Error != nil { self.errors = append(self.errors, report) } else if report.Failure != "" { self.failures = append(self.failures, report) } } func (self *problem) Exit() {} func (self *problem) EndStory() { self.show(self.showErrors, redColor) self.show(self.showFailures, yellowColor) self.prepareForNextStory() } func (self *problem) show(display func(), color string) { fmt.Print(color) display() fmt.Print(resetColor) self.out.Dedent() } func (self *problem) showErrors() { for i, e := range self.errors { if i == 0 { self.out.Println("\nErrors:\n") self.out.Indent() } self.out.Println(errorTemplate, e.File, e.Line, e.Error, e.StackTrace) } } func (self *problem) showFailures() { for i, f := range self.failures { if i == 0 { self.out.Println("\nFailures:\n") self.out.Indent() } self.out.Println(failureTemplate, f.File, f.Line, f.Failure) } } func NewProblemReporter(out *printing.Printer) *problem { self := problem{} self.out = out self.prepareForNextStory() return &self } func (self *problem) prepareForNextStory() { self.errors = []*AssertionResult{} self.failures = []*AssertionResult{} } type problem struct { out *printing.Printer errors []*AssertionResult failures []*AssertionResult } goconvey-1.5.0/reporting/reporter.go000066400000000000000000000015021227302763300175530ustar00rootroot00000000000000package reporting type Reporter interface { BeginStory(story *StoryReport) Enter(scope *ScopeReport) Report(r *AssertionResult) Exit() EndStory() } func (self *reporters) BeginStory(story *StoryReport) { for _, r := range self.collection { r.BeginStory(story) } } func (self *reporters) Enter(scope *ScopeReport) { for _, r := range self.collection { r.Enter(scope) } } func (self *reporters) Report(report *AssertionResult) { for _, x := range self.collection { x.Report(report) } } func (self *reporters) Exit() { for _, r := range self.collection { r.Exit() } } func (self *reporters) EndStory() { for _, r := range self.collection { r.EndStory() } } type reporters struct { collection []Reporter } func NewReporters(collection ...Reporter) *reporters { self := reporters{collection} return &self } goconvey-1.5.0/reporting/reporter_test.go000066400000000000000000000025531227302763300206210ustar00rootroot00000000000000package reporting import ( "runtime" "testing" ) func TestEachNestedReporterReceivesTheCallFromTheContainingReporter(t *testing.T) { fake1 := newFakeReporter() fake2 := newFakeReporter() reporter := NewReporters(fake1, fake2) reporter.BeginStory(nil) assertTrue(t, fake1.begun) assertTrue(t, fake2.begun) reporter.Enter(NewScopeReport("scope", "hi")) assertTrue(t, fake1.entered) assertTrue(t, fake2.entered) reporter.Report(NewSuccessReport()) assertTrue(t, fake1.reported) assertTrue(t, fake2.reported) reporter.Exit() assertTrue(t, fake1.exited) assertTrue(t, fake2.exited) reporter.EndStory() assertTrue(t, fake1.ended) assertTrue(t, fake2.ended) } func assertTrue(t *testing.T, value bool) { if !value { _, _, line, _ := runtime.Caller(1) t.Errorf("Value should have been true (but was false). See line %d", line) } } type fakeReporter struct { begun bool entered bool reported bool exited bool ended bool } func newFakeReporter() *fakeReporter { return &fakeReporter{} } func (self *fakeReporter) BeginStory(story *StoryReport) { self.begun = true } func (self *fakeReporter) Enter(scope *ScopeReport) { self.entered = true } func (self *fakeReporter) Report(report *AssertionResult) { self.reported = true } func (self *fakeReporter) Exit() { self.exited = true } func (self *fakeReporter) EndStory() { self.ended = true } goconvey-1.5.0/reporting/scope_report.go000066400000000000000000000006311227302763300204170ustar00rootroot00000000000000package reporting import ( "fmt" "github.com/smartystreets/goconvey/gotest" ) type ScopeReport struct { Title string ID string File string Line int } func NewScopeReport(title, name string) *ScopeReport { file, line, _ := gotest.ResolveExternalCaller() self := &ScopeReport{} self.Title = title self.ID = fmt.Sprintf("%s|%s", title, name) self.File = file self.Line = line return self } goconvey-1.5.0/reporting/scope_result.go000066400000000000000000000006031227302763300204210ustar00rootroot00000000000000package reporting type ScopeResult struct { Title string File string Line int Depth int Assertions []*AssertionResult } func newScopeResult(title string, depth int, file string, line int) *ScopeResult { self := &ScopeResult{} self.Title = title self.Depth = depth self.File = file self.Line = line self.Assertions = []*AssertionResult{} return self } goconvey-1.5.0/reporting/statistics.go000066400000000000000000000030511227302763300201040ustar00rootroot00000000000000package reporting import ( "fmt" "github.com/smartystreets/goconvey/printing" ) func (self *statistics) BeginStory(story *StoryReport) {} func (self *statistics) Enter(scope *ScopeReport) {} func (self *statistics) Report(report *AssertionResult) { if !self.failing && report.Failure != "" { self.failing = true } if !self.erroring && report.Error != nil { self.erroring = true } if report.Skipped { self.skipped += 1 } else { self.total++ } } func (self *statistics) Exit() {} func (self *statistics) EndStory() { self.reportAssertions() self.reportSkippedSections() self.completeReport() } func (self *statistics) reportAssertions() { self.decideColor() self.out.Print("\n%d %s thus far", self.total, plural("assertion", self.total)) } func (self *statistics) decideColor() { if self.failing && !self.erroring { fmt.Print(yellowColor) } else if self.erroring { fmt.Print(redColor) } else { fmt.Print(greenColor) } } func (self *statistics) reportSkippedSections() { if self.skipped > 0 { fmt.Print(yellowColor) self.out.Print(" (one or more sections skipped)") self.skipped = 0 } } func (self *statistics) completeReport() { fmt.Print(resetColor) self.out.Print("\n") self.out.Print("\n") } func NewStatisticsReporter(out *printing.Printer) *statistics { self := statistics{} self.out = out return &self } type statistics struct { out *printing.Printer total int failing bool erroring bool skipped int } func plural(word string, count int) string { if count == 1 { return word } return word + "s" } goconvey-1.5.0/reporting/story.go000066400000000000000000000026751227302763300171050ustar00rootroot00000000000000// TODO: in order for this reporter to be completely honest // we need to retrofit to be more like the json reporter such that: // 1. it maintains ScopeResult collections, which count assertions // 2. it reports only after EndStory(), so that all tick marks // are placed near the appropriate title. // 3. Under unit test package reporting import ( "fmt" "github.com/smartystreets/goconvey/printing" ) func (self *story) BeginStory(story *StoryReport) {} func (self *story) Enter(scope *ScopeReport) { self.out.Indent() if _, found := self.titlesById[scope.ID]; !found { self.out.Println("") self.out.Print(scope.Title) self.out.Insert(" ") self.titlesById[scope.ID] = scope.Title } } func (self *story) Report(report *AssertionResult) { if report.Error != nil { fmt.Print(redColor) self.out.Insert(error_) } else if report.Failure != "" { fmt.Print(yellowColor) self.out.Insert(failure) } else if report.Skipped { fmt.Print(yellowColor) self.out.Insert(skip) } else { fmt.Print(greenColor) self.out.Insert(success) } fmt.Print(resetColor) } func (self *story) Exit() { self.out.Dedent() } func (self *story) EndStory() { self.titlesById = make(map[string]string) self.out.Println("\n") } func NewStoryReporter(out *printing.Printer) *story { self := story{} self.out = out self.titlesById = make(map[string]string) return &self } type story struct { out *printing.Printer titlesById map[string]string } goconvey-1.5.0/reporting/story_report.go000066400000000000000000000013351227302763300204700ustar00rootroot00000000000000package reporting import ( "strings" "github.com/smartystreets/goconvey/gotest" ) type StoryReport struct { Test gotest.T Name string File string Line int } func NewStoryReport(test gotest.T) *StoryReport { file, line, name := gotest.ResolveExternalCaller() name = removePackagePath(name) self := &StoryReport{} self.Test = test self.Name = name self.File = file self.Line = line return self } // name comes in looking like "github.com/smartystreets/goconvey/examples.TestName". // We only want the stuff after the last '.', which is the name of the test function. func removePackagePath(name string) string { parts := strings.Split(name, ".") if len(parts) == 1 { return name } return parts[len(parts)-1] } goconvey-1.5.0/scripts/000077500000000000000000000000001227302763300150425ustar00rootroot00000000000000goconvey-1.5.0/scripts/doc.go000066400000000000000000000003541227302763300161400ustar00rootroot00000000000000// Package scripts contains scripts (pretty unexpected huh?) that // facilitate testing and development. See the project readme for // more information: // https://github.com/smartystreets/goconvey/blob/master/README.md package scripts goconvey-1.5.0/scripts/idle.py000077500000000000000000000066701227302763300163450ustar00rootroot00000000000000#!/usr/bin/env python """ This script scans the current working directory for changes to .go files and runs `go test` in each folder where *_test.go files are found. It does this indefinitely or until a KeyboardInterrupt is raised (). This script passes the verbosity command line argument (-v) to `go test`. """ import os import subprocess import sys import time def main(verbose): working = os.path.abspath(os.path.join(os.getcwd())) scanner = WorkspaceScanner(working) runner = TestRunner(working, verbose) while True: if scanner.scan(): runner.run() class WorkspaceScanner(object): def __init__(self, top): self.state = 0 self.top = top def scan(self): time.sleep(.75) new_state = sum(self._checksums()) if self.state != new_state: self.state = new_state return True return False def _checksums(self): for root, dirs, files in os.walk(self.top): for f in files: if f.endswith('.go'): try: stats = os.stat(os.path.join(root, f)) yield stats.st_mtime + stats.st_size except OSError: pass class TestRunner(object): def __init__(self, top, verbosity): self.repetitions = 0 self.top = top self.working = self.top self.verbosity = verbosity def run(self): self.repetitions += 1 self._display_repetitions_banner() self._run_tests() def _display_repetitions_banner(self): number = ' {} '.format(self.repetitions if self.repetitions % 50 else 'Wow, are you going for a top score? Keep it up!') half_delimiter = (EVEN if not self.repetitions % 2 else ODD) * \ ((80 - len(number)) / 2) write('\n{0}{1}{0}\n'.format(half_delimiter, number)) def _run_tests(self): self._chdir(self.top) if self.tests_found(): self._run_test() for root, dirs, files in os.walk(self.top): self.search_for_tests(root, dirs, files) def search_for_tests(self, root, dirs, files): for d in dirs: if '.git' in d or '.git' in root: continue self._chdir(os.path.join(root, d)) if self.tests_found(): self._run_test() def tests_found(self): for f in os.listdir(self.working): if f.endswith('_test.go'): return True return False def _run_test(self): subprocess.call('go test -i', shell=True) try: output = subprocess.check_output( 'go test ' + self.verbosity, shell=True) self.write_output(output) except subprocess.CalledProcessError as error: self.write_output(error.output) write('\n') def write_output(self, output): write(output) def _chdir(self, new): os.chdir(new) self.working = new def write(value): sys.stdout.write(value) sys.stdout.flush() EVEN = '=' ODD = '-' RESET_COLOR = '\033[0m' RED_COLOR = '\033[31m' YELLOW_COLOR = '\033[33m' GREEN_COLOR = '\033[32m' def parse_bool_arg(name): for arg in sys.argv: if arg == name: return True return False if __name__ == '__main__': verbose = '-v' if parse_bool_arg('-v') else '' main(verbose) goconvey-1.5.0/web/000077500000000000000000000000001227302763300141305ustar00rootroot00000000000000goconvey-1.5.0/web/client/000077500000000000000000000000001227302763300154065ustar00rootroot00000000000000goconvey-1.5.0/web/client/css/000077500000000000000000000000001227302763300161765ustar00rootroot00000000000000goconvey-1.5.0/web/client/css/goconvey.css000066400000000000000000000235331227302763300205470ustar00rootroot00000000000000/* Eric Meyer's Reset CSS v2.0 */ html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}table{border-collapse:collapse;border-spacing:0} ::selection { background: #333; color: #FFF; text-shadow: none; } ::-moz-selection { background: #333; color: #FFF; text-shadow: none; } html, body { color: #333; font-family: 'Open Sans', sans-serif; height: 100%; min-height: 100%; } b { font-weight: bold; } i { font-style: italic; } small { font-size: 12px; line-height: 1.25em; color: #555; } hr { border: 0; height: 1px; background: #CCC; } a { color: #3771C8; font-weight: normal; text-decoration: none; } a:hover { color: #3581F6; text-decoration: underline; } code { font-family: 'Monaco', monospace; line-height: 1.5em; font-size: 10px; white-space: pre-wrap; } table { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; width: 100%; border-collapse: collapse; } header { background: #F2F2F2; padding: .75% 0 .25%; border-bottom: 1px solid #555; } h1 { font: 33px 'Oswald', sans-serif; color: #000; } h1 a { color: inherit; text-decoration: none !important; } input, textarea { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; outline: none; font: 14px 'Open Sans', 'Helvetica Neue', sans-serif; padding: 6px 10px; } textarea { padding: 10px; font: 300 18px/1.5em 'Open Sans', sans-serif; width: 100%; } ul, ol { margin: .75em 0; } ul li { list-style: disc; margin-left: 1.5em; margin-bottom: .5em; } #path { width: 100%; display: block; font-weight: 600; margin-top: 1.5%; padding-left: 2.5em; } .watching-eye { position: absolute; left: 1em; top: .95em; color: #BBB; } a.zen-close { font-size: 24px; } .menu { margin-top: 1.5%; text-align: center; } a.link-fa { color: #444; margin: 0px 10px 0; cursor: pointer; } a.link-fa:hover { color: #000; text-decoration: none; } a.link-fa.clr-red:hover { color: #FF0000 !important; } a.link-fa.disabled { color: #AAA; cursor: default; } #server-down { padding: 10px 0; background: #F7CACA; color: #CC0000; border-bottom: 1px solid #CC0000; } .overall { padding: 10px 0; box-shadow: inset 0 3px 5px -2px rgba(0, 0, 0, .5), inset 0 -3px 8px -3px rgba(0, 0, 0, .35); position: relative; z-index: 50; display: none; } .overall.ok { background: #5AA02C; } .overall.fail { background: #E79C07; } .overall.panic { background: #AA0000; } .overall.buildfail { background: #AAA; } .overall .status { float: left; margin-right: .75em; color: #FFF; font: bold 80px 'Georgia', serif; text-transform: uppercase; } .overall .go-up { display: none; margin-top: .3em; float: right; color: #FFF; } .overall.buildfail .status { font-size: 65px; } .overall .summary { float: left; font: 18px/1.25em monospace; color: rgba(255, 255, 255, .85); margin-top: .5em; } #results { display: none; margin-top: 1.5em; } .toggle { text-decoration: none !important; color: #666 !important; } .toggle-package-shortcuts, .toggle-spacer { padding: 0 5px; display: inline-block; } .goto, .toggle { text-decoration: none !important; color: #666 !important; } .goto:hover, .toggle:hover { color: #000 !important; } .failure-shortcuts, .panic-shortcuts, .builds-shortcuts { margin-bottom: 1em; } .failure-shortcuts a, .panic-shortcuts a, .builds-shortcuts a { line-height: 1.5em; } .failure-shortcuts a { color: #E79C07; } .failure-shortcuts a:hover { color: #FFAD2B; } .panic-shortcuts a { color: #CC0000; } .panic-shortcuts a:hover { color: #FF0000; } .builds-shortcuts a { color: #666; } .builds-shortcuts a:hover { color: #AAA; } .package-shortcut { padding: .15em 0; } .testfunc-list { max-height: 200px; overflow-y: auto; padding-left: .75em; margin-top: .5em; display: none; } .testfunc-list a { display: block; } .failures, .panics, .builds { font-size: 12px; margin-bottom: 2em; } .failures .failure table, .panics .panic table, .builds .build table { margin-bottom: 1em; } .failures .failure table { border: 3px solid #E79C07; } .panics .panic table { border: 3px solid #CC0000; } .builds .build table { border: 3px solid #888; } .file, .line, .panic-error, .stacktrace { font-family: 'Monaco', monospace; font-size: 14px; } .file { line-height: 1em; font-weight: bold; word-break: break-all; } .line { white-space: nowrap; text-align: right; vertical-align: middle; width: 100px; } .expected, .actual, .difference { width: 75px; text-align: left; } .failures .failure th, .failures .failure td, .panics .panic th, .panics .panic td, .builds .build th, .builds .build td { border: 1px solid #CCC; padding: 5px; } .failures .failure th, .panics .panic th { text-transform: uppercase; } .raw-output { padding: 0 !important; } .raw-output code { display: block; max-height: 200px; overflow-y: auto; font-size: 10px; line-height: 1.5em; word-break: break-all; background: #F0F0F0; padding: 5px; } .message { white-space: pre-wrap; word-break: break-all; font: 12px/1.5em 'Monaco', monospace; color: #666; } ins, .failures th.actual { background: #FFC6C6; text-decoration: none; } del, .failures th.expected { background: #C6FFC6; } .package-story { font: 14px 'Open Sans', sans-serif; line-height: 1.75em; width: 100%; margin-bottom: 3em; } .package-story th { text-align: left; padding: 10px; font-size: 16px; background: #EEE; line-height: 1.25em; word-wrap: break-word; font-weight: bold; } .package-story .package-top { position: relative; text-shadow: 1px 1px 1px #FFF; cursor: default; } .package-story td, .package-story th { border: 1px solid #E0E0E0; } .package-story .ignore { float: right; } .package-story .package-header { position: relative; z-index: 1; } .package-story .pkg-summary { padding: 5px 10px; font-size: 12px; background: #F8F8F8; } .package-story .pkg-summary.inverse { background: #333; color: #FFF; } .package-story .status { width: 5px; min-width: 5px; } .package-story .status.ok { background: #A6D37C; } .package-story .status.fail { background: #F7B336; } .package-story .status.panic { background: #FF8585; } .package-story .checks { white-space: nowrap; width: 50px; text-align: center; color: #5AA02C; font-weight: bold; border-right: 0; min-width: 25px; } .package-story .checks .ok { color: #5AA02C; } .package-story .checks .fail { color: #E79C07; } .package-story .checks .panic { color: #AA0000; } .package-story .checks .skip { color: #AAA; } .package-story .title { padding: .75em .5em; line-height: 1.25em; word-break: break-word; } .package-story .title small { white-space: pre-wrap; } .coverage { position: absolute; top: 0; left: 0; height: 100%; width: 5%; z-index: 0; border-bottom-right-radius: 25px; border-top-right-radius: 25px; } .depth-0 .title { padding-left: 1.5em !important; } .depth-1 .title { padding-left: 3em !important; } .depth-2 .title { padding-left: 4.5em !important; } .depth-3 .title { padding-left: 6em !important; } .depth-4 .title { padding-left: 7.5em !important; } .depth-5 .title { padding-left: 9em !important; } .depth-6 .title { padding-left: 10.5em !important; } .depth-7 .title { padding-left: 11em !important; } .sidebar { font: 12px 'Open Sans', sans-serif; margin-bottom: 2em; word-break: break-word; } #loading { text-align: center; text-transform: uppercase; font-size: 35px; font-weight: 300; color: #AAA; padding: 4em 0; } #footer { text-align: center; font-size: 12px; margin-top: 1em; margin-bottom: 4em; color: #888; line-height: 1.5em; } .text-center { text-align: center; } .clr-red { color: #CC0000 !important; } .clr-maroon { color: #7F1502 !important; } #loader { position: fixed; top: 20px; right: 20px; z-index: 99; width: 24px; } .zen { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; display: none; position: fixed; overflow: scroll; height: 100%; width: 100%; padding: 3%; top: 0; left: 0; background: rgba(255, 255, 255, .97); z-index: 51; } .zen h1 { font-size: 56px; text-align: center; } .zen p { margin: 1em 0; line-height: 1.5em; font-size: 20px; font-weight: 300; } .zen-close { position: fixed; top: 3%; right: 5%; z-index: 52; padding: .5em; } #gen-input { margin-bottom: 2em; resize: none; } #gen-output { white-space: pre; font-size: 16px; font-family: 'Monaco', monospace; padding: 10px; color: #333; background: #F0F0F0; display: block; border: 0; resize: vertical; height: 300px; } .stuck { position: fixed; top: 0; width: 100%; background: white; z-index: 48; } .stuck .overall { box-shadow: 0px 1px 3px #333; } .stuck .overall .status { font-size: 22px !important; } .stuck .overall .summary { display: none; } .stuck .overall .go-up { display: block; } @media (max-width: 1024px) { h1 { text-align: center; } .watching-eye { top: .5em; } .package-story th { font-size: 12px; } } @media (max-width: 600px) { .overall .status { font-size: 60px; margin-right: .4em; } .overall .summary { font-size: 14px; } .package-story th, .package-story .title { word-break: break-word; font-size: 12px; } .package-story .title { padding-top: 5px; padding-bottom: 5px; } }goconvey-1.5.0/web/client/css/tipsy.css000066400000000000000000000041651227302763300200660ustar00rootroot00000000000000.tipsy { font-size: 12px; position: absolute; padding: 5px; z-index: 100000; } .tipsy-inner { background-color: #000; color: #FFF; max-width: 200px; padding: 6px 8px 6px 8px; text-align: center; } /* Rounded corners */ .tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; } /* Uncomment for shadow */ /*.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }*/ .tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; } /* Rules to colour arrows */ .tipsy-arrow-n { border-bottom-color: #000; } .tipsy-arrow-s { border-top-color: #000; } .tipsy-arrow-e { border-left-color: #000; } .tipsy-arrow-w { border-right-color: #000; } .tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; } .tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} .tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;} .tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } .tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } .tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; } .tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; } .tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; }goconvey-1.5.0/web/client/css/unsemantic.css000066400000000000000000000465711227302763300210730ustar00rootroot00000000000000/* ================================================================== */ /* This file has a mobile-to-tablet, and tablet-to-desktop breakpoint */ /* ================================================================== */ @media screen and (max-width: 400px) { @-ms-viewport { width: 320px; } } @media screen { .clear { clear: both; display: block; overflow: hidden; visibility: hidden; width: 0; height: 0; } .grid-container:before, .clearfix:before, .grid-container:after, .clearfix:after { content: "."; display: block; overflow: hidden; visibility: hidden; font-size: 0; line-height: 0; width: 0; height: 0; } .grid-container:after, .clearfix:after { clear: both; } .grid-container { margin-left: auto; margin-right: auto; max-width: 1200px; padding-left: 10px; padding-right: 10px; } .grid-5, .mobile-grid-5, .tablet-grid-5, .grid-10, .mobile-grid-10, .tablet-grid-10, .grid-15, .mobile-grid-15, .tablet-grid-15, .grid-20, .mobile-grid-20, .tablet-grid-20, .grid-25, .mobile-grid-25, .tablet-grid-25, .grid-30, .mobile-grid-30, .tablet-grid-30, .grid-35, .mobile-grid-35, .tablet-grid-35, .grid-40, .mobile-grid-40, .tablet-grid-40, .grid-45, .mobile-grid-45, .tablet-grid-45, .grid-50, .mobile-grid-50, .tablet-grid-50, .grid-55, .mobile-grid-55, .tablet-grid-55, .grid-60, .mobile-grid-60, .tablet-grid-60, .grid-65, .mobile-grid-65, .tablet-grid-65, .grid-70, .mobile-grid-70, .tablet-grid-70, .grid-75, .mobile-grid-75, .tablet-grid-75, .grid-80, .mobile-grid-80, .tablet-grid-80, .grid-85, .mobile-grid-85, .tablet-grid-85, .grid-90, .mobile-grid-90, .tablet-grid-90, .grid-95, .mobile-grid-95, .tablet-grid-95, .grid-100, .mobile-grid-100, .tablet-grid-100, .grid-33, .mobile-grid-33, .tablet-grid-33, .grid-66, .mobile-grid-66, .tablet-grid-66 { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding-left: 10px; padding-right: 10px; } .grid-parent { padding-left: 0; padding-right: 0; } body { min-width: 320px; } } @media screen and (max-width: 767px) { .mobile-grid-100:before, .mobile-grid-100:after { content: "."; display: block; overflow: hidden; visibility: hidden; font-size: 0; line-height: 0; width: 0; height: 0; } .mobile-grid-100:after { clear: both; } .mobile-push-5, .mobile-pull-5, .mobile-push-10, .mobile-pull-10, .mobile-push-15, .mobile-pull-15, .mobile-push-20, .mobile-pull-20, .mobile-push-25, .mobile-pull-25, .mobile-push-30, .mobile-pull-30, .mobile-push-35, .mobile-pull-35, .mobile-push-40, .mobile-pull-40, .mobile-push-45, .mobile-pull-45, .mobile-push-50, .mobile-pull-50, .mobile-push-55, .mobile-pull-55, .mobile-push-60, .mobile-pull-60, .mobile-push-65, .mobile-pull-65, .mobile-push-70, .mobile-pull-70, .mobile-push-75, .mobile-pull-75, .mobile-push-80, .mobile-pull-80, .mobile-push-85, .mobile-pull-85, .mobile-push-90, .mobile-pull-90, .mobile-push-95, .mobile-pull-95, .mobile-push-33, .mobile-pull-33, .mobile-push-66, .mobile-pull-66 { position: relative; } .hide-on-mobile { display: none !important; } .mobile-grid-5 { float: left; width: 5%; } .mobile-prefix-5 { margin-left: 5%; } .mobile-suffix-5 { margin-right: 5%; } .mobile-push-5 { left: 5%; } .mobile-pull-5 { left: -5%; } .mobile-grid-10 { float: left; width: 10%; } .mobile-prefix-10 { margin-left: 10%; } .mobile-suffix-10 { margin-right: 10%; } .mobile-push-10 { left: 10%; } .mobile-pull-10 { left: -10%; } .mobile-grid-15 { float: left; width: 15%; } .mobile-prefix-15 { margin-left: 15%; } .mobile-suffix-15 { margin-right: 15%; } .mobile-push-15 { left: 15%; } .mobile-pull-15 { left: -15%; } .mobile-grid-20 { float: left; width: 20%; } .mobile-prefix-20 { margin-left: 20%; } .mobile-suffix-20 { margin-right: 20%; } .mobile-push-20 { left: 20%; } .mobile-pull-20 { left: -20%; } .mobile-grid-25 { float: left; width: 25%; } .mobile-prefix-25 { margin-left: 25%; } .mobile-suffix-25 { margin-right: 25%; } .mobile-push-25 { left: 25%; } .mobile-pull-25 { left: -25%; } .mobile-grid-30 { float: left; width: 30%; } .mobile-prefix-30 { margin-left: 30%; } .mobile-suffix-30 { margin-right: 30%; } .mobile-push-30 { left: 30%; } .mobile-pull-30 { left: -30%; } .mobile-grid-35 { float: left; width: 35%; } .mobile-prefix-35 { margin-left: 35%; } .mobile-suffix-35 { margin-right: 35%; } .mobile-push-35 { left: 35%; } .mobile-pull-35 { left: -35%; } .mobile-grid-40 { float: left; width: 40%; } .mobile-prefix-40 { margin-left: 40%; } .mobile-suffix-40 { margin-right: 40%; } .mobile-push-40 { left: 40%; } .mobile-pull-40 { left: -40%; } .mobile-grid-45 { float: left; width: 45%; } .mobile-prefix-45 { margin-left: 45%; } .mobile-suffix-45 { margin-right: 45%; } .mobile-push-45 { left: 45%; } .mobile-pull-45 { left: -45%; } .mobile-grid-50 { float: left; width: 50%; } .mobile-prefix-50 { margin-left: 50%; } .mobile-suffix-50 { margin-right: 50%; } .mobile-push-50 { left: 50%; } .mobile-pull-50 { left: -50%; } .mobile-grid-55 { float: left; width: 55%; } .mobile-prefix-55 { margin-left: 55%; } .mobile-suffix-55 { margin-right: 55%; } .mobile-push-55 { left: 55%; } .mobile-pull-55 { left: -55%; } .mobile-grid-60 { float: left; width: 60%; } .mobile-prefix-60 { margin-left: 60%; } .mobile-suffix-60 { margin-right: 60%; } .mobile-push-60 { left: 60%; } .mobile-pull-60 { left: -60%; } .mobile-grid-65 { float: left; width: 65%; } .mobile-prefix-65 { margin-left: 65%; } .mobile-suffix-65 { margin-right: 65%; } .mobile-push-65 { left: 65%; } .mobile-pull-65 { left: -65%; } .mobile-grid-70 { float: left; width: 70%; } .mobile-prefix-70 { margin-left: 70%; } .mobile-suffix-70 { margin-right: 70%; } .mobile-push-70 { left: 70%; } .mobile-pull-70 { left: -70%; } .mobile-grid-75 { float: left; width: 75%; } .mobile-prefix-75 { margin-left: 75%; } .mobile-suffix-75 { margin-right: 75%; } .mobile-push-75 { left: 75%; } .mobile-pull-75 { left: -75%; } .mobile-grid-80 { float: left; width: 80%; } .mobile-prefix-80 { margin-left: 80%; } .mobile-suffix-80 { margin-right: 80%; } .mobile-push-80 { left: 80%; } .mobile-pull-80 { left: -80%; } .mobile-grid-85 { float: left; width: 85%; } .mobile-prefix-85 { margin-left: 85%; } .mobile-suffix-85 { margin-right: 85%; } .mobile-push-85 { left: 85%; } .mobile-pull-85 { left: -85%; } .mobile-grid-90 { float: left; width: 90%; } .mobile-prefix-90 { margin-left: 90%; } .mobile-suffix-90 { margin-right: 90%; } .mobile-push-90 { left: 90%; } .mobile-pull-90 { left: -90%; } .mobile-grid-95 { float: left; width: 95%; } .mobile-prefix-95 { margin-left: 95%; } .mobile-suffix-95 { margin-right: 95%; } .mobile-push-95 { left: 95%; } .mobile-pull-95 { left: -95%; } .mobile-grid-33 { float: left; width: 33.33333%; } .mobile-prefix-33 { margin-left: 33.33333%; } .mobile-suffix-33 { margin-right: 33.33333%; } .mobile-push-33 { left: 33.33333%; } .mobile-pull-33 { left: -33.33333%; } .mobile-grid-66 { float: left; width: 66.66667%; } .mobile-prefix-66 { margin-left: 66.66667%; } .mobile-suffix-66 { margin-right: 66.66667%; } .mobile-push-66 { left: 66.66667%; } .mobile-pull-66 { left: -66.66667%; } .mobile-grid-100 { clear: both; width: 100%; } } @media screen and (min-width: 768px) and (max-width: 1024px) { .tablet-grid-100:before, .tablet-grid-100:after { content: "."; display: block; overflow: hidden; visibility: hidden; font-size: 0; line-height: 0; width: 0; height: 0; } .tablet-grid-100:after { clear: both; } .tablet-push-5, .tablet-pull-5, .tablet-push-10, .tablet-pull-10, .tablet-push-15, .tablet-pull-15, .tablet-push-20, .tablet-pull-20, .tablet-push-25, .tablet-pull-25, .tablet-push-30, .tablet-pull-30, .tablet-push-35, .tablet-pull-35, .tablet-push-40, .tablet-pull-40, .tablet-push-45, .tablet-pull-45, .tablet-push-50, .tablet-pull-50, .tablet-push-55, .tablet-pull-55, .tablet-push-60, .tablet-pull-60, .tablet-push-65, .tablet-pull-65, .tablet-push-70, .tablet-pull-70, .tablet-push-75, .tablet-pull-75, .tablet-push-80, .tablet-pull-80, .tablet-push-85, .tablet-pull-85, .tablet-push-90, .tablet-pull-90, .tablet-push-95, .tablet-pull-95, .tablet-push-33, .tablet-pull-33, .tablet-push-66, .tablet-pull-66 { position: relative; } .hide-on-tablet { display: none !important; } .tablet-grid-5 { float: left; width: 5%; } .tablet-prefix-5 { margin-left: 5%; } .tablet-suffix-5 { margin-right: 5%; } .tablet-push-5 { left: 5%; } .tablet-pull-5 { left: -5%; } .tablet-grid-10 { float: left; width: 10%; } .tablet-prefix-10 { margin-left: 10%; } .tablet-suffix-10 { margin-right: 10%; } .tablet-push-10 { left: 10%; } .tablet-pull-10 { left: -10%; } .tablet-grid-15 { float: left; width: 15%; } .tablet-prefix-15 { margin-left: 15%; } .tablet-suffix-15 { margin-right: 15%; } .tablet-push-15 { left: 15%; } .tablet-pull-15 { left: -15%; } .tablet-grid-20 { float: left; width: 20%; } .tablet-prefix-20 { margin-left: 20%; } .tablet-suffix-20 { margin-right: 20%; } .tablet-push-20 { left: 20%; } .tablet-pull-20 { left: -20%; } .tablet-grid-25 { float: left; width: 25%; } .tablet-prefix-25 { margin-left: 25%; } .tablet-suffix-25 { margin-right: 25%; } .tablet-push-25 { left: 25%; } .tablet-pull-25 { left: -25%; } .tablet-grid-30 { float: left; width: 30%; } .tablet-prefix-30 { margin-left: 30%; } .tablet-suffix-30 { margin-right: 30%; } .tablet-push-30 { left: 30%; } .tablet-pull-30 { left: -30%; } .tablet-grid-35 { float: left; width: 35%; } .tablet-prefix-35 { margin-left: 35%; } .tablet-suffix-35 { margin-right: 35%; } .tablet-push-35 { left: 35%; } .tablet-pull-35 { left: -35%; } .tablet-grid-40 { float: left; width: 40%; } .tablet-prefix-40 { margin-left: 40%; } .tablet-suffix-40 { margin-right: 40%; } .tablet-push-40 { left: 40%; } .tablet-pull-40 { left: -40%; } .tablet-grid-45 { float: left; width: 45%; } .tablet-prefix-45 { margin-left: 45%; } .tablet-suffix-45 { margin-right: 45%; } .tablet-push-45 { left: 45%; } .tablet-pull-45 { left: -45%; } .tablet-grid-50 { float: left; width: 50%; } .tablet-prefix-50 { margin-left: 50%; } .tablet-suffix-50 { margin-right: 50%; } .tablet-push-50 { left: 50%; } .tablet-pull-50 { left: -50%; } .tablet-grid-55 { float: left; width: 55%; } .tablet-prefix-55 { margin-left: 55%; } .tablet-suffix-55 { margin-right: 55%; } .tablet-push-55 { left: 55%; } .tablet-pull-55 { left: -55%; } .tablet-grid-60 { float: left; width: 60%; } .tablet-prefix-60 { margin-left: 60%; } .tablet-suffix-60 { margin-right: 60%; } .tablet-push-60 { left: 60%; } .tablet-pull-60 { left: -60%; } .tablet-grid-65 { float: left; width: 65%; } .tablet-prefix-65 { margin-left: 65%; } .tablet-suffix-65 { margin-right: 65%; } .tablet-push-65 { left: 65%; } .tablet-pull-65 { left: -65%; } .tablet-grid-70 { float: left; width: 70%; } .tablet-prefix-70 { margin-left: 70%; } .tablet-suffix-70 { margin-right: 70%; } .tablet-push-70 { left: 70%; } .tablet-pull-70 { left: -70%; } .tablet-grid-75 { float: left; width: 75%; } .tablet-prefix-75 { margin-left: 75%; } .tablet-suffix-75 { margin-right: 75%; } .tablet-push-75 { left: 75%; } .tablet-pull-75 { left: -75%; } .tablet-grid-80 { float: left; width: 80%; } .tablet-prefix-80 { margin-left: 80%; } .tablet-suffix-80 { margin-right: 80%; } .tablet-push-80 { left: 80%; } .tablet-pull-80 { left: -80%; } .tablet-grid-85 { float: left; width: 85%; } .tablet-prefix-85 { margin-left: 85%; } .tablet-suffix-85 { margin-right: 85%; } .tablet-push-85 { left: 85%; } .tablet-pull-85 { left: -85%; } .tablet-grid-90 { float: left; width: 90%; } .tablet-prefix-90 { margin-left: 90%; } .tablet-suffix-90 { margin-right: 90%; } .tablet-push-90 { left: 90%; } .tablet-pull-90 { left: -90%; } .tablet-grid-95 { float: left; width: 95%; } .tablet-prefix-95 { margin-left: 95%; } .tablet-suffix-95 { margin-right: 95%; } .tablet-push-95 { left: 95%; } .tablet-pull-95 { left: -95%; } .tablet-grid-33 { float: left; width: 33.33333%; } .tablet-prefix-33 { margin-left: 33.33333%; } .tablet-suffix-33 { margin-right: 33.33333%; } .tablet-push-33 { left: 33.33333%; } .tablet-pull-33 { left: -33.33333%; } .tablet-grid-66 { float: left; width: 66.66667%; } .tablet-prefix-66 { margin-left: 66.66667%; } .tablet-suffix-66 { margin-right: 66.66667%; } .tablet-push-66 { left: 66.66667%; } .tablet-pull-66 { left: -66.66667%; } .tablet-grid-100 { clear: both; width: 100%; } } @media screen and (min-width: 1025px) { .grid-100:before, .grid-100:after { content: "."; display: block; overflow: hidden; visibility: hidden; font-size: 0; line-height: 0; width: 0; height: 0; } .grid-100:after { clear: both; } .push-5, .pull-5, .push-10, .pull-10, .push-15, .pull-15, .push-20, .pull-20, .push-25, .pull-25, .push-30, .pull-30, .push-35, .pull-35, .push-40, .pull-40, .push-45, .pull-45, .push-50, .pull-50, .push-55, .pull-55, .push-60, .pull-60, .push-65, .pull-65, .push-70, .pull-70, .push-75, .pull-75, .push-80, .pull-80, .push-85, .pull-85, .push-90, .pull-90, .push-95, .pull-95, .push-33, .pull-33, .push-66, .pull-66 { position: relative; } .hide-on-desktop { display: none !important; } .grid-5 { float: left; width: 5%; } .prefix-5 { margin-left: 5%; } .suffix-5 { margin-right: 5%; } .push-5 { left: 5%; } .pull-5 { left: -5%; } .grid-10 { float: left; width: 10%; } .prefix-10 { margin-left: 10%; } .suffix-10 { margin-right: 10%; } .push-10 { left: 10%; } .pull-10 { left: -10%; } .grid-15 { float: left; width: 15%; } .prefix-15 { margin-left: 15%; } .suffix-15 { margin-right: 15%; } .push-15 { left: 15%; } .pull-15 { left: -15%; } .grid-20 { float: left; width: 20%; } .prefix-20 { margin-left: 20%; } .suffix-20 { margin-right: 20%; } .push-20 { left: 20%; } .pull-20 { left: -20%; } .grid-25 { float: left; width: 25%; } .prefix-25 { margin-left: 25%; } .suffix-25 { margin-right: 25%; } .push-25 { left: 25%; } .pull-25 { left: -25%; } .grid-30 { float: left; width: 30%; } .prefix-30 { margin-left: 30%; } .suffix-30 { margin-right: 30%; } .push-30 { left: 30%; } .pull-30 { left: -30%; } .grid-35 { float: left; width: 35%; } .prefix-35 { margin-left: 35%; } .suffix-35 { margin-right: 35%; } .push-35 { left: 35%; } .pull-35 { left: -35%; } .grid-40 { float: left; width: 40%; } .prefix-40 { margin-left: 40%; } .suffix-40 { margin-right: 40%; } .push-40 { left: 40%; } .pull-40 { left: -40%; } .grid-45 { float: left; width: 45%; } .prefix-45 { margin-left: 45%; } .suffix-45 { margin-right: 45%; } .push-45 { left: 45%; } .pull-45 { left: -45%; } .grid-50 { float: left; width: 50%; } .prefix-50 { margin-left: 50%; } .suffix-50 { margin-right: 50%; } .push-50 { left: 50%; } .pull-50 { left: -50%; } .grid-55 { float: left; width: 55%; } .prefix-55 { margin-left: 55%; } .suffix-55 { margin-right: 55%; } .push-55 { left: 55%; } .pull-55 { left: -55%; } .grid-60 { float: left; width: 60%; } .prefix-60 { margin-left: 60%; } .suffix-60 { margin-right: 60%; } .push-60 { left: 60%; } .pull-60 { left: -60%; } .grid-65 { float: left; width: 65%; } .prefix-65 { margin-left: 65%; } .suffix-65 { margin-right: 65%; } .push-65 { left: 65%; } .pull-65 { left: -65%; } .grid-70 { float: left; width: 70%; } .prefix-70 { margin-left: 70%; } .suffix-70 { margin-right: 70%; } .push-70 { left: 70%; } .pull-70 { left: -70%; } .grid-75 { float: left; width: 75%; } .prefix-75 { margin-left: 75%; } .suffix-75 { margin-right: 75%; } .push-75 { left: 75%; } .pull-75 { left: -75%; } .grid-80 { float: left; width: 80%; } .prefix-80 { margin-left: 80%; } .suffix-80 { margin-right: 80%; } .push-80 { left: 80%; } .pull-80 { left: -80%; } .grid-85 { float: left; width: 85%; } .prefix-85 { margin-left: 85%; } .suffix-85 { margin-right: 85%; } .push-85 { left: 85%; } .pull-85 { left: -85%; } .grid-90 { float: left; width: 90%; } .prefix-90 { margin-left: 90%; } .suffix-90 { margin-right: 90%; } .push-90 { left: 90%; } .pull-90 { left: -90%; } .grid-95 { float: left; width: 95%; } .prefix-95 { margin-left: 95%; } .suffix-95 { margin-right: 95%; } .push-95 { left: 95%; } .pull-95 { left: -95%; } .grid-33 { float: left; width: 33.33333%; } .prefix-33 { margin-left: 33.33333%; } .suffix-33 { margin-right: 33.33333%; } .push-33 { left: 33.33333%; } .pull-33 { left: -33.33333%; } .grid-66 { float: left; width: 66.66667%; } .prefix-66 { margin-left: 66.66667%; } .suffix-66 { margin-right: 66.66667%; } .push-66 { left: 66.66667%; } .pull-66 { left: -66.66667%; } .grid-100 { clear: both; width: 100%; } } goconvey-1.5.0/web/client/favicon.ico000066400000000000000000000353561227302763300175430ustar00rootroot00000000000000 h6  00 %F(   /0 }} /. /T2V$e3//}Sz}/q:SIES P@FS P@NNF@oH!7Ol$0}b}0.=r. /&. }} /0 D@@G |( @  WW $nK::Kn$ GG #CC#/ /##    wx $CD$_C3.5M GgG(E WH~4W#3p03nK7Qhr3J:83::8ye|5:K8`P1Jp8!_>n6W+:vu W GIdE y9$Cw ,D$ ^ j #GQ:#/ 0#DD# EE $nJ::Jn$ WW ?`#`@8BxB8xB8xB8`B8`B8`B888<x`8x8?(0` $ #WW#klI))I t%%t -vv-O OjkijjDCkO;<O-DD- kS>MPH Aym+k t Z& t U!v0v41d k!E~k%A7( "# _B!#W( 9FWJ>*FH*JF(Q(((>FT)FT+FT%?#T 4, TV*T0s(JTcHWP sW#ET _#%/`;QL/ "l r~l=bv&v '#!t}@t i |i -ChSB-O<3dyya/9OjDBkkkikO!!O-vv- t~$"~t H((Hkl#WW#??<800 @ `q p x x x x x x? |? | `x`xx|Àx??goconvey-1.5.0/web/client/ico/000077500000000000000000000000001227302763300161605ustar00rootroot00000000000000goconvey-1.5.0/web/client/ico/goconvey-buildfail.ico000066400000000000000000000353561227302763300224520ustar00rootroot00000000000000 h6  00 %F(   0تت0 00تتتت00 0تت0( @  XǪ骪骪ǪX $$ #ѪѪ#0說說0#說說# ѪѪ $$ XXǪǪ骪骪骪骪ǪǪXX $$ ѪѪ #說說#0說說0#ѪѪ# $$ XǪ骪骪ǪX ??(0` $ #Xڪ몪몪ڪX#mƪ񪪪񪪪ƪm몪몪 t󪪪󪪪t -ŪŪ-O쪪쪪OkkkkOO-쪪쪪- ŪŪ tt󪪪󪪪몪몪mmƪƪ#񪪪񪪪#XXڪڪ몪몪몪몪ڪڪXX#񪪪񪪪#ƪƪmm몪몪󪪪󪪪tt ŪŪ -쪪쪪-OOkkkkO쪪쪪O-ŪŪ- t󪪪󪪪t 몪몪mƪ񪪪񪪪ƪm#Xڪ몪몪ڪX#????goconvey-1.5.0/web/client/ico/goconvey-fail.ico000066400000000000000000000353561227302763300214320ustar00rootroot00000000000000 h6  00 %F(   00    0000    00( @   XX $$  ##00##  $$  XXXX  $$  ##00##  $$ XX ??(0` $ #XX#mm tt --OOkkkkOO--  ttmm##XXXX##mmtt  --OOkkkkOO-- tt mm#XX#????goconvey-1.5.0/web/client/ico/goconvey-ok.ico000066400000000000000000000353561227302763300211300ustar00rootroot00000000000000 h6  00 %F(   ,Z0,Z,Z,Z,Z,Z,Z,Z0,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z0,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z0,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z0,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z0,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z0,Z,Z,Z,Z,Z,Z,Z0( @  ,Z ,ZX,Z,Z,Z,Z,Z,Z,Z,Z,ZX,Z ,Z$,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z$,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z#,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z#,Z0,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z0,Z#,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z#,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z$,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z$,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,ZX,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,ZX,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,ZX,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,ZX,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z$,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z$,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z#,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z#,Z0,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z0,Z#,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z#,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z$,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z$,Z ,ZX,Z,Z,Z,Z,Z,Z,Z,Z,ZX,Z ??(0` $ ,Z,Z#,ZX,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,ZX,Z#,Z,Z,Z,Zm,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zm,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Zt,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zt,Z ,Z-,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z-,Z,ZO,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,ZO,Z,Z,Zk,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zk,Z,Z,Zk,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zk,Z,ZO,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,ZO,Z-,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z-,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Zt,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zt,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zm,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zm,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z#,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z#,ZX,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,ZX,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,ZX,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,ZX,Z#,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z#,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zm,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zm,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zt,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zt,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z ,Z-,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z-,ZO,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,ZO,Z,Zk,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zk,Z,Z,Zk,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zk,Z,Z,ZO,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,ZO,Z,Z-,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z-,Z ,Zt,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zt,Z ,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zm,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Zm,Z,Z,Z,Z#,ZX,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,ZX,Z#,Z????goconvey-1.5.0/web/client/ico/goconvey-panic.ico000066400000000000000000000353561227302763300216110ustar00rootroot00000000000000 h6  00 %F(   00 0000 00( @  XX $$ ##00## $$ XXXX $$ ##00## $$ XX ??(0` $ #XX#mm tt --OOkkkkOO-- ttmm##XXXX##mmtt --OOkkkkOO-- tt mm#XX#????goconvey-1.5.0/web/client/index.html000066400000000000000000000352061227302763300174110ustar00rootroot00000000000000 GoConvey

GoConvey Generator

Tell your program's story. Write one-line behavioral comments to create a BDD test structure. Use tab indentation to define scopes. Your test file will be automatically stubbed out for you.   [See an example]

Processing goconvey-1.5.0/web/client/js/000077500000000000000000000000001227302763300160225ustar00rootroot00000000000000goconvey-1.5.0/web/client/js/diff-match-patch.min.js000066400000000000000000000453671227302763300222600ustar00rootroot00000000000000(function(){function diff_match_patch(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=0.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=0.5;this.Patch_Margin=4;this.Match_MaxBits=32} diff_match_patch.prototype.diff_main=function(a,b,c,d){"undefined"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error("Null input. (diff_main)");if(a==b)return a?[[0,a]]:[];"undefined"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b);c=a.substring(0,f);a=a.substring(f);b=b.substring(f);var f=this.diff_commonSuffix(a,b),g=a.substring(a.length-f);a=a.substring(0,a.length-f);b=b.substring(0,b.length-f);a=this.diff_compute_(a, b,e,d);c&&a.unshift([0,c]);g&&a.push([0,g]);this.diff_cleanupMerge(a);return a}; diff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[1,b]];if(!b)return[[-1,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);return-1!=g?(c=[[1,e.substring(0,g)],[0,f],[1,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=-1),c):1==f.length?[[-1,a],[1,b]]:(e=this.diff_halfMatch_(a,b))?(f=e[0],a=e[1],g=e[2],b=e[3],e=e[4],f=this.diff_main(f,g,c,d),c=this.diff_main(a,b,c,d),f.concat([[0,e]],c)):c&&100c);v++){for(var n=-v+r;n<=v-t;n+=2){var l=g+n,m;m=n==-v||n!=v&&j[l-1]d)t+=2;else if(s>e)r+=2;else if(q&&(l=g+k-n,0<=l&&l= u)return this.diff_bisectSplit_(a,b,m,s,c)}}for(n=-v+p;n<=v-w;n+=2){l=g+n;u=n==-v||n!=v&&i[l-1]d)w+=2;else if(m>e)p+=2;else if(!q&&(l=g+k-n,0<=l&&(l=u)))return this.diff_bisectSplit_(a,b,m,s,c)}}return[[-1,a],[1,b]]}; diff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d);a=a.substring(c);b=b.substring(d);f=this.diff_main(f,g,!1,e);e=this.diff_main(a,b,!1,e);return f.concat(e)}; diff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b="",c=0,f=-1,g=d.length;fd?a=a.substring(c-d):c=a.length?[h,j,n,l,g]:null}if(0>=this.Diff_Timeout)return null; var d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.lengthd[4].length?g:d:d:g;var j;a.length>b.length?(g=h[0],d=h[1],e=h[2],j=h[3]):(e=h[0],j=h[1],g=h[2],d=h[3]);h=h[4];return[g,d,e,j,h]}; diff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,j=0,i=0;f=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[0,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[0,b.substring(0,e)]),a[f-1][0]=1,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=-1,a[f+1][1]=b.substring(e),f++;f++}f++}}; diff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_),c=g&&c.match(diff_match_patch.linebreakRegex_),d=h&&d.match(diff_match_patch.linebreakRegex_),i=c&&a.match(diff_match_patch.blanklineEndRegex_),j=d&&b.match(diff_match_patch.blanklineStartRegex_); return i||j?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c=i&&(i=k,g=d,h=e,j=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-1,1),c--),a[c][1]= h,j?a[c+1][1]=j:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\s/;diff_match_patch.linebreakRegex_=/[\r\n]/;diff_match_patch.blanklineEndRegex_=/\n\r?\n$/;diff_match_patch.blanklineStartRegex_=/^\r?\n\r?\n/; diff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,j=!1,i=!1;fb)break;e=c;f=d}return a.length!=g&&-1===a[g][0]?f:f+(b-e)}; diff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=//g,f=/\n/g,g=0;g");switch(h){case 1:b[g]=''+j+"";break;case -1:b[g]=''+j+"";break;case 0:b[g]=""+j+""}}return b.join("")}; diff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;cthis.Match_MaxBits)throw Error("Pattern too long for this browser.");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));for(var j=1<=i;p--){var w=e[a.charAt(p-1)];k[p]=0===t?(k[p+1]<<1|1)&w:(k[p+1]<<1|1)&w|((r[p+1]|r[p])<<1|1)|r[p+1];if(k[p]&j&&(w=d(t,p-1),w<=g))if(g=w,h=p-1,h>c)i=Math.max(1,2*c-h);else break}if(d(t+1,c)>g)break;r=k}return h}; diff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c=2*this.Patch_Margin&& e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}1!==i&&(f+=k.length);-1!==i&&(g+=k.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;cthis.Match_MaxBits){if(j=this.match_main(b,h.substring(0,this.Match_MaxBits),g),-1!=j&&(i=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==i||j>=i))j=-1}else j=this.match_main(b,h,g); if(-1==j)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=j-g,g=-1==i?b.substring(j,j+h.length):b.substring(j,i+this.Match_MaxBits),h==g)b=b.substring(0,j)+this.diff_text2(a[f].diffs)+b.substring(j+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);for(var h=0,k,i=0;ie[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;0==e.length||0!=e[e.length-1][0]?(e.push([0, c]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c}; diff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c2*b?(h.length1+=i.length,e+=i.length,j=!1,h.diffs.push([g,i]),d.diffs.shift()):(i=i.substring(0,b-h.length1-this.Patch_Margin),h.length1+=i.length,e+=i.length,0===g?(h.length2+=i.length,f+=i.length):j=!1,h.diffs.push([g,i]),i==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(i.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);i=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);""!==i&& (h.length1+=i.length,h.length2+=i.length,0!==h.diffs.length&&0===h.diffs[h.diffs.length-1][0]?h.diffs[h.diffs.length-1][1]+=i:h.diffs.push([0,i]));j||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c 20) return "Wait! You still have test cases in the GoConvey generator!"; }; $('#gen-input').keydown(function(e) { var rows = parseInt($(this).attr('rows')); if (e.keyCode == 13) // Enter { lastKeyWasEnter = true; $(this).attr('rows', Math.min(rows + 1, maxRows)); } else lastKeyWasEnter = false; }).keyup(function(e) { if (lastKeyWasEnter) return; if (e.keyCode == 13) { var rows = parseInt($(this).attr('rows')); $(this).attr('rows', Math.min(rows + 1, maxRows)); } else { var newlines = $(this).val().match(/\n/g) || []; $(this).attr('rows', Math.min(newlines.length + 1, maxRows)); } generate($(this).val()); }); gen.template = $('#tpl-convey').text(); // Inserts a sample $('#gen-sample').click(function() { if ($('#gen-input').val().length > 10) { if (!confirm("This will clear your story. Continue?")) return false; } $('#gen-input').val('TestWhatGoConveyCanDo\n\tThe first line can be your "go test" function name\n\tIndented lines are tests to be wrapped in Convey()\n\t\tYou can--and should--nest your statements like this\n\t\tYou can fill out the details later.\n\tJust type away!').keyup(); }); var betterTextArea = new EnhancedTextArea('gen-input'); // Original from: http://potch.me/projects/textarea // with fixes by yours truly function EnhancedTextArea(id, tab) { var el = document.getElementById(id); tabText = tab ? tab : "\t"; el.onkeydown = function(e) { if (e.keyCode == 9) { var ta = el; var val = ta.value; var ss = ta.selectionStart; var nv = val.substring(0,ss) + tabText + val.substring(ss); ta.value = nv; ta.selectionStart = ss + tabText.length; ta.selectionEnd = ss + tabText.length; suppress(e); } if (e.keyCode == 13) { var ta = el; var val = ta.value; var ss = ta.selectionStart; var bl = val.lastIndexOf("\n",ss-1); var line = val.substring(bl,ss); var lm = line.match(/^\s+/); var ns = lm ? lm[0].length-1 : 0; var nv = val.substring(0,ss) + "\n"; for (var i=0; i 0; j++) { curScope = curScope.stories[curScope.stories.length - 1]; prevScope = curScope; } // Don't go crazy, though! (avoid excessive indentation) if (tabs > curScope.depth + 1) tabs = curScope.depth + 1; // Only top-level Convey() calls need the *testing.T object passed in var showT = convey.zen.gen.isFunc(prevScope) || (!convey.zen.gen.isFunc(curScope) && tabs == 0); // Save the story at this scope curScope.stories.push({ title: lineText.replace(/"/g, "\\\""), // escape quotes stories: [], depth: tabs, showT: showT }); } return root; }goconvey-1.5.0/web/client/js/goconvey.js000066400000000000000000000441601227302763300202160ustar00rootroot00000000000000// Let's keep things out of global/window scope var convey = { speed: 'fast', statuses: { pass: 'ok', fail: 'fail', panic: 'panic', failedBuild: 'buildfail', skip: 'skip', ignored: 'ignored' }, timeout: 60000 * 2, // Major 'GOTCHA': should be LONGER than server's timeout! serverStatus: "", serverUp: true, lastScrollPos: 0, payload: {}, assertions: emptyAssertions(), failedBuilds: [], overall: emptyOverall(), zen: {}, revisionHash: "" }; $(initPage); function initPage() { initPlugins(); // Focus on first textbox if ($('input').first().val() == "") $('input').first().focus(); // Show/hide notifications if (notif()) $('#toggle-notif').removeClass('fa-bell-o').addClass('fa-bell'); // Find out what the server is watching, and by passing in true, tell the // server we're a new client (I'm pretty sure only 1 client is supported right now). updateWatchPath(true); // Poll for latest status and ask for current test results, if any initPoller(); update(); // Smooth scroll within page (props to css-tricks.com) $('body').on('click', 'a[href^=#]:not([href=#])', function() { if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') || location.hostname == this.hostname) { var target = $(this.hash); target = target.length ? target : $('[name=' + this.hash.slice(1) +']'); if (target.length) { $('html, body').animate({ scrollTop: target.offset().top - 150 }, 400); return suppress(event); } } }).on('click', 'a[href=#]', function(event) { $('html, body').animate({ scrollTop: 0 }, 400); return suppress(event); }); initHandlers(); } function initPlugins() { // JQUERY WAYPOINTS PLUGIN // Make certain elements stick to the top of the screen when scrolling down $('#banners').waypoint('sticky').waypoint(function(direction) { if (direction == "down") bannerClickToTop(true); else if (direction == "up" && $('.overall').parent('a.to-top').length > 0) bannerClickToTop(false); }); // MARKUP.JS // Custom pipes Mark.pipes.relativePath = function(str) { basePath = new RegExp($('#path').val(), 'g'); return str.replace(basePath, ''); }; Mark.pipes.showhtml = function(str) { return str.replace(//g, ">"); }; Mark.pipes.nothing = function(str) { return str == "no test files" || str == "no test functions" || str == "no go code" }; Mark.pipes.boldPkgName = function(str) { var pkg = splitPathName(str); pkg.parts[pkg.parts.length - 1] = "" + pkg.parts[pkg.parts.length - 1] + ""; return pkg.parts.join(pkg.delim); }; Mark.pipes.chopEnd = function(str, n) { return str.length > n ? "..." + str.substr(str.length - n) : str; }; Mark.pipes.needsDiff = function(test) { return !!test.Failure && (test.Expected != "" || test.Actual != ""); }; Mark.pipes.coverageWidth = function(str) { // We expect 75% to be represented as: "75.0" var num = parseInt(str); // we only need int precision if (num < 0) return "0"; else if (num <= 5) return "25px"; // Still shows low coverage (borders are rounded) else if (num > 100) str = "100"; return str + "%"; }; Mark.pipes.coverageColor = function(str) { var num = parseInt(str); // we only need int precision if (num < 0) return "none"; else if (num > 100) num = 100; return coverageToColor(num); }; Mark.pipes.coverageDisplay = function(str) { var num = parseFloat(str); return num < 0 ? "" : num + "% coverage"; } // JQUERY TIPSY // Wire-up nice tooltips $('a, #path, .package-top').tipsy({ live: true }); } function initPoller() { $.ajax({ url: "/status/poll", timeout: convey.timeout }).done(updateStatus).fail(statusFailed); } function initHandlers() { // Runs tests manually $('#run-tests').click(function() { if (!$(this).hasClass('disabled')) { $.get("/execute"); } }); // Turns notifications on/off $('#toggle-notif').click(function() { $(this).toggleClass('fa-bell').toggleClass('fa-bell-o'); // Save updated preference for future loads localStorage.setItem('notifications', !notif()); if (notif() && 'Notification' in window) { if (Notification.permission !== 'denied') { Notification.requestPermission(function(per) { if (!('permission' in Notification)) // help Chrome out a bit Notification.permission = per; }); } } }); // Shows code generator $('#show-gen').click(function() { $('#generator').fadeIn(convey.speed, function() { $('#gen-input').focus(); generate($('#gen-input').val()); }); }); // Hides code generator (or any 'zen'-like window) $('.zen-close').click(function() { $('.zen').fadeOut(convey.speed); }); // TOGGLERS // Toggles a toggle's icon $('body').on('click', '.toggle', function() { $('.fa', this).toggleClass('fa-collapse-o').toggleClass('fa-expand-o'); }); // Package/testfunc lists $('body').on('click', '.toggle-package-shortcuts', function() { $(this).next('a').next('.testfunc-list').toggle(65); }); // Package stories $('body').on('click', '.toggle-package-stories', function() { $(this).closest('tr').siblings().toggle(); }); // Unwatch (ignore) a package $('body').on('click', '.ignore', function() { if ($(this).hasClass('disabled')) return; else if ($(this).hasClass('unwatch')) $.get("/ignore", { path: $(this).data("pkg") }); else $.get("/reinstate", { path: $(this).data("pkg") }); $(this).toggleClass('watch') .toggleClass('unwatch') .toggleClass('fa-eye') .toggleClass('fa-eye-slash') .toggleClass('clr-red'); }); // END TOGGLERS // Updates the watched directory with the server and make sure it exists $('#path').change(function() { var self = $(this) $.post('/watch?root='+encodeURIComponent($.trim($(this).val()))) .done(function() { self.css('color', ''); }) .fail(function() { self.css('color', '#DD0000'); }); }); } function updateWatchPath(newClient) { var endpoint = "/watch"; if (newClient) endpoint += "?newclient=1"; $.get(endpoint, function(data) { $('#path').val($.trim(data)); }); } function update() { // Save this so we can revert to the same place we were before the update convey.lastScrollPos = $(document).scrollTop(); $.getJSON("/latest", function(data, status, jqxhr) { if (!data || !data.Revision) return showServerDown(jqxhr, "starting"); else $('#server-down').slideUp(convey.speed); if (data.Revision == convey.revisionHash) return; convey.revisionHash = data.Revision; convey.payload = data; updateWatchPath(); // Empty out the data from the last update convey.overall = emptyOverall(); convey.assertions = emptyAssertions(); convey.failedBuilds = []; // Force page height to help smooth out the transition $('html,body').css('height', $(document).outerHeight()); // Remove existing/old test results $('.overall').slideUp(convey.speed); $('#results').fadeOut(convey.speed, function() { // Remove all templated items from the DOM as we'll // replace them with new ones; also remove tipsy tooltips // that may have lingered around $('.templated, .tipsy').remove(); var uniqueID = 0; // Look for failures and panics through the packages->tests->stories... for (var i in data.Packages) { pkg = makeContext(data.Packages[i]); convey.overall.duration += pkg.Elapsed; pkg._id = uniqueID++; if (pkg.Outcome == "build failure") { convey.overall.failedBuilds ++; convey.failedBuilds.push(pkg); continue; } for (var j in pkg.TestResults) { test = makeContext(pkg.TestResults[j]); test._id = uniqueID; uniqueID ++; if (test.Stories.length == 0) { // Here we've got ourselves a classic Go test, // not a GoConvey test that has stories and assertions // so we'll treat this whole test as a single assertion convey.overall.assertions ++; if (test.Error) { test._status = convey.statuses.panic; pkg._panicked ++; test._panicked ++; convey.assertions.panicked.push(test); } else if (test.Passed === false) { test._status = convey.statuses.fail; pkg._failed ++; test._failed ++; convey.assertions.failed.push(test); } else { test._status = convey.statuses.pass; pkg._passed ++; test._passed ++; convey.assertions.passed.push(test); } } else test._status = convey.statuses.pass; var storyPath = [{ Depth: -1, Title: test.TestName }]; // Will maintain the current assertion's path for (var k in test.Stories) { var story = makeContext(test.Stories[k]); // Establish the current story path so we can report the context // of failures and panicks more conveniently at the top of the page if (storyPath.length > 0) for (var x = storyPath[storyPath.length - 1].Depth; x >= test.Stories[k].Depth; x--) storyPath.pop(); storyPath.push({ Depth: test.Stories[k].Depth, Title: test.Stories[k].Title }); story._id = uniqueID; convey.overall.assertions += story.Assertions.length; for (var l in story.Assertions) { var assertion = story.Assertions[l]; assertion._id = uniqueID; $.extend(assertion._path = [], storyPath); if (assertion.Failure) { convey.assertions.failed.push(assertion); pkg._failed ++; test._failed ++; story._failed ++; } if (assertion.Error) { convey.assertions.panicked.push(assertion); pkg._panicked ++; test._panicked ++; story._panicked ++; } if (assertion.Skipped) { convey.assertions.skipped.push(assertion); pkg._skipped ++; test._skipped ++; story._skipped ++; } if (!assertion.Failure && !assertion.Error && !assertion.Skipped) { convey.assertions.passed.push(assertion); pkg._passed ++; test._passed ++; story._passed ++; } } assignStatus(story); uniqueID ++; } } } convey.overall.passed = convey.assertions.passed.length; convey.overall.panics = convey.assertions.panicked.length; convey.overall.failures = convey.assertions.failed.length; convey.overall.skipped = convey.assertions.skipped.length; convey.overall.duration = Math.round(convey.overall.duration * 1000) / 1000; // Build failures trump panics, // Panics trump failures, // Failures trump passing. if (convey.overall.failedBuilds) convey.overall.status = convey.statuses.failedBuild; else if (convey.overall.panics) convey.overall.status = convey.statuses.panic; else if (convey.overall.failures) convey.overall.status = convey.statuses.fail; // Show the overall status: passed, failed, or panicked if (convey.overall.status == convey.statuses.pass) $('#banners').append(render('tpl-overall-ok', convey.overall)); else if (convey.overall.status == convey.statuses.fail) $('#banners').append(render('tpl-overall-fail', convey.overall)); else if (convey.overall.status == convey.statuses.panic) $('#banners').append(render('tpl-overall-panic', convey.overall)); else $('#banners').append(render('tpl-overall-buildfail', convey.overall)); // Show overall status $('.overall').slideDown(); $('.favicon').attr('href', '/ico/goconvey-'+convey.overall.status+'.ico'); // Show shortucts and builds/failures/panics details if (convey.overall.failedBuilds > 0) { $('#right-sidebar').append(render('tpl-builds-shortcuts', convey.failedBuilds)); $('#contents').append(render('tpl-builds', convey.failedBuilds)); } if (convey.overall.panics > 0) { $('#right-sidebar').append(render('tpl-panic-shortcuts', convey.assertions.panicked)); $('#contents').append(render('tpl-panics', convey.assertions.panicked)); } if (convey.overall.failures > 0) { $('#right-sidebar').append(render('tpl-failure-shortcuts', convey.assertions.failed)); $('#contents').append(render('tpl-failures', convey.assertions.failed)); } // Show stories $('#contents').append(render('tpl-stories', data)); // Show shortcut links to packages $('#left-sidebar').append(render('tpl-packages', data.Packages.sort(sortPackages))); // Compute diffs $(".failure").each(function() { $(this).prettyTextDiff(); }); // Finally, show all the results at once, which appear below the banner, // and hide the loading spinner, and update the title $('#loading').hide(); var cleanSummary = $.trim($('.overall .summary').text()) .replace(/\n+\s*|\s-\s/g, ', ') .replace(/\s+|\t|-/ig, ' '); $('title').text("GoConvey: " + cleanSummary); // An homage to Star Wars if (convey.overall.status == convey.statuses.pass && window.location.hash == "#anakin") $('body').append(render('tpl-ok-audio')); if (notif()) { if (convey.notif) convey.notif.close(); var cleanStatus = $.trim($('.overall:visible .status').text()).toUpperCase(); convey.notif = new Notification(cleanStatus, { body: cleanSummary, icon: $('.favicon').attr('href') }); setTimeout(function() { convey.notif.close(); }, 3500); } $(this).fadeIn(function() { // Loading is finished doneExecuting(); // Scroll to same position as before (doesn't account for different-sized content) $(document).scrollTop(convey.lastScrollPos); if ($('.stuck .overall').is(':visible')) bannerClickToTop(true); // make the banner across the top clickable again // Remove the height attribute which smoothed out the transition $('html,body').css('height', ''); }); }); }); } function updateStatus(data, message, jqxhr) { // By getting in here, we know the server is up if (!convey.serverUp) { // If the server was previously down, it is now starting message = "starting"; showServerDown(jqxhr, message); } convey.serverUp = true; if (convey.serverStatus != "idle" && data == "idle") // Just finished running update(); else if (data != "" && data != "idle") // Just started running executing(); convey.serverStatus = data; initPoller(); } function statusFailed(jqxhr, message, exception) { // When long-polling for the current status, the request failed if (message == "timeout") initPoller(); // Poll again; timeout just means no server activity for a while else { showServerDown(jqxhr, message, exception); // At every interval, check to see if the server is up var checkStatus = setInterval(function() { if (convey.serverUp) { // By now, we know the previous interval called // updateStatus because the server is obviously up. // We're done here: continue polling as normal. clearInterval(checkStatus); initPoller(); return; } else { // The current known state of the server is that // it's down. Check to see if it's up, and if successful, // run updateStatus to let the whole page know it's up. $.get("/status").done(updateStatus); } }, 1000); } } function showServerDown(jqxhr, message, exception) { convey.serverUp = false; disableServerButtons("Server is down"); $('#server-down').remove(); $('#banners').prepend(render('tpl-server-down', { jqxhr: jqxhr, message: message, error: exception })); } function render(templateID, context) { var tpl = $.trim($('#' + templateID).text()); return $($.trim(Mark.up(tpl, context))); } function bannerClickToTop(enable) { if (enable) { $('.overall').wrap(''); $('#loader').css({ 'top': '13px' }); } else { $('.overall').unwrap(); $('a.to-top').remove(); $('#loader').css({ 'top': '20px' }); } } function executing() { $('#loader').show(); disableServerButtons("Tests are running"); } function doneExecuting() { $('#loader').hide(); enableServerButtons(); } function disableServerButtons(message) { $('#run-tests, .ignore').addClass('disabled'); $('#run-tests').attr('title', message); } function enableServerButtons() { $('#run-tests, .ignore').removeClass('disabled'); $('#run-tests').attr('title', "Run tests"); } function sortPackages(a, b) { // sorts packages ascending by only the last part of their name var aPkg = splitPathName(a.PackageName); var bPkg = splitPathName(b.PackageName); if (aPkg.length == 0 || bPkg.length == 0) return 0; var aName = aPkg.parts[aPkg.parts.length - 1]; var bName = bPkg.parts[bPkg.parts.length - 1]; if (aName < bName) return -1; else if (aName > bName) return 1; else return 0; /* Use to sort by entire package name: if (a.PackageName < b.PackageName) return -1; else if (a.PackageName > b.PackageName) return 1; else return 0; */ } function emptyOverall() { return { status: 'ok', duration: 0, assertions: 0, passed: 0, panics: 0, failures: 0, skipped: 0, failedBuilds: 0 }; } function emptyAssertions() { return { passed: [], failed: [], panicked: [], skipped: [] }; } function makeContext(obj) { obj._passed = 0; obj._failed = 0; obj._panicked = 0; obj._skipped = 0; obj._status = ''; return obj; } function assignStatus(obj) { if (obj._skipped) obj._status = 'skip'; else if (obj.Outcome == "ignored") obj._status = convey.statuses.ignored; else if (obj._panicked) obj._status = convey.statuses.panic; else if (obj._failed || obj.Outcome == "failed") obj._status = convey.statuses.fail; else obj._status = convey.statuses.pass; } function splitPathName(str) { var delim = str.indexOf('\\') > -1 ? '\\' : '/'; return { delim: delim, parts: str.split(delim) }; } function notif() { return localStorage.getItem('notifications') === "true"; // stored as strings } function coverageToColor(percent) { // This converts a number between 0 and 360 // to an HSL (not RGB) value appropriate for // displaying a basic coverage bar behind text. // It works for any value between 0 to 360, // but the hue at 120 happens to be about green, // and 0 is red, between is yellow; just what we want. var hue = percent * 1.2; return "hsl(" + hue + ", 100%, 75%)"; } function suppress(event) { if (!event) return false; if (event.preventDefault) event.preventDefault(); if (event.stopPropagation) event.stopPropagation(); event.cancelBubble = true; return false; }goconvey-1.5.0/web/client/js/its-working.mp3000066400000000000000000003051521227302763300207260ustar00rootroot00000000000000ID3TSSE Lavf52.64.2di  4LAME3.99.5UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3.99.5UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUdi  4LAME3.99.5UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3.99.5UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUdi  4LAME3.99.5UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3.99.5UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUdi  4LAME3.99.5UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUo(@0Gab/q` a#@q./sN N{Fu{nndJ罂r29 BLde;ssqsh!&2l\pN(.Y L9(GIG吽o/s@J罆/Q2eshIV`H 1sssss.(Ԕh0CCʚܬ-jN'Wr{&^|:e9' nQ/aF{ nledr!4hDj'W \GĂP踐pن-\0,Cpq s|By\~@N=G FDE~ cKrO"nf]ާ=-viƆ8gx(FσINq_żRY+ X4B2r^`a2p!dD ɀ71?vxE[1BkxsR2'ڐF Cl. @B<ˎ;$F4=FW֗y<!xɁ`.ƈg9(2CG*XFXAm~ne0|!4zga \F i܆HEwӮh4Q!&qXoa4hz\8c/2LՅ[ Ov.x*@&\m8迏Y`/.n6kB `#0QJSQ?ԋP6F!Ic 9֐!*bhBx.CB<,?CJ#, 0ɣӝ =΅ȜPQ]܏rW{lT6D JJѯp0 g!֫wX1/߈XmV3HEA #ɘ 6Pblh Z5cRn bLA=$TzRIZwl~͗7E[vR5_n'$Xܚñ6Lך&QgT]|3Z08Z7SڝMeiĥ/! =dos~<1r﷠1n^չ ᖒ˜<#ksnؗjřR1futcxwxcAha"35j+O-r~URPו٫ַGV˹9ũDJ8*6ΣB&Pwc[d`N! "e)&QEQZ?RF`T 'tPL4k{"{&[p'MbEɈɏeFA*Q4= ⚝RV@LR)cLJ>U2)94Փl?9,%覱1w&4N,2| AЭ1A\ăK` B[IT*4ip bxK0!]Կ6"?)#&qRm4pYCn97zJ m)`2Ά޴i*ʹ2! Ls޶($P0_j[Ō90]4a:w 8]7H0#0Bpx5 $c4VN `u"<b jG;cw*xCcg-!8Hei ]d aE1%@ZO7@xDو LX  p k bg`:r]AbK^>>c9{_ƼAn8|yM6H}Is}JyCܠ04훘a :1UsdBvOm D@ϲ s %K3X\/5J|An>?9IM^ |tycGq#F鯜W!!5Xg*DfSޚ6G5dH3ޣ{q&sxMO&5}||?+?)UUܖCА=:n BP=Lc 7\r-2l YE$C8r2sƄى @;G!l}L \]ڷjh;π(Mφ@&I[(Jg"K4M*˨Qԡ^ MrN@(P^dk8퍇 qF&N,5rͧ/\I" oc8y>¤(brgFoy?Ƴ-u}MB|b=/7f-{^75#0dwąlo9n-<+x. M@#p ##QAKd\ q hh=@*V˝,間CP*1JR^qMqXvgs]+GwHbQٶ>jnN{.Viw*`wMB(t m(5HGy$Ή18|Wmٷ{oꫦ*u.<I珢kYoiu J*)R9\<,]RQ/ 1IYdboKpRo/\;M-Žͼ5yDlZ'\|3eWZgGeUEܕ.WSEQAɝ"l҄I g"⻫F&h\lNMI %QM%X>a&ũy~x(yW3,]2"2)1; 2Ph)zLˀ@k@݀t\dHE!ܴr~nj`XSjm]b"J1 pEӬc dPCSj"\1:=BW)uo^ݱ7ot3ZmHL;@cU14.Xƀ׉2 1 ӇRՌ,UZYԃ0j0zE})X[hnV{Qڵv$*Hӏ,4) "\ \ӎPZt(o>mBBp_grV/0#}e$kp;w_~W:o@\0`f8h`@a0Fpc$E$saQK]fDSrCW3\A dKaZzdN`HfLܬ=ft(_Ðd9I"ttDʝjEfz~L̙&Y~q?I&7EcBy|tOաE< F"@ll*p U$b@4tde_ΛxKpHɓk\<LQVp/2=Znx]C\NJqL*#hЊ/$I :թ4ʝIP!vE Ku GeuVG},k;4>kU3>R0W73g7JYKB/FG7Jf!jr2V; -؂8  t  aAD@AV@5"9|w'HQo:Еqzچ^"KmŖ9> !x1وS΃1Y6$BQ,TJkF0g1@i1ۼ+9m2"a͝ZݨhjaæPcD*ic !I Ć"LP)a:*E.nJ nh|G670<&v0jjk*fRM_׃<\_'m5  ǦiU֒D3bhCeɔ %+),KhW"LDdqst0~`'L5qKS뇨V2^9fffg :SF#m3C0 \Ph 0$@y|ez=-=qg٠(\yHOyJDjUL魲+j} e_nhnΡE$gryF:\ăiH>|=ݩkTqWw<pl>Ɏ2s"*1 *&'0b#+L J* 0~Jzz25H73 xa{ 7+j/ʵk:X(VGr'2hi wT2R)4nį.ŅOMYY34ҝY!^YӚ}k_眪XR(0g@pǔ l),ˈL\lm0Åa$phkX+٩v2Jց%aCкg/*R0xqܨ24Dq[U! mBdĀŊRƢʝfJ[15?W_WUߞSBIMw9ZK)QȄ H`!&H^f XѦM>`"ӊ%ydgOOKpYe\ .Neg!eA=p !W&ǫjZՈoHT3N9$ 5ʾ -DD<͊-6椹KRC-)܆Ĥ ܉$Oa!ئЉF=swj$u$f{γ? kVC ! (AR\lA|N#kjhX9$lb^T*Jhػ1^EVe:rF_jN95YG>.q>}xʚoc7]Hkgɒġskr(dƲ`yHԂ>@@*b̀Zd01}[ uRm`ԛ0ke_Kdi3tw3}_tm%O\1.;xxEKV (wRHJMUK@h<n.+,'UR[U]khvgׯ^ؾcj׽ݷXq/L˯,c:3H502BSIK`  b`LA(A"F@a0瘴]HaT?m)(2 GHHr%xm Vv؞) 49Ypn>aWlS7ݵ4_ܰ7yR`k`¤ @ # `h O]j di`3cp|ɣi\].Niɶͬ%p{ d3;do`eKRNCK]h꺧ȫ^s`WsM2;/IbƏO}GO ZnKsI4-' 725'6'[**~:-\~$gK=HY[)珸^sֺm6z -ֳ49HNbC ǹ  dLQ LF 41`o ˥]@x)jr$#$LxHKcDzk +I!#l+X%Wy}ʍ;۴pY{$:h0Ы3301 K1\&081M  "0-l;`eMǍ+]YSHC9dCT5&R< %2ik$TB]6H½ o`)P5$8rV Y*Tx;(Hj\lC HҏzXybxjk_5V`q ˋ-1x,P>횊}6q"Q"s__Љ$CaI) SfwqӪ0bfRRSDkpC (j| DNP4]{4e:Nw"D*8]Wo5>yڕ{pyhJ8fQ@4B3!yb糗~ B&R0<RZtaM"_2%KEmanÐg呩m>[<!ID!(}uE:pbP5 *EyVmSg?sj|lE%P l:' ptV` TӥG˵JP*Lf'hnwF5sEmm kX?Ϥ5~"KėPKY.^Kcut6KaZƸ!idViM-;Nq Uڴi}ǵo6̉!X4 $C"\@p10\de7Q*BL4CuFj%ҾO%F|0VG$Q^]D^ ѐ47QjScw**$*S`1rS3 0 APq[*( pF 0ǁ9[_)')oc'ș;K,MZ{;I۴~R0@iTT)V$LzBQVPdD]xKpwGe\1gUL*(& 2Y&bJg4"(A,=1PJly/:}Tnm] $) @^ !wEX ˂(*}ڴ1iqx#,ɖ)dq`PoKpyc \]EM-gi-pࡡZ?>԰4}8q#bS$zgJ ϠΖXR+g' ,OqpTpŀˤ D"ޥ9ZX1w6W(AVO:aBcY^>mzY[PoS2",󸼌ƌ!p6dM%4Nqle2%`y8M N$œRdSBfPACDӣ}dwfP"[TFko96&ԗkV94DA`g& #0UZf1-1O>%f RneIJ!ӆZ}SCQp%rQKGb?ɥrw0 ә7Hf'(1XR'0 o RdX_ i!S B[B㤑NiŝGUJ (I^{W"@ "S-a%qS4}$9Pij7qtJ\Q\ҨpɔEH,-Wy^JnKAĐfߐ@ p@5*`7 4I~ A t,lɤ:AEZh ;ZnQhCQ7Z?"*/ u}\:{d}^~^XG B3@@Nǀ 0M9@d%^OOKrq k/JYyC=-ĝgupC[< \&ek'v4kL>N̴ӮML>D p룞2T M 8#$s[$E, =亂_ZLU6@A\3-vuOQŤ( a͉Z"H+O55&3e:G/a+O!Nv/JxJ"A3ۋݕ"$aj>2hH#. ţ]04~CI^W0ۈm~kN[fفPKhPe&E 4.)q;JG!T~MHU*[_b4#.:K3VMx&ZH m튐 FvzPꤍXceN͐[-p)j&L//csE2P (DD2 2{ VJlRUL<{.֔b   A:HLCJ& 6C Lk}c70aST S7 G2.ErF :-}]"ּU(Ä#_Up)LU_P%߶\\ qXvΖ %vf$fdԀ%C\Rk/Kr|Ig+\{;M&p~֝VTt7 ~ƉRLwʌHGR}/azh{xa281鉮lVzj2Ώnc%5y4@:@FLPQ XG2z)/Z7QX~=gnF:Փ eјe) Cͼ8O'[_LcLa%>޿_1)s:C8yD g#r#> 1X riEtM-4TXdIKs 3v!곩P.CV4vR%J" 9"4&%`)8$Z@Q'@bܴsA[K7tt1]xo1J#XC +u<ǼUSYR邯s,yƳ1;$ f~&/l0lOt5ANa;,.CYi.R䊉(Re]0b8,PyC,h jBsl"(XDrcJcQ$Lqk;-{]jIYxʠS RT[i!&*dN [!(Vp$Ա5HZ +SN)d^K!;1;9Al$Q6& *vWD#kHMހ/Pf*l4~e K6fjc\'vÔb4зQ%A\#cjgĨ{q2Au;GjuZxgH*M 4@)!-R ź0؊2 Sۀ4$],$15A 2xR4}+#eGB70E‚-#+?QO7 Xȇ⥙Ã)ΣV#g&#lE>T 'qEV%.֝J;.c!GQrCRW3DU8o_bǑ 2]6hB$%f%alP9pPK e{Ԉ-JZlXqa9 tu@G`~1i3RW 31㎝QkHq >d[ ` FXbs)-2SC +qƋˈ+I@y:(B䃢R"PaUc0b;KؖxU0@({4@]bDE=j 4t!sdKdNx{p%)k/L8mfM=0`[VíZd4.0k4Q.')W?ngc:12 SG<♅Q dbˆB$́/[JG+4/((FP(T\2Ӥ: `]Rd̀AH@M!rLpi89`7LBy_cdvғ҅?[;Ȱ*>UJ T}G9XifVK8?Ҋ5,tWogT7 ,3GKO\wRrXg)hk@n/㿪pA;Z$dTh(UجnXH a-е)Z՚<88@??1"(ɰ+-BP+d Ty,S>V7"0&SԃHc7qwTj&(gl4" 1Kc@P lT0]b fbVc%by`' P yD D.<9 ֘ t{\K\Bda\My{tikP\]i6M h510ŪV+2p:nk6baӱ#tl81.|SWrh#9m|-[5MA)u%\*S)-ɉtr5gxX;rSV(>ǨbgEaĩ2qhV%r(ˉ$LFfAAGsE?2PH27J~ȥp8cEAJsm_tWlÖ 89Vqoʛ/9}I?fMQ&d0I#P"H0" (z /_&g hPG1.RIҡ 0`"GL\'4!Ir Dd'hMzpfJa\AgAM='釡p!Eq]ED&*Ae{YE> VS8JffƳͯ;LsɆffc{g\ PA ?d=4ڶdCA dyOEk,N`3ε-MN}x+<1yjN(7!ܒ^[XJۈԷjNy1T8[@bi&)0aSS,$3c.=#MdS2l$cDXE= 0X""p*sqTsk)K!t;8МٰE$MnXp)GEr@7虥I865i}Uj񈲠x%yU"Z!R#f:?Pn:T.^1a[/ Yu6!KU1_:6&CaP .?021ͣ"g!oAC0,93UQhfnffj$־s !~ ;S\jfKY`]I^_\W 3!"] RUơ0ϡt9Dqל>:XzN=+WMy%F\rMq ƺb00I2s`,* 8< ((JTaa @ġkdgʋ{pwk*n}.M&ݬ=(@+H/$`ޤC vniJukh9 !lA- 11 @ Z|B9i-<2`UH^T46,d#+8s+'q!/Jˏ-].Ĺ2%s 8A* d2x02@F*5iLr٭;kdW/*2(fN#D\8R78Q|ަJEUl,S*c8y)1S104g3.4 1@pS ``L df~*X,U{) SFM}X[W:g-C{W\XC>9!# 5B2aLRx9 ڻp "!eKP 30$~v~Q4@a}O pͶ0=EHevڳk.[?X@:! [RB-@4xGrwC"s,:IK!7'Z܆b Z~Ɣ_25 x/!l[kOwY h⩑F0^"~T@ HJ i5$ LS0ŕ4wi] ${i&觃 BU˅0!K].Ң!Hq57IBt{WUpy yڡ!fnc1#.A4tXH <0|__ k̡s(qG8Tq7-d&*6!dnN(hn֝G@罃OjaX֣AQ4VLa+4%dk%!tCC+~\&մT6H=⫙Ч|4!tx#ۑv4eq+0ǴVT{L>p#QHܺ0Sc ͛3n xA3HCDBC xJ4ZQtngtL,6 д0_ <ˌrD.!͏dX>EE.qObHKRujK[WRZei4;pId^,xi& +0q0@rz,M_)T* UgmJXY4Ժ1(bl+rCWdR=IVuvӏd'H`Ly{prkQ\8mƒ)a($V#ϥĄHPG*.&>k0!^]ȅ‘2Ԋ[]HpR'12Ns9}M=`kI*xM˖ 6ÆSD#ɉDpC$)McXbf60 O +~ *?I4JXv׻Kf]ܛCJ(/ \_*Z2LZ3<_22Hb°c Cr4,10c# PIm BD_ GyXЎ :~dɔjڮHQ4ÍeX D. &`QKիNQwTar騛+#2U2ua1v X)ZhN2]kCNkؠXg:rd-)->e(&ܒڐ%=U-YUnS_5TK,أ;}&@o8,Ҡ"!bgA$.YlL6՝wC:fb="ӷk&~ $JĕqJfVzneHƌF8RmU+S9 0#v)PpH@2RR $4aJA ->g|*J9p(? ˥ׅd ^pk\!;Mnݗ(]PU韔T.36jW99FW!#Y#]1Om=|g_@&IΙ2(׮l)C rmeT8hdw<[GM( .,5y¼8vl{7K}  R&T᫁@`(v[MNA#=QiRxu!aR$ K&I6tbyaw6˙[l;1|lGN>RY40L G)C&`q& tahX0(<*$&J~b+PbHp:a%epI (7,*#1yjغnCv7ҫ8ġdG`LØ{p&ٍk/\y=&pWW;IzQU܆q%-#[k3Vte΃')=eVJĕ++lxdmmI_J2>sӯE'm7~3u۫^f~XuQ!ѩ,@s&q fJM *0 X}Lp8}*Tnc:]hQv‹ WqARyH0xu $8&%G1ehqXKGr ?Qorm0떐J".9`N F>Y& *k_GFf_tEP"RU ѥ-.%Er-m}e72u&fSbXܷi\>V`r\XSXt~vB ºrkç*ast8Z:f&h@y1z-V_wG1=i#KP/^M)X 1m'̫*{N3y ÁQI10\u rֺ[k2Zù*N).*')KxR¹a$xFFL!ZކeZf7<!&%@@`x䰨W7ᅮ:ĕ~?W¦%",5ٻ+"!a](,6&se-k<bAĀ: ()(@. Ǘ"i<9WAIY:T7}kU#Q̆N%rz f 41,F1{ %…›167S-s,2A0wa xqAq@0!(e@ˮ 1PB)mLtHvap@o!1JlI %Rj ?+q'A,ԑ*6c+ ӢX<|V΁#IuiQiaI*\9 =f-TWNOYN݋sq(aj|=X0EKhBݕ* QL 4?%O cHONhsW$ܱ,B$&jL2NBCDܗ-6[IJ龠w;N>&KN |; E&sʳ3 c "BAuZVͨ"45BfB@ ,`b?`bp` 1UU6WiIX6!Ted hLycpg9iL! }&—ݬ=0r̵)0PuaH3G9 BٙF(hFN(: zW=?y4kM!e1\Io7B_Pji4mcf:imVp>%<}[HءHtBf&]PhZP ďTVZRu!^r!9E8m5^Grg:7,KfU.rhɀĨdYD!   A)( в @Ge07!ĎOf'hU SI/b[jSVNY`d&0(ڐ澞hpr].].Ԡ f Yni@RNAV4Prcͼ4l1bHģSY0 61w04,! ; baD9}K``g P^˽g蹂@!B@.b1!q[ hMmY0r_]r8J+,HM |ΆXY4w3H^mqo~Vs:z^JX. HZ]3 Ȭ:II%0ˣXg]2mJKxR]$"HbG'b5%J+ 7C-^0 ?CZ<>!.Ԍ1D)z5 $i'I+^u9idR'eJM? L2Zc26(7i70*u:, CYo׻Y萦oS58I: ìd hagJ{tgeiL6nmj5(dGvi0OrƭZyt+;*)AprJ\>DQ@E; 7x(_<>J~a=hO[/qnH߯pฤH%/9+2ʖN2DVvohĥ,WY1GRr 5CW#CH ef`%1 T(XrYhksfd V!@cWR DiZ{>[ jBtX<6tLZ 1isZ0 +dy `pH`0Pe], , ɞ" B>CA3[r_j.G1AFRL0N”F5'nᎯz }$dܟVVI< :o*Qİd0NKJ%CtVmmv̍qtleqjgaesInq5:]ct(6. @Z ,gAHRxb!ǒ c"%NU(o Q8i 0 HKީ#5K DPe^P,KsSG }9A|eZ:B1`` z2`<k;"p]2,$,@88`Ӓf EChOB쏥dH gL{pqfiL%y.Nq~g闱(LF MW.ӸJ @~g.*MbLԠy3H44Q/8DK\R-4o4j;jvVĄ=fgJGfmv%Qκ[q[:Դ)룀@\HPz"*S0/XN`Ff8]C'I;;+Ճ ;Pط@\jĂQ`P@<³ E}< iTOBQ?Av!FNU. :ts ic).&K̝?q:jks~ -2+U`LϧM hˉG&),6xlX7zs ;.@Gi3E R#h2c":F'I+u`ڲtR@94TK1aԥW#nj,홡$xX{7ahQ Afr C0Q0A|-XI+pXw߆%5MLbEpYJ)idXhʓ{ro& kL=;M]p]1XdN6iJ)RBZ:uA,]3t 9]fg7YMqe$dR3 RAY@e6q+-!-.0 گb|x4M= X ,3QbZN*NE{-Tc+r9qvn9 \WPln^c %@}>>K\H&ʓ]9QW@d Hr]R4p)g8酪(lƆxy[K. QZ `L{l ٚ R^Xfg (vޔ9Ef }u-!2&,'Yz pz#IcP$Ge!B'=ɶ:)*KCBJx^;XFeQ!?}ܴRlNj{R|j>ru\#fq+=-1x`ZI+%Zr*'WLZﻲ +i("Uz_)E&HL282R!Dkd v+#dMJYmG^iî8` S30$~MN40%`4]*CͩNɣ쿳ldd˓cpeeg L;eə%0'f[=_y_Շ{ykk9A$%Hx'iњ@իf̒pEYJןItW $'Ie}*MR2|2Q׽^)CuyUftZ.>Xڂ T@TXp:(G 5vԑ̵"[UdTbS4$J(W-x+6}y?~s$3;%30  SV x1#tG01&LSH …F*&"}Q`:fQ9MG` C( UD& ( Dd!L(30ȡ\tF&T؟7*Fb,1mW)lѷmdͣ35 5Qs/݅>>LDI(f/,FEr_73j]rL'nr/c^ws=oZ)FeqF K*MơəuȄ1,qdDJJ/%'ieCdе*8fK&ilzNϥߣ|UR*pC|CֶzT1-: MJ|ɆhPvMnJS1w\^f3vhm}[Ʊ&p_;cdMS{{pbE9k L.ni=0Uu]Df9Y/n)eA8ws.JV9ȩ8fZl2GC)pqCq)9䂯|jiJ|$ׇ%`ϡ]vmKM@wۚ-I 9^խ_4 {pACrD 2< 2he ޒJYwVV5oHY\PV | 3ŗSfKcnnފS%253!k 1 04iI?#i``c(}8f f ge=K5R*-sNc#;A %\u2*;TaӔM8?IhzXxp6Z%ƥ1n4$fɜxx&1ƍ~`S%[j\x8s|8n&Pw Bn~1"ɢ%p,j*\oIBJl3wW]yf^g"_j Io4ar / b#ypfeC¥B#$\ HU`ȍ́ vЄ%?!n*8n%pYc@JډGH']Mص-)t,Pd倧 ^M{cpbe9k L2i=([MY:vEO$:pH)b/ePI…7Gn/9.0:\ӫjS< V4eʕ9D&g ChmC3EU]NS $8$갇ifd@A@f0b$;>Su+uem';dK"CtuFԻ^:OqwoE5&xGb"уfFeY`.bsP*Jҩ-<㲹3AYbB± U(f]HɩP M'VZ m*Ϩ|=e$2~W\պ9C'΅h>1${S_Aah[4♙ŞgpdkgH Q ˲$~H^KTS8Jv3vX+Qu7[ dle/qt/:0ńQ8a 1# 5#j&)ceU N2 ")|1}hⷭ5ivRLd5k;QV;w嚰)W)`'^{CB,edOhLcp{ o \ы:ma e5pڵ[DbԊsTU܄/YU6_FtM bh:|c?Y*֌Bثy_)kș9s\RW2C BC^& }S=,rGt+z+U`X.eʎCl2(14 "vG $LR.ԘE?i@^H[O2Mhch(ũB1ə#pza!CAxL 6 .L!p+ YX~ ˔R,Tf1茀fOa ~e+qdW2)&_.3I*i@,`"کo4Q!Kjn 'F~S )A6@ͭo9꠹~UK@.q2ZLMifY;,jⶒ*cio,7$D@^ ΀bqшCADCƺ-J+qX7S OH O;|8zݱ(de"!0xLt@"kr30j&4ub@T]5*+a%Tmk JA ]Y4=zf;;Ҹ&4X0>{J|dh;cpCoX\ّ7M&=pj%MLڂ͑bnxqMUUF!3Y:iye.{(Y{} @3eQ\6Xrx ='FκXij&ap=AI0 !)&2䚎;zBbFCm(J齦ϡS;83s<9[#C,Ι N]d9g{V>IͲ3*L<1"ónè aYIF3 1h%0lIp^0/X#@<0Z\G%K_B(2WRV 4x14dч. hHB8A"JNNSX;USЕa2a ~ 1/",wBi|MفkK[z8PxV7ȗsO?mWذ:;P\"C=nw^TJ2c;=S66Q S4`B31Ԝȃ9+ p " |%E$~P6ɭ.j!ZDo\(N"XUrgN^NH^xʇޱZ&ȒMKU $(PF@H.p YR`)t B8Fm7ݧC?:]%͖N!q&% d(_K {tgI`o/\у:fͬp+'O*`%<6"0p+A8;JeXֽrl̶M&%%SVa7uO6׽", Â9i$!$Y4'JiWQN?HFC>7.DqZ8LG:AV4wSRHy?ԑEk?2d뗌PUJrp7pÉ!456 3Bŗ̀A @pY4_.d\bK"J!_/(B(>UȠhE'G^fs!WuZg[V UtE.ޒI%@"s"Jَ52eWTH0MHS9"~ܽg֏Bu᩿Q_aylcȟ6؛b&]հՈ(p' ?; Qȸ*۳.\#Sˢ Sp6_U60b?F E)sEiR-x]~rǃyTO +.4О(n{X$P^P`a R\DN/%Ah ng9}BANUq52(VL0UFH H$Ȁ I_"TiUF'_}W-ւ[va"mWtJc0cUOʚMVg z' z>dxbK{pik*^M<-捬(Mk/$!-5WigI.r(= mX]$qʺ$M(TH#>RR^ݖUMɂnp`sċkLD!g_` *Pک7*&Hڬ7\"E.hqTJ֌k>NthPokVx- u=>wͬ7.7ZM?*L  Mo\ z)c"L ^̨5 AA@p6f.,b@>j! gU c8lFb?D@ .D1b/WI4 X 5$8`p{.13!G|H!QLꙒYS04,,4%3i 1gˈ( 0P' 23103dފ6aMzcrdc L w,Nm͗͜=0Q@0PHYĢApF7P#&0,5U3y;o"%D6bv($$E?52cb$]026.&j]iLf= CMʧ2UW5qT(`6:oe UǦTq&" 6ihH)|nEH"H$ 캟pRPi1|yZNNJ'* ,dkƞ5`H+ԏC5.`q bQ @eQ&*qG; {%Qͽ5HRv:a4EAh%j)zD!2XgYwgbY&bx"g FH-` P*HS x\@ L``gHA%ёѼXeĈYB d؊^̻{pe)g LQo2NiɊ穗0ep\)V9 NA|եN>r O'rQX`fMnkmECϙPL=JV31k~rרhvfZgTAWNYTmV> 4V03$MGlՔi|27m. 4Hxu֤)AAw_? S֜ňlt!%Ҝ^I}`*&\No휡O;_&e2aRAEqXȩd)q1$FאK[PP(0l)S! Tϩ)(bĀ#zJzL}6`F;a* G=*Q]BܜFl;N4diǂ(Z,&n I(b&| CjOɉL@9bOj`WkSՕEs'OIqf7sZ,v-i5Mc H 9 bqXT9@=I.Bqk/V[,0iAf~>73%âfi42s` a' ` ` Ȋ$ C ܊?/!Ƃ^t,()qooYKPk̛rh%#o' ̜{djNYsP,LBT6GE 1401R0k FZRbDׁad _{{pcE=c L-2l鵜0! D_"ɚjJ%ۖ]x(<1FP@ ٲ !m+0Ü&V]G2VbX/7 5g;Jv֜cݾ>Uæٛ{yWظ@Lɖ|j@]fBU>XѼ(.n6Zd5 l6Dv PԤM弳qAAeplˌdPG%V~u?45r[lX1`QJ4]%0 twn Y{zioENC80He1F9gIFo $O$(2+*0!" C Zmؙ&¦,#`چe܌p&Q!(eNgeqHiZ4ma[@SB6/Bԕ*0UQUV2^*+*=\EL f $VD S7d!fPA" =i8^daK{pd-i\}8n!0:ϒN0k^NJ]@k3lgJDwaT&f8lTeZ=iLCW|/JzktU7#L;X_4RAp8E}!S=_ڑUBw;h-ÓUQYA^z.0T$&ǘɲ!5euos~OUIʢs H,2g`p08aсʮܜ&AFbW,-)n=P;ƙ`s-.eq؈iӴw($aH˚C8&"7%"%LΡ2r.S fAu0dTZ؝,8ui߮usK-%BVDfx:x"RdR6{S HuW36ZQ @@x@ 0+fDaH"W`6bv?hf g AgB13Z_Y68"rFeKʾaxhO4?`@b1f- 20-( ,p-0ĐDL!fK8`34XhSfDS\Áabq-}Ai]dݎ')bMcpjhi\_0.iݬ0"H";Lw2L*A3>u9 8U( G.6*册ڇ'BGȤ!(͗llQ*LW:dOuyKveyQӋ߼d Ǎ1wFv N2`p]EKUZZ8,Aن^ \E.0..!ۉ է3?p1o?jpY"2S* %0@e1D3 @b1dQghC7/D&D T5ٙ9SscPzE'L,24yhy J&B]LWNP Fd0 %DE'˓{a.ܴuG-oj޾xl _Ph#8nfW^j١7 oo)! dW6h!%˒;7\ӡjV«pc~}` V"`2(\bYm6 $M6,|(⻋Z_?W`l8 _\fbԉ; ")XdDa l`(JX6 $5TFAH2" 3Ta YZB0?@vUVkqx0d f^L{pngL}0.mћg%0oB>GU'9y!kQ+ Buکf4F^#̳IO ;fX{RǾU\U`n+3%e2rYꍁ`ٝO5,}XrѨ{f>IS}A!SՍ~s>rrފg Z-citN)4Js yN_Lx$eBQnJ&'1%_CXݯIXm.Q<ʬ !XN-FgWɘ)/яkYC؆:R>ɶWϲ|5e!1L$)@A4 p y2$,.tؔÓNoC"ot7aZAd [.%.G!+kO0f8Pk# ȓEAƁ  LP(B1.l\ȜEԏ. #9S־Uћ.1 /MB0 *D `"  K Jy!o8 ZlܔɢS@3ؤ84ڔe^k,U6M_f&+c!jÍw^ls'GT+IU|W(#)SI;]ڽhb.TY*&*)&n5ZRaKuڲy -NJ++`fYZ~(@P?D$0dIV7I qSa?,ī.aޏK3aNoUd3KЦN5joR;&TB`R 3./@@S(ܗf0 fULp ePMX)zʲ " %rq8Z5<R Ϩdݎ'_ˋ{tdeImL!{4m&ͬ=0k@&$2PgjFP 4.d KTIDuwJah7tʪΑ!>xYS{ h*I:/Ip;fGYt:):e/eIm YC,ܓ 9 G h E-R=GQnT_Y :>e[S9B,+ұ~ ;gs:=u#kP80O4L{N XLI/ 6,j̆&BBU Lr7S1*#)t0 ]~L" 8x*Labd# \&Raw:Na#O4l$#[+ĕ]Wnw,aRw#ǁy*(]ڢfytYELt0)\Y:W2+b ?j{[TLدN_֛ܧbvWu,Fo? l Ng!uFI^ AX|y_A7gIx i:E"5!)K!˷{ GvX4^[\8A (#0pHbQبle/;9g.d UV@BEK?pR0\PDsB 0d([{{tkiJa{2g0wʆIw)I9C@Yl.,e$:v-J3Klz7KJW,I,e#݅1+dF2m\n_4Vgnȩ=l"=V7 :#c l-9BLTܣ{ofVhq+#XH 9ܜDXPME`m>SCl`]@r;&;BG0>hEfct/+Mi92IVtQu߫c/@p30#7A `pfِE&*D (dÈ@^W*LhdnPP=& @.x-,5Jհˌkg&lp`IJ-PHI -Nz6J{ Nme2mZi""wm$OխXRiʵ;K?Ü{#Zb븱68__@c`ѝ *m!!)c1 -:E0 v Yd3%wjAv  %.(@u“ԖL ADŤNrvjc>AK;{0N"7hps:L|?0lHc M2pl2P ^ أ.&">!LF~VؓLIPc AZmH#ؿG@Δ 47Q+ ̮T…PP-R#Ad8Ľ`5D!57 q*!JO% Ы_M|ƤHܬtlo~g"ӯ*!SWC@)ǀȏdd.bDHP4B1v)L7n.PanޕEqOLjaZBgק$%[U09(m`!7qXV*3젞зb0ddb•P0N}0wv"M;YPT@}I[j(.Y|q){2Dm2JG`& bhn(gF4gʡlD .9L+XX+IF^8xL~$3l/0q(hI;< "rԜ 9@|yH%N ¶(1N dI_ϻyKpik Lݕ5Mf=0_ΩTA/xS4)N_^VZSA8mG@;w ޼.YHGeJ8=qj#.,^qE#wPqNm`*\JܤCe V3Ogy9A>ތXWX3f:cBQ3QcG(:z0Bpx:{(KaC\}Q0 ^QXW.I\^'k Z@PLpp475 @ÆZha(hhH1|yŅTp;YV.p6-pZ\8Ya# tl? X2`Ezïi"Q> 96&r(~s}lP\@Mdj*ZaiӾ)A*4/f#.TxB&>Ԉ~8Omt|b%/rm+SZꦌlHGOh~cjMaoo$Kl[$,J<`0̠8l0BǏ5taNHAh"M,uPΝ6*a%-;~er^` n4ЅU3 *q2:;+4=<p^أdWߝ_nC0h0Nga#.Vbʂ,l?-%"Eb+)ļB@/DfaX^+ @#XO<!*y?)0Wd'p[L {{tk\{6mה捬=0`>Yk8%R4+K$6dŷ/z}tkje#[mfTR%EǠҝęBa.$||1=2D (ƳųsS/I݆OՍyKy2#'}Z!$BP8HvXb+aPa@pzm L)V` -iIXS1lMm>LOcRJ(5XW%#i;ݯkYkѓ P|hŌpTȁhi=¡eBz/Mdbl0`aw3CӝA`6.+FJ3{; 0%|wd'J]z{r%9roLw4Mi=(oel/xb|mET3v?Evߴ'K_<5* 2Tù& 5cmOa͕ޭqU[ z3>Hw ,=9_Jrh!854.;dFL(D8ę44Cg^R!$) lf{Z&\RNF1ŋz.6:KJ* Ptf xg&`fc`D\pB"(Xi3Du/ֱ":U_)8a60 PƒD1@y&39RNpܺ8`QQZFX/rJ1#֕j!IӴHTRDx-jzlBU2Bl#!++g7Vno48C¿J)A*` W.!t1x54hH42*K)B!I"pA4Ĵ: yfIND .@zoeȅdMhC:ICg$|2lx=4B(&,;ymO}#'} q6hJF a 1?FZ\/aDbBee-fÏ]ynlġWA7Q ^Bd'`z{pKmn=M<'i%xk{QƱ2SR+{@@P펎x 9L$LL̩`V # -[P}mJAr»|$jilzw!4D̽CU,@"e07-RxAd89>F aFt8ol=Fq7k4DO֛&eJi4)l`(QFdaesM/7dX AFޅzOQGm4"f"i' ճ]JS6gF#k0 ?2#>6280d0hZ GH&9V1ե{$@u^ƠŒ'!uVT8mnZjö T !#eǭ#8bO9nY3('S;w?s >mL|1bE PQYr/D~*K>TD"N3S&عnZڕP&dedO;OKpo8L {0Nei%) eqjIXV>zoV_`~$v^FĴWm@5e X(Q`^w#1O廔Fbپ,V7p7xsM<;F#/L?^ә>2S4~q0r"@s408d`X)e@Af\\ *\n>SF 8jm+]V0VZ)(s)N W z!p q@/A(/ʛ^`yHeVim>:6I*c` fѰsu3 LDv/RP. }4؅CPldؿ>cS7[XaΚ6dMmS!rh@r%"FtHm 7_;4K : t,5L[v,(F9)=\})#K#yV%&S7":~0 &bg68fefa0DjU" F]"k=j^ @%cm +Yæ-y%͕.!ulxTjO$v7W׶z[_r{E=56 EIyTDG @80@5EdL$-a`D02$5Bw)|PJ>V$Ýi PIVFnj mRXkdfOOKryo\i6bErD#/nԯ@|CUrw91x ّ_ f*Q1!$O8YK yίe4֩Z7۫[@Ihr h4jc!h~aFCB@#44 J'|ʠ]V" UA@"k6ZׄYV3gt[(R!ὐ b4/!dzl#R4}1gR0 04G;xZ5R/uĖ%pZxKn[x1ֹ jk90h2ba@M2Qt╉&#&+5a* uݚDR$&d%{9Snx8)E'#5ZBn ӑMG=I)*J,OFbP41C$H OpE.2jJU ysUNLKgsƒN~0qKA>4I34.*Gb{liEeE;2Ql]mmq|M>RbfhpljTfFngϱ i ua&EłWp"Up&ꪴTOunQԌ'$mN},jnYǀ@dMh $ /36,vADA#ؔZ2DUu-bF<3Bn7% GuqΤ'ҤNbNN[Yb]E4H'j>9j2zjt=bjYP]ajF  !gA1v(ʎsRF$bmQeDqRݱɦ Z䞞?~sR:ߑgWˏu#k%wRÒ1'(t]jVR˹ }rJo:o QSv=K 5Z^b8/|ۨ۳9 S@@\A6D+XjT%|LjĈsFHcI"5ֆXmD&h74mmg Nkd&x\ ^ 1dMYyZkxul%:SZ]Hha9u˷Ψ[4BTR)߻]s/|QRWfsi2"AI?⁗B(8hDT/h™"lGMUt'Yc֛1+ _X?8u7J(@tb=ztDFcNYcplYenqE-ʧgM%c.I(|%s D 3VIkeZI46t&j;阔Y(អiJ* @(J w hX A Ÿrz\Ma?kQӣ8jÐ/{i0c-|4R/`}:dM >ewd[k5Vju=9,XRÚQ8k + J3s`&DgTD戉YH1R-qu^.__(%LbsԮ/-x¢ $\L)0]rP,ֺm"̾tB"LۉYܲ7)u?V11uƧdh;z{pk\<-g%(/Uw:f̼T@Qe:lkiz2e0\ٻ :id^efH?g{:]mQ?+pӫZt@ @@(`~cO.D(25E{ܰm)K j3&Rݎ&9) ǁ¤&!eQ %WCˇ.k`trk%׭^Q)?LcMEJ ߽РBSEA.[SӚZM77??lk\IG̴Ī=L SЈsō<&HI3`ŖJvD@ Wz'MМLD5u,L-Aqok V<(EF+Q~LAfSr<[SREK3o+w8P,_=.PliaL2a`aa0p0,ac$dMpq*wd@XvRXK-b-%|嫞JRrZrY +.sWN?N8BdphSXcpaoP^8M-N+ d0.sXTbL"3d'B&zoi ̮)7k1%+/ɞn!gXr/uMZcho#R 2H@s[f؉\Phנuxb>6EO!ٴY RaYn$CvZx_y=bѐ?-1?=O= gXPQT43ňHy'*@Zqs{g4 'U$J: C$@ @n$Qf4{,!@H8S7$Q4AYfJ"4d`{?c11;8NDw+3rAEMrY,Ƀ(-Tv~k=(+/,-V^%S͛ѕબ50SD%nQ,?vSU4&N$vY/ CN>эB1η_C޿Q28Fצgal"3l@ &Qc0ʲ`.M%h%ߤYs-&DEIl(&L`Whv}"Ys$Fe)a5pp[htȫÐ`ƔkӿvR5n2YV}%ڏAr/HMe/.S)uƴeq4dedSXcpm k L99MeC&p2@wWC;TT+K*8Yõt8w¶n:O)SXc=_~a]+tێ~k*p@`92g# k&a8$:rlElb8h1k~ %u.pUq\\&D_{=K)_@0DaR79"g/Bd[os=#d~˹een8U jB3FHC_B| BȰKB {_fR:mg7CQ>r/)]ܪQ^M$)jBh5ld-`C"kXSv dIE5m}v9#O;(k+})$( =2` `xq!U@ FƎ Iamn"F鿯 Z |(S7/K}]vw Q cP$frIL)LュhE$v4suCZK}FJRƣ,hyQM]Xݞa.[!ImԄ3Dsq`Fd("A!<߁k FՁ1BQ،%)n&~{^7rU7?">ӻ]dtH 4 @(UD^\OXKponu@-†0tDM9Eu_Trn݄Rrbju'-XkQ"Qe(%9.+P>ٚ>2 Z P#! 6Tļ*)(&)ԗ7ov7w{蘰4B)$s+ E~͋mTSU P(ynpS4-aDG$5*A*aC͔‰8Xec qD!@Càt@]JP᳹sm-~S/F7F CVb4tTApx`2ISSj 1fBgVFd~yy{!e Vn͏.)WͯDlcxsZ^[8mI54VBxZɅfr0L`E(JHy`K4È(NjaF)sy B"h&jo`ȋJ_)#].}> Z8r Ža;@aK'Ģr#L16"v7g 9N^QY:s:-V!.ծ r+BI.bKJ!Ka;SHq"K>C*c,@;)?Hx% Y'o99} Í\0\;?tDtDdXcpo n AL-ž0uQb0u[펦eg1KE4tq6V `C"'Sir̓hԏ}ӣUd@{6sdŭc$Tp``ik -8&Whت#mcafw"t-0=IO ܘ<ѐ,/z(1m'5)SS2~ jׄqػºFьe޶dvSjHѩnItw]fB t۳7L+/|¤`FC 1֜ B%ZZp%/&d Q*)cf؈cj (?OݧI.ROu:ިyHḁ _bؔ>;nZN է2=f^Sg}? 1 ܔ,Nލ,Nc :0 j F 4P%(;o̴ĵMYZx}mc5rVS-UUi ߝ*~s^ZK{UԸ86Ɠ}5?l0,qQ GBӔubBdMDy[GXV) Y dnf}\^Fb,%$uŰ=0.R*7RqS*YKa;|S?DdƵ]ޱQd_OXcpx&o \4Mk&podֻnl]f.q{z3Ɉα١V${ l^i"%]nG)"Pa  _!M+ Fg7PD ":[1X$Y2IѺ:%WyUF[Mƚa#B!A>ga_ G&#W7kZsTWRǻJ{#7Û"{|^ה9JHINq`%@&>bB,6DǗ jř0+BlvzD ۔AyzE kPz쐥5RqoXҮ21VM"uX02UR)䊱7?,vq}{wHf~ BnIYXnmPϭ,(s# 070*x&`1oQ倇 !\tV< 烟iOgW͞U(C18c4jlt'iT ^h=WP &6"a\e=.H$jFNKdB60]6۪Y1dfOKrk ^@=ʐ%z,-;]IdH%Da~'ݻ XT~ݞ<~&Wݾή BsXa8TBZ$m9&m4 Θ'(pܹJڥE5WS͖  S"SFȺh b蚏 xQct"w. C*֍IhIf2]W!Yf5đ<[q^q1ȯ3333gi(tĆJs(3ҀI)l@ $TJb@&TOݥH-ГXa;/i'82P\x. [ChBArJ!}^<~8詑AL sJy=YP@Š9`LsRUdFL1Ra@IUR@l$U"!i*.'16|ސc|-olP_8Wm8RכyoS3@@sr8BhKpقC@(@ gQ\Q#Potsʤ;bzc`K6u:Yg+,+0&VƉ.Jx&X4h4B"fugM>[v)^+0<.|1RlT=|E)qUav{&2 U=i,w/Kpdã25͑)B[d nsT KiT?'X,>CRqGa۰{QYh jxPZ64i^&2/?^mb1i~5R|_ޒɬ&amn׺OvzXAjNm ti҅Ƈ%@)fI` L匓lzJ6|PXLЁu?R."E%Mq5(4M9bDdCm'qÓEa^JD iPZKQpTD0`QKr g nUCL²h !lfrbPi0,_IQTwsEJwc`& ><,0٥_" DEuPzg?\Dj(3Wdӱԗ-}秦'q:TH}4b /T.yGGEE Yh"I.`@E`*uAᔃ2!dj>pٺEe(1334 @(ILL`@`F %=~ q|<τʶ Op,T$, $:ꪬu&nb$k /K#ƃes)Jy$BkcG$= |A(\Ց*X{ .Ae< ^a#cxcB-^'7֙;Pii,)$0.]f dc21hLun0:+řC7HTF3.U]HW#S3jh_7 Gzfxc҉C=<[T0Ws/0h(2u1 dEÂBF.ceNd |lx@Qbj˒\DxR *_1h)k= p44khS7r,MuZE^|o% ib,d"ay{p)k/L)6M͜-p<^rE=KfgxĐ&euYfhΏx:{e,fRN">eOU'Y⟲K0~F]l3bj|<ǰGcEs.h?Otbd.H);Z}˶ j匩~(a ]V/Fh JMPk`GJPa5ǒ]mJP9buGK_:ɱs^X g_U(A*!ojFx&44MJuAԤ -,:u4 ЁE۠ F(R\MR觔P ZDp}@IdH T7t'uh^w5e=Wwέ8VIXŔr2ʀ2v@xؑƧ0ܚsŚaM>ߨ&DL#Ď-Ė P|T1$l&&;% 3i뤶Ё"ch0LҔRz qB(i'T9ANT&VI"41 2vA]{3̹[m1g2o_q=GB:M\"9FM6dƭehdC%$ yO4YNJ녖=@n߄hYD[hO@ `QCHfHnK#+0d5iu\qDhj-=1q$K?^B5_$SZ^jnrkTh`k$hr/.PrCؙ7qPWFlIjJWgV/&rɻp(̊44"vnrC)A f|vRtYD!3?05e.Ow~qBqLb.8|1s#/%>@%C[Ő5`,Ո #l$ 2gL2da+GOTQh1t4AI@4 n ADU檫#=+"%**8yPNT,1nlN ӗ`\ldg&cYcr|)kOL:meE0hWt 50~3B\b*>鎗Q]K̉E̤gұN,!}^q^yR)}^GKQ@CS#%-Y^c3g~uޙ~#iWY,h4ӎQ.J"rPuؗ'40egȚy"=cN+szJa J%K\ݚ}^ݼfѫu%ϝyLJTG lFXk$ ,٣BL2ʾVQHZ_ fx!*? /BDǥׇy]|bńLRlxki2DMqH h*V*vYDL:~DơYr,Z +_DI$5sY`c! >$YZ9N  $iM< Mj"= fs_s@p33x؁XZISfcUjktֆ*Z(ԋH5Eav,P掀؆p0D*V 50 8X4,l P8"n */ic[uuY}X]y#p ^oZ\dbKz{p院k-^:m(x`Mlr9Gt:CQY+aB/1 $ţZֻw^w5z!/4^v>sr^Bf4qJz޿ VF! XF:]Ȋ؀֟WZ4{w?f}^h:p؛E"t`Iެkt)ʺi9<-6k٦gU3pu}ͱ-2 gϒf`\o8qyl\.졨5!Va &@\R>+Q/lQiELA 6&C(+Ope8fV/_zpb,-x~l9 \FV6>έH CN%81Ǝ XmA:6:HZ*4XxYN !  @A(raP9[tea^+p@Li [ԃسRf@ 6Luؐ$GQ!nӈBX PԌ8b@Ya4\B=zjrFoQbmasw(Ks\L|2.Ma霨55pi&mX8_B3hi7$o*Q4 Nx?5qqa#T+^ʙZHwno$?fEsӖu+shqOK,ch;{yJI؁4ex0X B0*AxCLǎ2rf抏F #4McKN5Cvuޓ, VY*n]HLcDI!U"x+Mz bbROG{~MڕhqPAgɢz.<ޥ!64,Ð(@LL#AA j<-:ؑeRD,Ѱ"~4BۂMC VRT\2ROEF,b DVZ)FDT!xd%LTKT]37ayP#TptvK5ݱXj3 Md~ {c4^=UڶΨ,@0*A($fvg DP,0Ԁ(vbwGTre8TS ĕBH>O$u-͛T^CSZM(1|YCg?B\?*rׯdYDE%yLDłHz{8"\Jw%uc]p(c]i!j*z#o!A~zMrvda z{tgO\E-55pA @RtE 5˕Q5Hfj,i3Yʔ'HN;&eS2&m iRj`i{$h.CM>mC&QFPO2  `< ̀ʥ -Si ƀتɐ1䍮QRjF5ju9pO1  $1Q*12Hb.݇IZ8Z횿IROL0 C0J x.(4B4*c"mr;E5`Ә3[P*V}[\}HDC Y؜=  $u-nQsƂ0t*0^>;;6Lv| IH%YE¬۽T>le2ꊤWc;U;0M)y-}[G m, P"6nBNf稂+ܹY+j0F>ۺmum %NTTXKvlȀSQHem$N _-I"A`ܴ3{ek}q{ĝ PyÀm.)P x R`'plXkW%w6pd }܎j$2Kr`O$1ydyNy#p'BY'Tdb xct yg nم?L-h-pJ$Ro~.{K7hݴwOHbfm1~2_Ff9󔅸ؽES`ؙ"_}u_6LRJԹ#MUVbYrf)dE-U+e|ZvUg߭7R^YvH$⇑딖{IqЎ}M_dl[ R_l"M6|P@$CQUu&`(*0a*3 3PXpd0hVi*<5pܵne/UB[%WH.Z_ C D;>ӬK{.AAq!x茆lw$#̪n9(ms6̸Q[6y{~SioOyyf~ ^oXT.,4"A8>sLǿ?EQG&MUJCO4&Vɪ D`̰4T( Vb lHW f r;puFG)BuAnGd\aO1b ?L坦3 [wGPL+JD2#sʮVS*SLȞ~^4~״bU]FCSr)jQ&9ə,~@a!tMLJӅܔB\sy"d0Ò$ AKa}LmX?ױx8#rsZ(8 b uߡ#+>NJ>m{ֿ ߘήOt}&$ FM ɪ0BX2S!K(FpB?FBÕ>GW)cVt#Xf=fw瑣+)wk~_Gb3( tD4Vd&JaNxcpɩgOL%C=-3)*IfI <"2a1)ː=C2™ec5.Ƨ"jҝ2l,Wռ'A0v@2P|X< y1 cQzWz!z>_3'<,@! -q3sN.Ezx!iCh?T,#FH"\k]ɠe[Huԍw8nt/e[@6 8qbC `ڬSSmIЊ)XȪ} uBt8I)DVUYZ S6,--]40pPJ6,YS6ؔHc"iܼUމ /*R+&0\h @h2F P0B!CBpaQi,bcJY.cg T(* C 0.Oz11ފ3VNWNūk1W$a[/}DgCr manW= =«2%JeGMG`?j۬:93.7|nXt#qoMJgXPˁ-/ iBDo z=%h- c1|]3q,6DfT'k5fY˘"1;ʠmV.;#1.v_2`P+SU0iEMF홃)䔎%,h|UQDGw͔/6\k ޷,r$lɰ<+%X@C',0At< EbbJCŴ_(3Y8 Ḣ8[܀~'[w{ aV/=g _U68Q5O}@Lht=3٪mRyOEEK>zui.ߕ&Ij-J1{旃GI#(5@˧!:.(I)m ,C`(ec\O!X{1-J&3ì$Z9*~,/L㨠hDyIl }@1l704Jm)7FqkkGOE{mIgIt?ԉxSL̤_ṿX={pK+eVZRIɴ`f¹D۔UڀpR Mg  #p5l'JR p0hk 4\ @lTvE*&٣BsxhGr!P0 i/|!ja]t>,ưlueY]*$)I< %_2ccQJ9ȐD8!́(Æ Ay8D!1Q 2$%MG pOZel9%gs8v5f~lk)O d|DhqQ.eң̑fj9B*iI7j k'0d9;K,))M DOs qh$՚ge4!o_RLIkpBYStˈd0B=LIpWY^O\V"t*:Bk§vn, ƌX]sff_vZ_h75~b1m*lMR=twTk$r~ c)C$Iܚ;@f{[C&OSl:Z A:jm%:)Z|j[(ԦQ,LCrkrnHOEn~d&jCyKr gnWMC,-/ */&x4,yWZrkqL#Mrg=6ʠQ@n'?IG_4#WJR&1tD}D7N+sEAd 60P2dL9BL? cuҜÑ;  nxהVD. A5?㐬^?Wc6GN: UΟp 0o̩:* L0xg#C@-6^UbH.Ld|%Kftm<,~TҪ(j E GRۏfE8 q҂ HǬn&:0:BM7JIheaQ=;j#ӕ|BydtOnne AXySXYGPͩ,+x`BB`5VFPBĥ 2ڂZ~<$a\/"IzqzZWaC4Q)\5HH$b5̪Y;K,} G:Yo2S}Q"4CS )8MYKW)8ҐP$haIa&N0УS`2trXV^6@"ݠv;B(j2G7:4X+\ 7r}_y332#DpPd&iOKYcr-gnE8-#)pAvQG qfG ,802H=InyK`"$8riE i9<*(3LޢM\D =$W.Da-a>R(CE(Y j[QNYj#l } (Hfz2Qr\_4mƬn# Yq0&"! D[@ĥom:r9bG]N\X.k &C(@ "6@MFnƤ%,A /Hc2Y2arih/U^HlbV]:,Qԑ+E&H,z>[ .lR r[pudRʂQ`e:^jlzSnqbL!g y6]yU|,U !E J B\fb^R;`R!\RZtk=57\;k,.a26 %p]h)őIg=vIԦ|ŲǡwXruMQ@scS8YPt:$*˲ƚ 5_&*!m;v\4Rv72(f;%䐍hCŚXNXb*sQ۷'U|q^%Hq1K΂K[Z(dhc/Kpyzc)\?-aW f=p0=jMa7z&=@?+!>ٺZ{VBy`&DM(PMQ eTCiRn! Q%m~؈׉ZI[J:ԏZ ]R <7m,,VDνog|kxϮc[/$.mBh'j&Abvia6F9. #{0U1 K$OE($cǚp H$?Y> aԖғ{>  wP vׄ,b9a|=_$=8[N4nt P/<X|td8fŵq_Gqa& JĉꙂ;N  HջݍY26>[Ԓ8Dgw y[;:OVFe+fy ,LQi:mi*"W+ހL\]2癠.LG^A MpyڅgY 7 {)^SMul$"JVۿ( Cٶ"bB &2凄#PG)oIo_fa=N.d 4\(igN#!Ek(v?flcZ?Y8}1-?9id'lMy{pGg \= aɦe0Ƶ(DX;LjXi7%s ώ Zufh{L)1~*'pF!:J#y*(JX/G-5Mc1W?jz3ǥTд^TRRKR Ŧ7.=1p$ p@2x  @)C%( K^f<*xЫcI֘/8+/J)yŀK|0= 恪G$Z] CoCV8Jpa1}TN[9֭?IX8"ag|J} #vdC )x3.IZ%S/K: ~e]zB=_(ʯm$<"IpŤ``#@/td5s >0O6W;CIť2m2)~PWWr2,kJ"#䱃R Nijq Mv(1 & D06-FgSn Y5NKt4A3q@а֥p\Z5, 0lǠHkӗ:2+jr3Hr:$:I7*v- u?.dDlL{pj gn[ͥ8qə/鵗}@dvŒ,JQ #LE1^zRy Td0R<a u݋OTシ>Z↫&/aʟ>sJ:z¤A.V-u堀 ik D\dpec3]锒?GDϚb/DwV PǤp]:Jn- NE&\g`@#tC0d -(D `f D 7n`X)'(K>R)di>[`,Pb.cnSjXI;@8 YE5/%#+RlLJw3"V2IV'ZQW8ZFLvNjv^Ԫ-WÂYb斁s;,/="X:7]9Zרּ p 3W"xR|@& -I #ƕuc1?l)Hbt Z 0Ak 5I>ܿ¿kᮊ`qP*!FFF I`<1B&(4 ]|Lq8 )x`_0 B0PPo(1@`Z JӢgy+*Z 0yv d 'j {{pfe c L!a2s ɿ')=0騭9\ۈAq%?f!Lm9ˡ95Q7}M©!ugk**.Zi]i5$g?g9](B $Hcb3r욇DRi&RF|2\aچ#pQGIDzG׏FȪ"$)#`\ k*b<0P@GGXQV*a'Q`ॊ2WtU Rr*/vռ JwKR\Н |fR%َ{-幺 lSS[>SXI(MWYKu5Y_߭Wu\jgS\?5Ez^|'gRol4_P#2(4bU R%@:ՁS~?BI[aE8g..uʚ*~3: `8XyBC(OԨDD74L(ƌxJC>HÈ;I60D1HH5L%XʁO@SLӣ!ѯ+&1x8]DkJZV*+ Quo% 3KdhO:rfgJ m7Mo ]a(QFJ^|q%_e"ܥ1~MM1w:ZY$R~j˧)iP7WkVJn+7Aj1 ]VI?7ۚJc߄J)&62'4w]R[b 40!C2T\ liU#ԘXU\SIT1(B%dPD=P.n/C.[eoj-O{Yo#R3;bXz  `%Jē4Y.1*!䰈Dve@tq jⴰ2xf~b Ѩy}$)N2djbUi2YV#萟w⹉_wxR5ƞ<0vukgLs17F85e+,gBd&fNZ{pnٶkJ};-k gu-0nQCȬMjĪ;&Vg:8Ԧ)WYSRO7场U1^9/8O}٪kNݷy{׮ݜrn~[OekZƿ)O97A<1MQѸq%4(TH]EʕR~ۥ pG!"Z@#.qUJ$5'-ݪJZ E   IƦTfF,C& b1>!+P@q"H ~ t5_5aX{G6NeQQRkXQJn,lO0xy~YJ7zj:K)|f(/ 3 @oVR֐)/&78ܮ]c @P#y7#%9E{+Կ.z|JU^m31M{E_*H8Lz\1A" @8PKfgM,҈RۘäC$CC(x: "9WL)z pH.@~T@"x:G ?&FM&OT;5S Gd'`SzpyEɷkLmCe=(Z&3>^#ZQ3_b]6uvBmTH%˯=ZdVNz_n:Z/mG/^iKk9o♡҈:T@@4k P8#i@"* T909)_LY\QA;;Rqз *?p:lŮ&77+Tna2©Ƭo?n)bc?ØIN3!cL|*0@F1ǧ1b (Th$J+7 ĶFR4(ƣf ąP2%tDHRUc$"ʮR)a!Nlwn@y. Q&=&_BQGN^;A8b骫[F(q:qN`RQMq-Lpإ,H!T-KLvGk o`SHsWDjPʀ)zÚBfY8vxh Ӱ)xY2td"ғn`/`ɘ'v#H䚀!€[ ,br Y(r'[YQޅ =SW(,9C[6N1!#1@ (5( _#p(9\ lN;0@sk#@U0Qd~Tp, G`XdabӚ{pɂkLщ2-ф(>Oʐpx(R삆u+IZ톌]Uf5:Vujl)+E&Q+R4fdu Rސ,myUq6g|'6}p!a,R#>[#6Y5x)byZAC"\c"8x@LP g3 Sq(p&@v p96ihRÝV}2C`W3?$)€wCq_O"v)ljF|4V b5cXTD`IKbcBj  @EKF D2'D x481vC pP82^˸24%Ɍ'k\KN*Q4CMkJl[NT-*ZJ{*m ( 띠ƺP5)YXbGCCkz .Y*0qMQgs?̙8; v@ % ,! fA .^ >FՐ'JX 7 ZuZ%ȤjO:-a Udiu%'ŧ*sDy AH0=fF'#L<2Y6*:ARD#۠T9;$9pA9mE47Whr'D,1Tٖ踘c= Ad']L+{rq$eJŅ0i'u(Utz}IJO(pļ% QӱI.'L*)tDrU%ٹxHe d)Ж:Sq`8Hgfs^ec@ė&H6j,7N0h+ ,DgBXĉLp@Z8P&4 j.ҝP*fT[yA 8AY Cŕ9!jyFs˨, ,rgw%RK0BsJ&,r90!qLTG0t,EԇWF @dV 씈r)|Om ELI4hwlZjH$^(qލܣ<ҠjΟwKF$Ȣt/^onlo-y]GuWV^}ɢ)NɩƓI<(Y>!}yAqzМ;ISU4BmTdඃʙ'*IG Hf_meBa!+?# O~ik:!,Y oIyʧ{#7-5͵ڶh4CLD31t03!M@0¢#000<8$,t2pg*r$i9GX%p36 Pٔ,e`Hgm9(᭸ d܀&`ycplIg \u.e ٜ=pa.D#W-$BF(aQRZqSϓK)\iQHYb0GS+GT9!CUѽ_ ^3Zڡ]%r%x nß`Gŷ@(qL0 M xBI<(h02!cA.ӂ)pMiu$%n;Ic0`qRc IBW-ke`iGl lړ+Rhg}֕RUe.Tu>}Գ* =Ju8ѓ||]:fHD0d@~B c"c[vynj(<jR֥Hleʓ^bdxk\G /x~*K}Q?l/3 4Ț dbě@&Y) fębc=M/Y8aSiʑL%ҹL흗D]|gek= uHDlYߠ@!i)k/LA@4RXNxI)odqbIc2!JuiO)j_ˉJQ.XcΘ1"KRXoΝN2!HN kK 3T^u#VS΁oK)%;SbaWI>Ar$.]qIZ=V6:W*iWՌ3[RiRfo'µ/ ~k,|ANR#  LGBMYPw@Fi"qt 3Ww8neix{i0yyt̮f+c1K|Tsp+aml.aweZ;9V긇9=m{G(OVU`w? pGd&b`6\bCbC 2`Z-0 HYPA !LyX*0u7)*`BjG4@ZaNpCidA_% x39bF9+SHNhu)jS Vnwjg1Œ $VW#nP++XVUMp{ů+eq|ٺ 0sOI_ӂB D-P-%k)uNZBd'5QEU>߂YW.VSn//J훸W EV9+ H +8ߠBZBbmuMR_l2 ´cx}BH. buAHT5Q`$S&8KiK5vK kx6Cz%1d\cM{{r)k*n:a-')xH]%YtT//ʠPZk2\F$d.DO$+el'a 96Qm#S#XK%ihwDJIjiE6]5t[_kmMێ QL`1FRs h[,-W0{zi_N6i|4)$U+_҈!I'xqj*Ha1Qw-+U#B~ Fٺcfa@` %@rk9QPj%c͆5ΛUt7̅|tWae/2ϊ&nǢRRq Oy-:'&udͦk NYdMQvẸ.TB* 0beI>EOfX#pE}{mo|ܒ[޳kE sG=cVd63 A ;f5?GaEXUڭƼd ;3@͕}?2ҝuc$1N{'[ɧMbe1 arXG k ǀ? !TIsN ng&]GFKpaŏ"u?N_n}!#W]S>1ʏIO{ڜ{bTz `ˮL.Ya"sF㑶d/_NXKr g'nE-Ӧy2pP4q(z* {W%yaPmYg'"cgy~Q3R Zƥ0L C/H8$)lLCSEitƀ0K~ ͺD߀Fb L4'*%YCbBBGDſoU899UCi"-rH*jI0"p> z{f % JXR! Iۓ-X8 I B0,0HMYa Kgtu W%"B3ABA9'_s,k6mp_sn+?) [@dj@1\a1 (NH(Ea.b C "0FHj!J(`2d‚aPʣW0"AIZˆǣ#TfdcSz{pygO\}4MΞp+\@Cp LB QgHVYYċ[R*1]7}]A쿆V)G@RGl 1@()ުlS` NY[IhD4(ԍyTI{ḬBǵ2<9!Fj[ F~daMzcpJIg*^;Me赇x!h`TiQ 'bΰU NXZ2o 5ťd1E;,+z-W`Z6Qm%Q*LjRGk2ۘ( E$tkX!^K`ZRTt.(ΒdRK\5T3ݧ|И]^*zxPAa&Eu9+j?K CLҁOO lPӗP% ٌNC LdXh̀LxuR|G Dc7 \=@X FNH@ar6VnJ#H ? $heb)DRiJ. ߭-AD-Y\GWedx٣Ƶi3dkǁ9մ ri^6ֵS i&FRa`/1d3eulHqk#()[]]$U_l蚠GNԀZ-PgҝP&&Yo8ՊEr'*#t-VH=/{\5`0oӿJDCL@8TPa s>h(#.Uˁa<uI U" Rv 6iot;b8A_j@)L8p@S3 jXd\,vŎ!EisHz+ɖZB0 zd(e9iV5CcqK, GrRjwO+JX]TJrq4cO,p9%Σ=\Ԑ32 0_\!Uy)ϳ: r v "!c%9 H`IJ\\Yc MILɜCC-$bwf3`HUeяIJI"ԥ47Y')}"3fsGVg_8yFLTjIx  H]%\1$D` $E hX$LؘH` x`ʍq+* 5\‚27I16L+@1 (de9cpngL!%.-²g -$sЍ?~"4&ebH1 q^C_I VVe l|h(nj1Qk>?yҺe:jR,XX;G"9(<$ d5S^0_(rq5My|G]oܺy`[ рt 4/zҰaGXd']b;Z{pkg-\=?epmȔkZaHG*K ==ցtuN ;X=Y脁P&9;{ST4" 3)ՔxD [P\o#$3cUoGzNǿh(߱߁~}P |qI <*D4>BuL9'ꡲ$unzMm^22oJX0D?$N1N>Q%CYǑ|vSO8] Dmo ζrb@G U#AǨJf@b 7}&ZC42x`B@KƬ 8P(m].cO@P(уjB7w>Dp01 @}CDxcfӤGwyn.Ȕ6iu.a]hLTb˦7JW3۝8"8x;%~cjg&- X1!8GTA1BP``dJx[,6Yw v9ov_w<^x (@\15.E,`H$}L٫8c.t 3F,ibv`D@2hF8wHxlWs72סtC|:MDA C(EAG`a 9qd D_KZ{pgj]g \6m()pǁ8Fi<>:T'zƞ*QZR.Us{KlTq}iG7koXq,;$RQuX?3*} UʙKng-y.k%T̀n`qL# [:M 4/H  i.,eսSgʒ( j.5a`FţAQ&J0 y Ʌ2PtYq?Za FR`"d1oR㘂`ҁC1=vF@f-`b,1T>Fe2 #\mۆEv K%*ߖ HZ(iZSK&?{c1Bfo ۓ$uY怈Kckʵօ#W] hL/1aґvr@ +S#byD0#`ŲPH/*~'9SPg1z(d*d3Lƛ݂Ahs!KNahH:nq%C$fL/Ǻ&CYKbI/HBJac I葠1TWG3b˥P1tK"IsWX .UvHR`{fm-)[DLYv9>!o˚RԍqqNXXv WdfaYcpɦkM\Y{ZkqHg5I{F.3)3mA~ p)y~$M;3N81S#BH ) ‰3 G[CB,>S8XЇ,D0 "ӌy *k uȭCr 2 ()4-DܾŁhH '42&ǩFkF.?Vyߖ"YfX"#1{kT)QiV.݉7OsQn|NC KQKT1D+Gz6UF^wf:5 Af`YP *g,ޗ8 &FD:J#jҡ) b9Tt0̓ߎ>u!h,GqD~p*s.{_Ce;"]Nf2bRpp!Hh`@5LP2 e0fV(0 aWBƐm2#QIKTFB[dbzpهkOL6wi0Hb* PLheEdX:ޝtsV!ٓ%I}d6ybSLg'?4a=\~erzC*]жTrr3z/XJFC /GP x`K'e9:мV0f[Xj D1ȸ.6J(gk*M\ Xhؖ <`R]` y0֏ 4̀@Ŝd@$Bl,p$HsyPF2( ;!3,f K|`IL&$! % @=0 ]PBL.n!l/u-ڲ('%lh Fؔ(||J?/x>%bC3ek-PP}#2=?RRs9ʡY;0fPݚn} - ADd4D4BRPElŝЬ@A`D,K NZϛ `gju=Ғ!`),I5qOa:1Lt:<Ʋ@PzY?( "F`J1@Ɲ,!j.2\@f05`ZZEwUvOfNSC dLA[J^2VY)J7O`n)d &` {tuie\9iɪupYTS͙?V.0Ը(Nq GHGߘT TTn'"B1#^FOu.#(Wt]V X'JN뺇*[lVBr&<2H`z 5.b*eXd~18 b, D. 鱴UuG~Q-2- wK؞Y02I9h$C%G1KUfs6 H! * *tEQ`)*n-5K,//m&PÖ>o1OMKu8FwZ3iy)CyG ZV@Bke g T9`MzF !>C$P*&]=Z}>kr k@SY";FsL`@b1.L%电ot;Y:*s>1bc 0ѳ OC2p*-2U0!!U15DH"JaAR"0Ɔ#Fix: "0Lب(_-2(6PaǝtJ(y(0qI0p0(8;nK)0=7F5\]I~38]Iޭ-YW3b+iy,^Gw+2dG8*&~ޡ09h4?VÙL/¢[Cnfh?k&dHob6D,&ri0M!!Ԃ܅cSv-}؊2) + ,yFhEk{77wIw}_>LDEax 0 B-T$*ި*+h2-^n6UEQi&RauRhUCx똛ODZE#ZHȻg>!]#~h89A#JtɊ D<8/:zD09)23GK\h)TLX; ZE=>n}$٢uO+Hi'Gzh)шcrՁ%2J8eC-dyo {ܘ%IB39)u%0 (\65PE@ xueV`@Y3B`0}>qB)+ȴ+H\0pvғ&Aƛ:95rMyIj^ecU2ŧ2E\+%CDxsVvi*w&"0 *E:a ^AQ1$2&V!RwFhߢi4~DW Zx"YkeroG~ӛגd-wҀGj(<1q3QH\QB>0bqB1Ƞ^La< B0D0L J@( ZH8F2Х}D@“VD3@8@ ˀ]>OEX`,d&_3ZcricJ!%0k Ô'u=(i,+K^bKD[uv/j;tֻZHu>e]{cdkHN{MNOn]f'JiybN3I=bohbװ,Z7'/p5g.v 5'Hȼ!L¹P&EҊRÈ<K6ʤ=3-jU ߱=aT80DŽqoi 45<[~FdQ !bDp:9>CF1TD/%(T2*s"#+m Sk"\R`.p( 3OǪ}2% dARDyBA)=>:>|Z8 HKL'sKU:Fi(c0"/>Q38P">1~YnNk3&iXh ff&eXXN0@0I56CE ꊈ*_`}C,#Zkxcf)7l~N52g#4`ÑIDB"W25N4=)0Hv-jG IyᯔV˾Eh,BT` :"AIzwP@JA£ٌ3o#}B7dކ&cλZcpaDg J6mgxN}KeUHRy]iKZ[U4BֺVĄ/*~ֳ0:w:enK[[u폕@‚߹&s>= } M)@FpfR|Nn*&Δ5VT}İX|OzbP&]/r&edn7`L[ a`G⷏?ZVlٿRO.,;ty'"S_ X"т,`k@pI3ȐXc_Br6iaTTksvN$yQ^ƕ'ОL6'ybXg/Z$-}e(GJ벣ܞ!B]iZ͚RڕyJi?|csYB”%oC _^';0i@:U$y4t Œ3$v۪k; Ou*0Q؛5wT=5,Dir>m?jG/ P\Do*&*7X"G-oR$a8@6 Fw.! 3¨% EOR.v^_&Pǭf\]l-gU*}bwf'$8PDXS%Ь !R,!O"XޕqFr\R*EDd_Ycr~)Yk^ك=L-i.ٽ5BiRۤ9"DS%я,va =Dg I_EL8J @ f6jf3R*B`Ea$/@ V8و~%cn ǭ[X0"~2P~un> +kػÞdk+Sq 4A5ELْ(_"=wmko"P4ar@c*BcC'woQ YGǨl%LK+I~UeڵpEqx?L^'x>ވZT}p{m_n`oڛeP8GI-j ;*ap0Ja26 1%^ris"z{RϩB-cզϾхW\k Ta-" Epp)3̔m5\)DEkS2\ۂH YV[UHFԚmrGAF>s/P BPAL$< X4 ']Dt/dMҦ!$ofx&Ddf\Pe+˱I::mHrMDyƌ2ϼL?} d;bb~ н[g>K0?-1~A Ppl3@ gYB$X Y*éQP.xz0G_q{ 3h$TL`eA",fI,9sME$KXS{nbstnO!2TDc.@KLC.CbY55vmCloÑI/25mÝ WeXxJr6i(s0cw%d'cSy{pio2\EUߝ斵@_*Z~5nkߞ3z-}&dMEeT.:0yJ){my+C75+K9Rjlo}J 0Ʒ ^uX&pDaNJ#>΀3ENaM׭HJ [P7".23"hE;Z 3%EnLJc9zGSMFDIS,߿0ʝ@Bhёh4UE&keh`@&@ `L z-m Dj_Q:w⁤)_g!A_Ao/d2a $̽U@몽t0h]籃.f}4*ڳH5H\kn̥t#q{W3\\4λԐ%K2ǦtZjU7Z3 2Hv|hrUx7:eK.㏿^Rľ7Õ$4 In,WHIڕ0!O@@"ጆ8Jcx r:E+Nd(]I4(h@% ap/) /]J}T$!rU%&ynv4αu؆\/-iz4(~}HD NVo <I3 H%DЦme2B7,4KC4M=nMK#4ѩTj?M}$e9=ƝFֳA#xx|"o{+|w9ܘyYy۩n,W&9cȋY rFt0ө,%!)A3^DJT"*"P{KZֲkZڴV.ͭwYZַͭZ־޲ZfӬZ.+ + `+WM)6)p+M܂})}(ora!J0@%Fs,q$3;"&LR)p6=T5ADBS+"jC<)K^zȑALtSa0Qq]+]6+ lSr W܂⻁_/7WM*LAME3.99.5goconvey-1.5.0/web/client/js/jquery-2_0_3.min.js000066400000000000000000002431601227302763300212670ustar00rootroot00000000000000/* jQuery v2.0.3 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license */ (function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],p="2.0.3",f=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:p,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return f.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,p,f,h,d,g,m,y,v="sizzle"+-new Date,b=e.document,w=0,T=0,C=st(),k=st(),N=st(),E=!1,S=function(e,t){return e===t?(E=!0,0):0},j=typeof undefined,D=1<<31,A={}.hasOwnProperty,L=[],q=L.pop,H=L.push,O=L.push,F=L.slice,P=L.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",W="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",$=W.replace("w","w#"),B="\\["+M+"*("+W+")"+M+"*(?:([*^$|!~]?=)"+M+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+$+")|)|)"+M+"*\\]",I=":("+W+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+B.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=RegExp("^"+M+"*,"+M+"*"),X=RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=RegExp(M+"*[+~]"),Y=RegExp("="+M+"*([^\\]'\"]*)"+M+"*\\]","g"),V=RegExp(I),G=RegExp("^"+$+"$"),J={ID:RegExp("^#("+W+")"),CLASS:RegExp("^\\.("+W+")"),TAG:RegExp("^("+W.replace("w","w*")+")"),ATTR:RegExp("^"+B),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:RegExp("^(?:"+R+")$","i"),needsContext:RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Q=/^[^{]+\{\s*\[native \w/,K=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Z=/^(?:input|select|textarea|button)$/i,et=/^h\d$/i,tt=/'|\\/g,nt=RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),rt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{O.apply(L=F.call(b.childNodes),b.childNodes),L[b.childNodes.length].nodeType}catch(it){O={apply:L.length?function(e,t){H.apply(e,F.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function ot(e,t,r,i){var o,s,a,u,l,f,g,m,x,w;if((t?t.ownerDocument||t:b)!==p&&c(t),t=t||p,r=r||[],!e||"string"!=typeof e)return r;if(1!==(u=t.nodeType)&&9!==u)return[];if(h&&!i){if(o=K.exec(e))if(a=o[1]){if(9===u){if(s=t.getElementById(a),!s||!s.parentNode)return r;if(s.id===a)return r.push(s),r}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(a))&&y(t,s)&&s.id===a)return r.push(s),r}else{if(o[2])return O.apply(r,t.getElementsByTagName(e)),r;if((a=o[3])&&n.getElementsByClassName&&t.getElementsByClassName)return O.apply(r,t.getElementsByClassName(a)),r}if(n.qsa&&(!d||!d.test(e))){if(m=g=v,x=t,w=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(g=t.getAttribute("id"))?m=g.replace(tt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",l=f.length;while(l--)f[l]=m+mt(f[l]);x=U.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return O.apply(r,x.querySelectorAll(w)),r}catch(T){}finally{g||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,r,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>i.cacheLength&&delete t[e.shift()],t[n]=r}return t}function at(e){return e[v]=!0,e}function ut(e){var t=p.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function lt(e,t){var n=e.split("|"),r=e.length;while(r--)i.attrHandle[n[r]]=t}function ct(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return at(function(t){return t=+t,at(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}s=ot.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},n=ot.support={},c=ot.setDocument=function(e){var t=e?e.ownerDocument||e:b,r=t.defaultView;return t!==p&&9===t.nodeType&&t.documentElement?(p=t,f=t.documentElement,h=!s(t),r&&r.attachEvent&&r!==r.top&&r.attachEvent("onbeforeunload",function(){c()}),n.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ut(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=ut(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),n.getById=ut(function(e){return f.appendChild(e).id=v,!t.getElementsByName||!t.getElementsByName(v).length}),n.getById?(i.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){return e.getAttribute("id")===t}}):(delete i.find.ID,i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=n.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.CLASS=n.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&h?t.getElementsByClassName(e):undefined},g=[],d=[],(n.qsa=Q.test(t.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll(":checked").length||d.push(":checked")}),ut(function(e){var n=t.createElement("input");n.setAttribute("type","hidden"),e.appendChild(n).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&d.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||d.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),d.push(",.*:")})),(n.matchesSelector=Q.test(m=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&ut(function(e){n.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",I)}),d=d.length&&RegExp(d.join("|")),g=g.length&&RegExp(g.join("|")),y=Q.test(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,r){if(e===r)return E=!0,0;var i=r.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(r);return i?1&i||!n.sortDetached&&r.compareDocumentPosition(e)===i?e===t||y(b,e)?-1:r===t||y(b,r)?1:l?P.call(l,e)-P.call(l,r):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],u=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:l?P.call(l,e)-P.call(l,n):0;if(o===s)return ct(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)u.unshift(r);while(a[i]===u[i])i++;return i?ct(a[i],u[i]):a[i]===b?-1:u[i]===b?1:0},t):p},ot.matches=function(e,t){return ot(e,null,null,t)},ot.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Y,"='$1']"),!(!n.matchesSelector||!h||g&&g.test(t)||d&&d.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return ot(t,p,null,[e]).length>0},ot.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},ot.attr=function(e,t){(e.ownerDocument||e)!==p&&c(e);var r=i.attrHandle[t.toLowerCase()],o=r&&A.call(i.attrHandle,t.toLowerCase())?r(e,t,!h):undefined;return o===undefined?n.attributes||!h?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null:o},ot.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ot.uniqueSort=function(e){var t,r=[],i=0,o=0;if(E=!n.detectDuplicates,l=!n.sortStable&&e.slice(0),e.sort(S),E){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return e},o=ot.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=ot.selectors={cacheLength:50,createPseudo:at,match:J,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(nt,rt),e[3]=(e[4]||e[5]||"").replace(nt,rt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ot.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ot.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return J.CHILD.test(e[0])?null:(e[3]&&e[4]!==undefined?e[2]=e[4]:n&&V.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(nt,rt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ot.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,y=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){p=t;while(p=p[g])if(a?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[v]||(m[v]={}),l=c[e]||[],h=l[0]===w&&l[1],f=l[0]===w&&l[2],p=h&&m.childNodes[h];while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[w,h,f];break}}else if(x&&(l=(t[v]||(t[v]={}))[e])&&l[0]===w)f=l[1];else while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if((a?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(x&&((p[v]||(p[v]={}))[e]=[w,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||ot.error("unsupported pseudo: "+e);return r[v]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?at(function(e,n){var i,o=r(e,t),s=o.length;while(s--)i=P.call(e,o[s]),e[i]=!(n[i]=o[s])}):function(e){return r(e,0,n)}):r}},pseudos:{not:at(function(e){var t=[],n=[],r=a(e.replace(z,"$1"));return r[v]?at(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:at(function(e){return function(t){return ot(e,t).length>0}}),contains:at(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:at(function(e){return G.test(e||"")||ot.error("unsupported lang: "+e),e=e.replace(nt,rt).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return et.test(e.nodeName)},input:function(e){return Z.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},i.pseudos.nth=i.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})i.pseudos[t]=ft(t);function dt(){}dt.prototype=i.filters=i.pseudos,i.setFilters=new dt;function gt(e,t){var n,r,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=i.preFilter;while(a){(!n||(r=_.exec(a)))&&(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=X.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(z," ")}),a=a.slice(n.length));for(s in i.filter)!(r=J[s].exec(a))||l[s]&&!(r=l[s](r))||(n=r.shift(),o.push({value:n,type:s,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ot.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,n){var i=t.dir,o=n&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,a){var u,l,c,p=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[v]||(t[v]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,a)||r,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[v]&&(r=bt(r)),i&&!i[v]&&(i=bt(i,o)),at(function(o,s,a,u){var l,c,p,f=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,f,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(p=l[c])&&(y[h[c]]=!(m[h[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?P.call(o,p):f[c])>-1&&(o[l]=!(s[l]=p))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):O.apply(s,y)})}function wt(e){var t,n,r,o=e.length,s=i.relative[e[0].type],a=s||i.relative[" "],l=s?1:0,c=yt(function(e){return e===t},a,!0),p=yt(function(e){return P.call(t,e)>-1},a,!0),f=[function(e,n,r){return!s&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>l;l++)if(n=i.relative[e[l].type])f=[yt(vt(f),n)];else{if(n=i.filter[e[l].type].apply(null,e[l].matches),n[v]){for(r=++l;o>r;r++)if(i.relative[e[r].type])break;return bt(l>1&&vt(f),l>1&&mt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&wt(e.slice(l,r)),o>r&&wt(e=e.slice(r)),o>r&&mt(e))}f.push(n)}return vt(f)}function Tt(e,t){var n=0,o=t.length>0,s=e.length>0,a=function(a,l,c,f,h){var d,g,m,y=[],v=0,x="0",b=a&&[],T=null!=h,C=u,k=a||s&&i.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(u=l!==p&&l,r=n);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,c)){f.push(d);break}T&&(w=N,r=++n)}o&&((d=!m&&d)&&v--,a&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,c);if(a){if(v>0)while(x--)b[x]||y[x]||(y[x]=q.call(f));y=xt(y)}O.apply(f,y),T&&!a&&y.length>0&&v+t.length>1&&ot.uniqueSort(f)}return T&&(w=N,u=C),b};return o?at(a):a}a=ot.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[v]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ot(e,t[r],n);return n}function kt(e,t,r,o){var s,u,l,c,p,f=gt(e);if(!o&&1===f.length){if(u=f[0]=f[0].slice(0),u.length>2&&"ID"===(l=u[0]).type&&n.getById&&9===t.nodeType&&h&&i.relative[u[1].type]){if(t=(i.find.ID(l.matches[0].replace(nt,rt),t)||[])[0],!t)return r;e=e.slice(u.shift().value.length)}s=J.needsContext.test(e)?0:u.length;while(s--){if(l=u[s],i.relative[c=l.type])break;if((p=i.find[c])&&(o=p(l.matches[0].replace(nt,rt),U.test(u[0].type)&&t.parentNode||t))){if(u.splice(s,1),e=o.length&&mt(u),!e)return O.apply(r,o),r;break}}}return a(e,f)(o,t,!h,r,U.test(e)),r}n.sortStable=v.split("").sort(S).join("")===v,n.detectDuplicates=E,c(),n.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(p.createElement("div"))}),ut(function(e){return e.innerHTML="
","#"===e.firstChild.getAttribute("href")})||lt("type|href|height|width",function(e,t,n){return n?undefined:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||lt("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?undefined:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||lt(R,function(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}),x.find=ot,x.expr=ot.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ot.uniqueSort,x.text=ot.getText,x.isXMLDoc=ot.isXML,x.contains=ot.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(p){for(t=e.memory&&p,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(p[0],p[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!a||n&&!u||(t=t||[],t=[e,t.slice?t.slice():t],r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))x.extend(this.cache[i],t);else for(r in t)o[r]=t[r];return o},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){var r;return t===undefined||t&&"string"==typeof t&&n===undefined?(r=this.get(e,t),r!==undefined?r:this.get(e,x.camelCase(t))):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i,o=this.key(e),s=this.cache[o];if(t===undefined)this.cache[o]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):(i=x.camelCase(t),t in s?r=[t,i]:(r=i,r=r in s?[r]:r.match(w)||[])),n=r.length;while(n--)delete s[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){e[this.expando]&&delete this.cache[e[this.expando]]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.slice(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t) };"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t);x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n\f]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,i=0,o=x(this),s=e.match(w)||[];while(t=s[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,x(this).val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.bool.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,p,f,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(f=x.event.special[d]||{},d=(o?f.delegateType:f.bindType)||d,f=x.event.special[d]||{},p=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,f.setup&&f.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),f.add&&(f.add.call(e,p),p.handler.guid||(p.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,p):h.push(p),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,p,f,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){p=x.event.special[h]||{},h=(r?p.delegateType:p.bindType)||h,f=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=f.length;while(o--)c=f[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(f.splice(o,1),c.selector&&f.delegateCount--,p.remove&&p.remove.call(e,c));s&&!f.length&&(p.teardown&&p.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,p,f,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),f=x.event.special[d]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!x.isWindow(r)){for(l=f.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:f.bindType||d,p=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),p&&p.apply(a,n),p=c&&a[c],p&&x.acceptData(a)&&p.apply&&p.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||f._default&&f._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,s=e,a=this.fixHooks[i];a||(this.fixHooks[i]=a=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new x.Event(s),t=r.length;while(t--)n=r[t],e[n]=s[n];return e.target||(e.target=o),3===e.target.nodeType&&(e.target=e.target.parentNode),a.filter?a.filter(e,s):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=/^(?:parents|prev(?:Until|All))/,Q=x.expr.match.needsContext,K={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(et(this,e||[],!0))},filter:function(e){return this.pushStack(et(this,e||[],!1))},is:function(e){return!!et(this,"string"==typeof e&&Q.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],s=Q.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function Z(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return Z(e,"nextSibling")},prev:function(e){return Z(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return e.contentDocument||x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(K[e]||x.unique(i),J.test(e)&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function et(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,nt=/<([\w:]+)/,rt=/<|&#?\w+;/,it=/<(?:script|style|link)/i,ot=/^(?:checkbox|radio)$/i,st=/checked\s*(?:[^=]|=\s*.checked.)/i,at=/^$|\/(?:java|ecma)script/i,ut=/^true\/(.*)/,lt=/^\s*\s*$/g,ct={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ct.optgroup=ct.option,ct.tbody=ct.tfoot=ct.colgroup=ct.caption=ct.thead,ct.th=ct.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(mt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&dt(mt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(mt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!ct[(nt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(tt,"<$1>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(mt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=f.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,p=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&st.test(d))return this.each(function(r){var i=p.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(mt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,mt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,ht),l=0;s>l;l++)a=o[l],at.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(lt,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=mt(a),o=mt(e),r=0,i=o.length;i>r;r++)yt(o[r],s[r]);if(t)if(n)for(o=o||mt(e),s=s||mt(a),r=0,i=o.length;i>r;r++)gt(o[r],s[r]);else gt(e,a);return s=mt(a,"script"),s.length>0&&dt(s,!u&&mt(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,p=e.length,f=t.createDocumentFragment(),h=[];for(;p>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(rt.test(i)){o=o||f.appendChild(t.createElement("div")),s=(nt.exec(i)||["",""])[1].toLowerCase(),a=ct[s]||ct._default,o.innerHTML=a[1]+i.replace(tt,"<$1>")+a[2],l=a[0];while(l--)o=o.lastChild;x.merge(h,o.childNodes),o=f.firstChild,o.textContent=""}else h.push(t.createTextNode(i));f.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=mt(f.appendChild(i),"script"),u&&dt(o),n)){l=0;while(i=o[l++])at.test(i.type||"")&&n.push(i)}return f},cleanData:function(e){var t,n,r,i,o,s,a=x.event.special,u=0;for(;(n=e[u])!==undefined;u++){if(F.accepts(n)&&(o=n[q.expando],o&&(t=q.cache[o]))){if(r=Object.keys(t.events||{}),r.length)for(s=0;(i=r[s])!==undefined;s++)a[i]?x.event.remove(n,i):x.removeEvent(n,i,t.handle);q.cache[o]&&delete q.cache[o]}delete L.cache[n[L.expando]]}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}});function pt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function ht(e){var t=ut.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function dt(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function gt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=q.set(t,o),l=o.events)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function mt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function yt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&ot.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var vt,xt,bt=/^(none|table(?!-c[ea]).+)/,wt=/^margin/,Tt=RegExp("^("+b+")(.*)$","i"),Ct=RegExp("^("+b+")(?!px)[a-z%]+$","i"),kt=RegExp("^([+-])=("+b+")","i"),Nt={BODY:"block"},Et={position:"absolute",visibility:"hidden",display:"block"},St={letterSpacing:0,fontWeight:400},jt=["Top","Right","Bottom","Left"],Dt=["Webkit","O","Moz","ms"];function At(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Dt.length;while(i--)if(t=Dt[i]+n,t in e)return t;return r}function Lt(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function qt(t){return e.getComputedStyle(t,null)}function Ht(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&Lt(r)&&(o[s]=q.access(r,"olddisplay",Rt(r.nodeName)))):o[s]||(i=Lt(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=qt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return Ht(this,!0)},hide:function(){return Ht(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Lt(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=vt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=At(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=kt.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=At(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=vt(e,t,r)),"normal"===i&&t in St&&(i=St[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),vt=function(e,t,n){var r,i,o,s=n||qt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Ct.test(a)&&wt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ot(e,t,n){var r=Tt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ft(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+jt[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+jt[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+jt[o]+"Width",!0,i))):(s+=x.css(e,"padding"+jt[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+jt[o]+"Width",!0,i)));return s}function Pt(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=qt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=vt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Ct.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ft(e,t,n||(s?"border":"content"),r,o)+"px"}function Rt(e){var t=o,n=Nt[e];return n||(n=Mt(e,t),"none"!==n&&n||(xt=(xt||x("