예제 #1
0
func TestRouter(t *testing.T) {
	tests := []struct {
		path          string
		expectedRoute string
	}{
		{
			// 0
			"/",
			"/",
		},
		{
			// 1
			"/users",
			"/users",
		},
		{
			// 2
			"/users/meta",
			"/users/meta",
		},
		{
			// 3
			"/users/abc123",
			"/users/:id",
		},
		{
			// 4
			"/users/abc123/meta",
			"/users/:id/meta",
		},
		{
			// 5
			"/users/abc123/comments",
			"/users/:id/comments",
		},
		{
			// 6
			"/users/abc123/relationships/comments",
			"/users/:id/relationships/comments",
		},
		{
			// 7
			"/users/abc123/relationships/comments/meta",
			"/users/:id/relationships/comments/meta",
		},
		{
			// 8
			"/users/abc123/relationships/comments/def456",
			"/users/:id/relationships/comments/:id",
		},
	}

	for i, test := range tests {
		path := strings.Split(test.path, "/")[1:]
		route := deduceRoute(path)

		tchek.AreEqual(t, i, test.expectedRoute, route)
	}
}
func TestBuildSelfLink(t *testing.T) {
	tests := []struct {
		resource       interface{}
		expectedString string
	}{
		{
			// 0
			user{ID: "1"},
			"http://example.com/users/1",
		},
		{
			// 1
			&book{ID: "abc-123"},
			"http://example.com/books/abc-123",
		},
		{
			// 2
			user{ID: ""},
			"",
		},
		{
			// 3
			time.Now(),
			"",
		},
		{
			// 4
			"",
			"",
		},
	}

	for i, test := range tests {
		link := buildSelfLink(reflect.ValueOf(test.resource))
		tchek.AreEqual(t, i, test.expectedString, link)
	}
}
예제 #3
0
func TestBasicRequests(t *testing.T) {
	testApp := NewApp()

	testApp.UseFunc(Recoverer)
	testApp.UseFunc(URLParser)

	testApp.RegisterModel(user{})
	testApp.RegisterModel(comment{})

	testApp.Get("/users", func(ctx context.Context, w ResponseWriter) context.Context {
		w.Write([]byte("users"))
		return ctx
	}, GatePublic)

	testApp.Get("/users/:id", func(ctx context.Context, w ResponseWriter) context.Context {
		r := GetRequest(ctx)
		w.Write([]byte("user " + r.ResID))
		return ctx
	}, GatePublic)

	testApp.Get("/users/:id/relationships/comments", func(ctx context.Context, w ResponseWriter) context.Context {
		r := GetRequest(ctx)
		w.Write([]byte("user " + r.ResID + " " + r.ResRel + " " + r.ResRelName))
		return ctx
	}, GatePublic)

	testApp.Get("/users/:id/comments", func(ctx context.Context, w ResponseWriter) context.Context {
		r := GetRequest(ctx)
		w.Write([]byte("user " + r.ResID + " " + r.ResRel + " " + r.ResRelName))
		return ctx
	}, GatePublic)

	testApp.Get("/comments", func(ctx context.Context, w ResponseWriter) context.Context {
		w.Write([]byte("comments"))
		return ctx
	}, GatePublic)

	server := httptest.NewServer(testApp)

	tests := []struct {
		url                string
		expectedStatusCode int
		expectedBody       string
	}{
		{
			// 0
			url:                "/users",
			expectedStatusCode: http.StatusOK,
			expectedBody:       "users",
		},
		{
			// 1
			url:                "/users/abc123",
			expectedStatusCode: http.StatusOK,
			expectedBody:       "user abc123",
		},
		{
			// 2
			url:                "/users/abc123/relationships/comments",
			expectedStatusCode: http.StatusOK,
			expectedBody:       "user abc123 self comments",
		},
		{
			// 3
			url:                "/users/abc123/comments",
			expectedStatusCode: http.StatusOK,
			expectedBody:       "user abc123 related comments",
		},
	}

	for i, test := range tests {
		res := tchek.MakeRequest(server, "GET", test.url, "")
		fmt.Printf("\n")

		var body []byte
		body, err := ioutil.ReadAll(res.Body)
		tchek.UnintendedError(err)

		tchek.AreEqual(t, i, test.expectedStatusCode, res.StatusCode)
		tchek.AreEqual(t, i, test.expectedBody, string(body))
	}
}
예제 #4
0
func TestMarshalAndUnmarshal(t *testing.T) {
	tests := []struct {
		source                 interface{}
		destination            interface{}
		params                 int
		marshalErrorExpected   bool
		unmarshalErrorExpected bool
	}{
		{
			// 0
			nil,
			nil,
			0,
			true,
			false,
		},
		{
			// 1
			users["1"],
			&user{},
			0,
			false,
			false,
		},
		{
			// 2
			[]*user{users["1"], users["2"]},
			&[]*user{},
			0,
			false,
			false,
		},
		{
			// 3
			[]user{*users["1"], *users["2"]},
			&[]*user{},
			0,
			false,
			false,
		},
		{
			// 4
			[]*user{},
			&[]user{},
			0,
			false,
			false,
		},
		{
			// 5
			[]*user{users["1"], users["2"], users["3"]},
			&user{},
			0,
			false,
			true,
		},
	}

	options := []Options{
		Options{
			Extra: Extra{
				JSONAPI: map[string]interface{}{
					"version": "1.0",
				},
			},
		},
		Options{
			Extra: Extra{
				Meta: map[string]interface{}{
					"meta1": "value",
					"meta2": 38,
				},
				JSONAPI: map[string]interface{}{
					"version": "1.0",
				},
			},
			IncludeRelationshipIdentifiers: map[string]bool{
				"books": false,
			},
		},
	}

	for n, test := range tests {
		payload, err := Marshal(test.source, options[0])
		tchek.ErrorExpected(t, n, test.marshalErrorExpected, err)

		if !test.marshalErrorExpected {
			if printTests {
				log.Printf("Payload from test %d:\n", n)
				var out bytes.Buffer
				json.Indent(&out, payload, "", "\t")
				out.WriteTo(os.Stdout)
				fmt.Printf("\n")
			}

			err = Unmarshal(payload, test.destination)
			tchek.ErrorExpected(t, n, test.unmarshalErrorExpected, err)

			srcVal := reflect.ValueOf(test.destination).Elem()
			dstType := reflect.ValueOf(test.destination).Type().Elem()
			if dstType.Kind() == reflect.Slice {
				dstVal := reflect.ValueOf(test.destination).Elem()
				tchek.AreEqual(t, n, srcVal.Len(), dstVal.Len())
				for i := 0; i < dstVal.Len(); i++ {
					tchek.AreShallowEqual(t, n, !test.unmarshalErrorExpected, srcVal.Index(i).Interface(), dstVal.Index(i).Interface())
				}
			} else {
				tchek.AreShallowEqual(t, n, !test.unmarshalErrorExpected, test.source, test.destination)
			}
		}
	}
}
예제 #5
0
func TestJWTParser(t *testing.T) {
	testApp := NewApp()

	testApp.UseFunc(Recoverer)
	testApp.UseFunc(URLParser)
	testApp.UseFunc(JWTParser)

	testApp.Get("/jwt", func(ctx context.Context, w ResponseWriter) context.Context {
		r := ctx.Value(key("id")).(string)

		for _, s := range ctx.Value(key("groups")).([]string) {
			r += s
		}

		w.Write([]byte(r))

		return ctx
	}, GatePublic)

	server := httptest.NewServer(testApp)

	tests := []struct {
		id          string
		groups      []string
		expectation string
	}{
		{
			// 0
			id:          "abc123",
			groups:      []string{"admin", "developer", "founder"},
			expectation: "abc123admindeveloperfounder",
		},
		{
			// 1
			id:          "abc123",
			groups:      []string{},
			expectation: "abc123",
		},
		{
			// 2
			id:          "",
			groups:      []string{"public"},
			expectation: "public",
		},
		{
			// 3
			id:          "",
			groups:      []string{},
			expectation: "",
		},
	}

	for i, test := range tests {
		token, err := cybele.GenerateJWT(map[string]interface{}{
			"id":     test.id,
			"groups": test.groups,
		})
		tchek.UnintendedError(err)

		res := tchek.MakeRequest(server, "GET", "/jwt", token)
		fmt.Printf("\n")

		var body []byte
		body, err = ioutil.ReadAll(res.Body)
		tchek.UnintendedError(err)

		tchek.AreEqual(t, i, test.expectation, string(body))
	}
}
예제 #6
0
func TestURLParser(t *testing.T) {
	testApp := NewApp()

	testApp.UseFunc(URLParser)

	testApp.UseFunc(func(ctx context.Context, w ResponseWriter, next CtxHandlerFunc) context.Context {
		normURL := GetRequest(ctx).NormalizedURL

		w.Write([]byte(fmt.Sprintf("%v", normURL)))

		next(ctx, w)
		return ctx
	})

	server := httptest.NewServer(testApp)

	tests := []struct {
		url                string
		expectedStatusCode int
		expectedBody       string
	}{
		{
			// 0
			url:                "/",
			expectedStatusCode: http.StatusBadRequest,
			expectedBody:       "",
		},
		{
			// 1
			url:                "/type/1/relationships/rel",
			expectedStatusCode: http.StatusOK,
			expectedBody:       "/type/1/relationships/rel",
		},
		{
			// 2
			url:                "/type/1/relationships/rel/",
			expectedStatusCode: http.StatusOK,
			expectedBody:       "/type/1/relationships/rel",
		},
		{
			// 3
			url:                "/this/is/an/invalid/request",
			expectedStatusCode: http.StatusBadRequest,
			expectedBody:       "",
		},
		{
			// 4
			url:                "/request//invalid",
			expectedStatusCode: http.StatusBadRequest,
			expectedBody:       "",
		},
		{
			// 5
			url:                "/groups/1/users?fields[user]=id,name,age",
			expectedStatusCode: http.StatusOK,
			expectedBody:       "/groups/1/users?fields[user]=age,id,name",
		},
		{
			// 6
			url:                "/boards?filters[lang]=fr",
			expectedStatusCode: http.StatusOK,
			expectedBody:       "/boards?filters[lang]=fr",
		},
		{
			// 7
			url:                "/users?sort=xp,age",
			expectedStatusCode: http.StatusOK,
			expectedBody:       "/users?sort=xp,age",
		},
		{
			// 8
			url:                "/users?page[size]=10&page[number]=1",
			expectedStatusCode: http.StatusOK,
			expectedBody:       "/users?page[number]=1&page[size]=10",
		},
		{
			// 9
			url:                "/users?fields[user]=id,name&filters[group]=15&sort=age,-xp,name&page[size]=10&page[number]=3",
			expectedStatusCode: http.StatusOK,
			expectedBody:       "/users?fields[user]=id,name&filters[group]=15&page[number]=3&page[size]=10&sort=age,-xp,name",
		},
	}

	for i, test := range tests {
		res := tchek.MakeRequest(server, "GET", test.url, "")
		fmt.Printf("\n")

		var body []byte
		body, err := ioutil.ReadAll(res.Body)
		tchek.UnintendedError(err)

		tchek.AreEqual(t, i, test.expectedStatusCode, res.StatusCode)
		tchek.AreEqual(t, i, test.expectedBody, string(body))
	}
}
예제 #7
0
func TestAuthorizer(t *testing.T) {
	testApp := NewApp()

	testApp.UseFunc(Recoverer)
	testApp.UseFunc(URLParser)
	testApp.UseFunc(JWTParser)
	testApp.UseFunc(Authorizer)

	testApp.Get("/users", func(ctx context.Context, w ResponseWriter) context.Context {
		return ctx
	}, GateAdmin)

	testApp.Get("/comments", func(ctx context.Context, w ResponseWriter) context.Context {
		return ctx
	}, GatePublic)

	testApp.Post("/comments", func(ctx context.Context, w ResponseWriter) context.Context {
		return ctx
	}, GateNotBannedUser)

	server := httptest.NewServer(testApp)

	tests := []struct {
		method             string
		url                string
		id                 string
		groups             []string
		expectedStatusCode int
	}{
		{
			// 0
			method:             "GET",
			url:                "/comments",
			id:                 "",
			groups:             []string{},
			expectedStatusCode: http.StatusOK,
		},
		{
			// 1
			method:             "GET",
			url:                "/comments",
			id:                 "abc123",
			groups:             []string{"banned"},
			expectedStatusCode: http.StatusOK,
		},
		{
			// 2
			method:             "POST",
			url:                "/comments",
			id:                 "abc123",
			groups:             []string{"banned"},
			expectedStatusCode: http.StatusForbidden,
		},
		{
			// 4
			method:             "GET",
			url:                "/users",
			id:                 "abc123",
			groups:             []string{"admin"},
			expectedStatusCode: http.StatusOK,
		},
	}

	for i, test := range tests {
		var err error
		token := ""
		if test.id != "" {
			token, err = cybele.GenerateJWT(map[string]interface{}{
				"id":     test.id,
				"groups": test.groups,
			})
			tchek.UnintendedError(err)
		}

		res := tchek.MakeRequest(server, test.method, test.url, token)
		fmt.Printf("\n")

		tchek.AreEqual(t, i, test.expectedStatusCode, res.StatusCode)
	}
}