Commit 30b9d9e6 authored by Martin Sefcik's avatar Martin Sefcik

Rewritten tests

parent 07bee06b
......@@ -187,9 +187,6 @@ func (c *Client) SetBaseURL(urlStr string) error {
return err
}
// Set the encoded opaque data
c.baseURL.Opaque = c.baseURL.Path
return nil
}
......@@ -199,8 +196,12 @@ func (c *Client) SetBaseURL(urlStr string) error {
// specified, the value pointed to by body is JSON encoded and included as the
// request body.
func (c *Client) NewRequest(method, path string, opt interface{}) (*http.Request, error) {
u := *c.baseURL
u.Opaque += path
rel, err := url.Parse(path)
if err != nil {
return nil, err
}
u := *c.baseURL.ResolveReference(rel)
q, err := query.Values(opt)
if err != nil {
......@@ -351,11 +352,9 @@ type ErrorResponse struct {
}
func (r *ErrorResponse) Error() string {
path, _ := url.QueryUnescape(r.Response.Request.URL.Opaque)
ru := fmt.Sprintf("%s://%s%s", r.Response.Request.URL.Scheme, r.Response.Request.URL.Host, path)
return fmt.Sprintf("%v %s: %d %v %+v",
r.Response.Request.Method, ru, r.Response.StatusCode, r.Message, r.Errors)
return fmt.Sprintf("%v %v: %d %v %+v",
r.Response.Request.Method, r.Response.Request.URL,
r.Response.StatusCode, r.Message, r.Errors)
}
// An Error reports more details on an individual error in an ErrorResponse.
......
package gitlab
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"reflect"
"strings"
"testing"
)
var (
// mux is the HTTP request multiplexer used with the test server.
mux *http.ServeMux
// client is the Gitlab client being tested.
client *Client
// server is a test HTTP server used to provide mock API responses.
server *httptest.Server
)
// setup sets up a test HTTP server along with a gitlab.Client that is
// configured to talk to that test server. Tests should register handlers on
// mux which provide mock responses for the API method being tested.
func setup() {
// test server
mux = http.NewServeMux()
server = httptest.NewServer(mux)
// gitlab client configured to use test server
client = NewClient(nil, "")
client.SetBaseURL(server.URL)
}
// teardown closes the test HTTP server.
func teardown() {
server.Close()
}
func testMethod(t *testing.T, r *http.Request, want string) {
if got := r.Method; got != want {
t.Errorf("Request method: %v, want %v", got, want)
}
}
type values map[string]string
func testFormValues(t *testing.T, r *http.Request, values values) {
want := url.Values{}
for k, v := range values {
want.Add(k, v)
}
r.ParseForm()
if got := r.Form; !reflect.DeepEqual(got, want) {
t.Errorf("Request parameters: %v, want %v", got, want)
}
}
func testHeader(t *testing.T, r *http.Request, header string, want string) {
if got := r.Header.Get(header); got != want {
t.Errorf("Header.Get(%q) returned %s, want %s", header, got, want)
}
}
func testBody(t *testing.T, r *http.Request, want string) {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Errorf("Error reading request body: %v", err)
}
if got := string(b); got != want {
t.Errorf("request Body is %s, want %s", got, want)
}
}
func responseBody(w http.ResponseWriter, filename string) {
body, _ := ioutil.ReadFile(filename)
w.Write([]byte(body))
}
func TestNewClient(t *testing.T) {
c := NewClient(nil, "")
if got, want := c.BaseURL().String(), defaultBaseURL; got != want {
t.Errorf("NewClient BaseURL is %v, want %v", got, want)
}
if got, want := c.UserAgent, userAgent; got != want {
t.Errorf("NewClient UserAgent is %v, want %v", got, want)
}
}
func TestCheckResponse(t *testing.T) {
res := &http.Response{
Request: &http.Request{},
StatusCode: http.StatusBadRequest,
Body: ioutil.NopCloser(strings.NewReader(`{"message":"m",
"errors": [{"resource": "r", "field": "f", "code": "c"}]}`)),
}
err := CheckResponse(res).(*ErrorResponse)
if err == nil {
t.Errorf("Expected error response.")
}
want := &ErrorResponse{
Response: res,
Message: "m",
Errors: []Error{{Resource: "r", Field: "f", Code: "c"}},
}
if !reflect.DeepEqual(err, want) {
t.Errorf("Error = %#v, want %#v", err, want)
}
}
\ No newline at end of file
package gitlab
import (
"io/ioutil"
"net/http"
"net/http/httptest"
)
func Stub(filename string) (*httptest.Server, *Client) {
stub, _ := ioutil.ReadFile(filename)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(stub))
}))
client := NewClient(nil, "")
client.SetBaseURL(ts.URL)
return ts, client
}
......@@ -34,38 +34,56 @@ type ProjectsService struct {
//
// GitLab API docs: http://doc.gitlab.com/ce/api/projects.html
type Project struct {
ID int `json:"id"`
Description interface{} `json:"description"`
DefaultBranch string `json:"default_branch"`
Public bool `json:"public"`
VisibilityLevel VisibilityLevel `json:"visibility_level"`
SSHURLToRepo string `json:"ssh_url_to_repo"`
HTTPURLToRepo string `json:"http_url_to_repo"`
WebURL string `json:"web_url"`
TagList []string `json:"tag_list"`
Owner *User `json:"owner"`
Name string `json:"name"`
NameWithNamespace string `json:"name_with_namespace"`
Path string `json:"path"`
PathWithNamespace string `json:"path_with_namespace"`
IssuesEnabled bool `json:"issues_enabled"`
MergeRequestsEnabled bool `json:"merge_requests_enabled"`
WikiEnabled bool `json:"wiki_enabled"`
SnippetsEnabled bool `json:"snippets_enabled"`
CreatedAt time.Time `json:"created_at"`
LastActivityAt time.Time `json:"last_activity_at"`
CreatorID int `json:"creator_id"`
Namespace struct {
CreatedAt time.Time `json:"created_at"`
Description string `json:"description"`
ID int `json:"id"`
Name string `json:"name"`
OwnerID int `json:"owner_id"`
Path string `json:"path"`
UpdatedAt time.Time `json:"updated_at"`
} `json:"namespace"`
Archived bool `json:"archived"`
AvatarURL string `json:"avatar_url"`
ID *int `json:"id"`
Description *string `json:"description"`
DefaultBranch *string `json:"default_branch"`
Public *bool `json:"public"`
VisibilityLevel *VisibilityLevel `json:"visibility_level"`
SSHURLToRepo *string `json:"ssh_url_to_repo"`
HTTPURLToRepo *string `json:"http_url_to_repo"`
WebURL *string `json:"web_url"`
TagList *[]string `json:"tag_list"`
Owner *User `json:"owner"`
Name *string `json:"name"`
NameWithNamespace *string `json:"name_with_namespace"`
Path *string `json:"path"`
PathWithNamespace *string `json:"path_with_namespace"`
IssuesEnabled *bool `json:"issues_enabled"`
MergeRequestsEnabled *bool `json:"merge_requests_enabled"`
WikiEnabled *bool `json:"wiki_enabled"`
SnippetsEnabled *bool `json:"snippets_enabled"`
CreatedAt *time.Time `json:"created_at,omitempty"`
LastActivityAt *time.Time `json:"last_activity_at,omitempty"`
CreatorID *int `json:"creator_id"`
Namespace *ProjectNamespace `json:"namespace"`
Archived *bool `json:"archived"`
AvatarURL *string `json:"avatar_url"`
Permissions *Permissions `json:"permissions"`
}
type ProjectNamespace struct {
CreatedAt *time.Time `json:"created_at"`
Description *string `json:"description"`
ID *int `json:"id"`
Name *string `json:"name"`
OwnerID *int `json:"owner_id"`
Path *string `json:"path"`
UpdatedAt *time.Time `json:"updated_at"`
}
type Permissions struct {
ProjectAccess *ProjectAccess `json:"project_access"`
GroupAccess *GroupAccess `json:"group_access"`
}
type ProjectAccess struct {
AccessLevel AccessLevel `json:"access_level"`
NotificationLevel NotificationLevel `json:"notification_level"`
}
type GroupAccess struct {
AccessLevel AccessLevel `json:"access_level"`
NotificationLevel NotificationLevel `json:"notification_level"`
}
func (s Project) String() string {
......@@ -142,36 +160,12 @@ func (s *ProjectsService) ListAllProjects(opt *ListProjectsOptions) ([]*Project,
return p, resp, err
}
// ProjectWithAccess represents a GitLab project with permissions attributes.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#get-single-project
type ProjectWithAccess struct {
Project
Permissions *Permissions `json:"permissions"`
}
type Permissions struct {
ProjectAccess *ProjectAccess `json:"project_access"`
GroupAccess *GroupAccess `json:"group_access"`
}
type ProjectAccess struct {
AccessLevel AccessLevel `json:"access_level"`
NotificationLevel NotificationLevel `json:"notification_level"`
}
type GroupAccess struct {
AccessLevel AccessLevel `json:"access_level"`
NotificationLevel NotificationLevel `json:"notification_level"`
}
// GetProject gets a specific project, identified by project ID or
// NAMESPACE/PROJECT_NAME, which is owned by the authenticated user.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#get-single-project
func (s *ProjectsService) GetProject(pid interface{}) (*ProjectWithAccess, *Response, error) {
func (s *ProjectsService) GetProject(pid interface{}) (*Project, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
......@@ -183,7 +177,7 @@ func (s *ProjectsService) GetProject(pid interface{}) (*ProjectWithAccess, *Resp
return nil, nil, err
}
p := new(ProjectWithAccess)
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
......
package gitlab
import (
"fmt"
"net/http"
"reflect"
"testing"
)
func TestListAllProjects(t *testing.T) {
ts, client := Stub("stubs/projects/index.json")
defer ts.Close()
func TestListProjects(t *testing.T) {
setup()
defer teardown()
opt := &ListProjectsOptions{}
projects, _, err := client.Projects.ListAllProjects(opt)
mux.HandleFunc("/projects", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{
"page": "2",
"per_page": "3",
"archived": "true",
"order_by": "name",
"sort": "asc",
"search": "query",
"ci_enabled_first": "true",
})
fmt.Fprint(w, `[{"id":1},{"id":2}]`)
})
opt := &ListProjectsOptions{ListOptions{2, 3}, true, "name", "asc", "query", true}
projects, _, err := client.Projects.ListProjects(opt)
if err != nil {
t.Fatalf("Expected error nil, got: %v", err)
t.Errorf("Projects.ListProjects returned error: %v", err)
}
count := len(projects)
if count != 2 {
t.Errorf("Expected number of projects %q, got %q", 2, count)
want := []*Project{{ID: Int(1)},{ID: Int(2)}}
if !reflect.DeepEqual(want, projects) {
t.Errorf("Projects.ListProjects returned %+v, want %+v", projects, want)
}
if projects[0].Name != "project" {
t.Errorf("Expected project name %q, got %q", "project", projects[0].Name)
}
func TestListOwnedProjects(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/projects/owned", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{
"page": "2",
"per_page": "3",
"archived": "true",
"order_by": "name",
"sort": "asc",
"search": "query",
"ci_enabled_first": "true",
})
fmt.Fprint(w, `[{"id":1},{"id":2}]`)
})
opt := &ListProjectsOptions{ListOptions{2, 3}, true, "name", "asc", "query", true}
projects, _, err := client.Projects.ListOwnedProjects(opt)
if err != nil {
t.Errorf("Projects.ListOwnedProjects returned error: %v", err)
}
if projects[1].Name != "project2" {
t.Errorf("Expected project name %q, got %q", "project2", projects[1].Name)
want := []*Project{{ID: Int(1)},{ID: Int(2)}}
if !reflect.DeepEqual(want, projects) {
t.Errorf("Projects.ListOwnedProjects returned %+v, want %+v", projects, want)
}
}
func TestListAllProjects(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/projects/all", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{
"page": "2",
"per_page": "3",
"archived": "true",
"order_by": "name",
"sort": "asc",
"search": "query",
"ci_enabled_first": "true",
})
fmt.Fprint(w, `[{"id":1},{"id":2}]`)
})
opt := &ListProjectsOptions{ListOptions{2, 3}, true, "name", "asc", "query", true}
projects, _, err := client.Projects.ListAllProjects(opt)
if err != nil {
t.Errorf("Projects.ListAllProjects returned error: %v", err)
}
want := []*Project{{ID: Int(1)},{ID: Int(2)}}
if !reflect.DeepEqual(want, projects) {
t.Errorf("Projects.ListAllProjects returned %+v, want %+v", projects, want)
}
}
func TestGetProject(t *testing.T) {
ts, client := Stub("stubs/projects/show.json")
defer ts.Close()
setup()
defer teardown()
mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprint(w, `{"id":1}`)
})
want := &Project{ID: Int(1)}
project, _, err := client.Projects.GetProject(1)
if err != nil {
t.Fatalf("Expected error nil, got: %v", err)
t.Fatalf("Projects.GetProject returns an error: %v", err)
}
if project.Name != "project" {
t.Errorf("Expected project name %q, got %q", "project", project.Name)
}
if project.Namespace.Name != "group" {
t.Errorf("Expected namespace name %q, got %q", "group", project.Namespace.Name)
if !reflect.DeepEqual(want, project) {
t.Errorf("Projects.GetProject returned %+v, want %+v", project, want)
}
if project.Permissions.ProjectAccess.AccessLevel != MasterPermissions {
t.Errorf("Expected project access level %q, got %q", MasterPermissions, project.Permissions.ProjectAccess.AccessLevel)
}
func TestSearchProjects(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/projects/search/query", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r, values{
"page": "2",
"per_page": "3",
"order_by": "name",
"sort": "asc",
})
fmt.Fprint(w, `[{"id":1},{"id":2}]`)
})
opt := &SearchProjectsOptions{ListOptions{2, 3}, "name", "asc"}
projects, _, err := client.Projects.SearchProjects("query", opt)
if err != nil {
t.Errorf("Projects.SearchProjects returned error: %v", err)
}
if project.Permissions.GroupAccess != nil {
t.Errorf("Expected project group access nil, got %q", project.Permissions.GroupAccess)
want := []*Project{{ID: Int(1)},{ID: Int(2)}}
if !reflect.DeepEqual(want, projects) {
t.Errorf("Projects.SearchProjects returned %+v, want %+v", projects, want)
}
}
func TestCreateProject(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/projects", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "POST")
testFormValues(t, r, values{
"name": "n",
})
fmt.Fprint(w, `{"id":1}`)
})
opt := &CreateProjectOptions{Name: "n"}
project, _, err := client.Projects.CreateProject(opt)
if err != nil {
t.Errorf("Projects.CreateProject returned error: %v", err)
}
want := &Project{ID: Int(1)}
if !reflect.DeepEqual(want, project) {
t.Errorf("Projects.CreateProject returned %+v, want %+v", project, want)
}
}
\ No newline at end of file
[
{
"id": 12,
"description": "",
"default_branch": "master",
"tag_list": [],
"public": false,
"archived": false,
"visibility_level": 0,
"ssh_url_to_repo": "git@gitlab.example.com:group/project",
"http_url_to_repo": "https://gitlab.example.com/group/project.git",
"web_url": "https://gitlab.example.com/group/project",
"name": "project",
"name_with_namespace": "group / project",
"path": "project",
"path_with_namespace": "group/project",
"issues_enabled": true,
"merge_requests_enabled": true,
"wiki_enabled": false,
"snippets_enabled": false,
"created_at": "2015-10-26T14:32:44.103+01:00",
"last_activity_at": "2015-11-01T22:07:47.456+01:00",
"creator_id": 1,
"namespace": {
"id": 7,
"name": "group",
"path": "group",
"owner_id": null,
"created_at": "2015-10-26T13:36:40.147+01:00",
"updated_at": "2015-10-27T08:57:55.199+01:00",
"description": "group desc",
"avatar": {
"url": "/uploads/group/avatar/7/group-logo.png"
}
},
"avatar_url": "https://gitlab.example.com/uploads/project/avatar/12/group-logo.png",
"star_count": 0,
"forks_count": 0
},
{
"id": 11,
"description": "",
"default_branch": "master",
"tag_list": [],
"public": false,
"archived": false,
"visibility_level": 0,
"ssh_url_to_repo": "git@gitlab.example.com:johndoe/project2.git",
"http_url_to_repo": "https://gitlab.example.com/johndoe/project2.git",
"web_url": "https://gitlab.example.com/johndoe/project2",
"owner": {
"name": "John Doe",
"username": "johndoe",
"id": 1,
"state": "active",
"avatar_url": "https://secure.gravatar.com/avatar/123",
"web_url": "https://gitlab.example.com/u/johndoe"
},
"name": "project2",
"name_with_namespace": "John Doe / project2",
"path": "project2",
"path_with_namespace": "johndoe/project2",
"issues_enabled": true,
"merge_requests_enabled": true,
"wiki_enabled": true,
"snippets_enabled": true,
"created_at": "2015-03-18T19:33:20.166+01:00",
"last_activity_at": "2015-11-01T19:48:32.793+01:00",
"creator_id": 1,
"namespace": {
"id": 1,
"name": "John Doe",
"path": "johndoe",
"owner_id": 1,
"created_at": "2014-01-05T22:01:51.000+01:00",
"updated_at": "2014-01-05T22:51:08.000+01:00",
"description": "",
"avatar": null
},
"avatar_url": null,
"star_count": 0,
"forks_count": 0
}
]
{
"id": 11,
"description": "",
"default_branch": "master",
"tag_list": [],
"public": false,
"archived": false,
"visibility_level": 0,
"ssh_url_to_repo": "git@gitlab.example.com:group/project.git",
"http_url_to_repo": "https://gitlab.example.com/group/project.git",
"web_url": "https://gitlab.example.com/group/project",
"owner": {
"name": "John Doe",
"username": "johndoe",
"id": 1,
"state": "active",
"avatar_url": "https://secure.gravatar.com/avatar/123",
"web_url": "https://gitlab.example.com/u/johndoe"
},
"name": "project",
"name_with_namespace": "Group / project",
"path": "project",
"path_with_namespace": "group/project",
"issues_enabled": true,
"merge_requests_enabled": true,
"wiki_enabled": true,
"snippets_enabled": true,
"created_at": "2015-03-18T19:33:20.166+01:00",
"last_activity_at": "2015-11-01T19:48:32.793+01:00",
"creator_id": 1,
"namespace": {
"id": 1,
"name": "group",
"path": "group",
"owner_id": 1,
"created_at": "2014-01-05T22:01:51.000+01:00",
"updated_at": "2014-01-05T22:51:08.000+01:00",
"description": "",
"avatar": null
},
"avatar_url": null,
"star_count": 0,
"forks_count": 0,
"permissions": {
"project_access": {
"access_level": 40,
"notification_level": 3
},
"group_access": null
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment