Commit 11548086 authored by Tomas Vik's avatar Tomas Vik Ⓜ️
Browse files

Merge branch 'jmc-add-project-tests' into 'main'

test(project): add missing project tests

See merge request !1156



Merged-by: Tomas Vik's avatarTomas Vik <tvik@gitlab.com>
Approved-by: default avatarEzekiel Kigbo <3397881-ekigbo@users.noreply.gitlab.com>
Approved-by: Tomas Vik's avatarTomas Vik <tvik@gitlab.com>
Reviewed-by: default avatarEzekiel Kigbo <3397881-ekigbo@users.noreply.gitlab.com>
Reviewed-by: default avatarJay McCure <jmccure@gitlab.com>
Co-authored-by: default avatarJay McCure <jmccure@gitlab.com>
parents b7e92615 3becc968
Loading
Loading
Loading
Loading
Loading
+112 −0
Original line number Diff line number Diff line
package contributors

import (
	"net/http"
	"testing"

	"github.com/MakeNowJust/heredoc"

	"github.com/stretchr/testify/assert"
	"gitlab.com/gitlab-org/cli/pkg/httpmock"

	"gitlab.com/gitlab-org/cli/commands/cmdtest"

	"gitlab.com/gitlab-org/cli/test"
)

func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, error) {
	ios, _, stdout, stderr := cmdtest.InitIOStreams(isTTY, "")

	factory := cmdtest.InitFactory(ios, rt)

	_, _ = factory.HttpClient()

	cmd := NewCmdContributors(factory)

	return cmdtest.ExecuteCommand(cmd, cli, stdout, stderr)
}

func TestProjectContributors(t *testing.T) {
	type httpMock struct {
		method   string
		path     string
		status   int
		bodyFile string
	}

	tests := []struct {
		name     string
		cli      string
		httpMock httpMock

		expectedOutput string
	}{
		{
			name: "view project contributors",
			cli:  "",
			httpMock: httpMock{
				http.MethodGet,
				"/api/v4/projects/OWNER/REPO/repository/contributors?order_by=commits&page=1&per_page=30&sort=desc",
				http.StatusOK,
				"testdata/contributors.json",
			},
			expectedOutput: heredoc.Doc(`Showing 2 contributors on OWNER/REPO (Page 1)
															
															Test User	tu@gitlab.com	41 commits
															Test User2	tu2@gitlab.com	12 commits
															
															`),
		},
		{
			name: "view project contributors for a different project",
			cli:  "-R foo/bar",
			httpMock: httpMock{
				http.MethodGet,
				"/api/v4/projects/foo/bar/repository/contributors?order_by=commits&page=1&per_page=30&sort=desc",
				http.StatusOK,
				"testdata/contributors.json",
			},
			expectedOutput: heredoc.Doc(`Showing 2 contributors on foo/bar (Page 1)
															
															Test User	tu@gitlab.com	41 commits
															Test User2	tu2@gitlab.com	12 commits
															
															`),
		},
		{
			name: "view project contributors ordered by name sorted in ascending order",
			cli:  "--order name --sort asc",
			httpMock: httpMock{
				http.MethodGet,
				"/api/v4/projects/OWNER/REPO/repository/contributors?order_by=name&page=1&per_page=30&sort=asc",
				http.StatusOK,
				"testdata/contributors.json",
			},
			expectedOutput: heredoc.Doc(`Showing 2 contributors on OWNER/REPO (Page 1)
															
															Test User	tu@gitlab.com	41 commits
															Test User2	tu2@gitlab.com	12 commits
															
															`),
		},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			fakeHTTP := &httpmock.Mocker{
				MatchURL: httpmock.PathAndQuerystring,
			}
			defer fakeHTTP.Verify(t)

			fakeHTTP.RegisterResponder(tc.httpMock.method, tc.httpMock.path,
				httpmock.NewFileResponse(tc.httpMock.status, tc.httpMock.bodyFile))

			output, err := runCommand(fakeHTTP, false, tc.cli)

			if assert.NoErrorf(t, err, "error running command `project contributors %s`: %v", tc.cli, err) {
				assert.Equal(t, tc.expectedOutput, output.String())
				assert.Empty(t, output.Stderr())
			}
		})
	}
}
+16 −0
Original line number Diff line number Diff line
[
  {
    "name": "Test User",
    "email": "tu@gitlab.com",
    "commits": 41,
    "additions": 0,
    "deletions": 0
  },
  {
    "name": "Test User2",
    "email": "tu2@gitlab.com",
    "commits": 12,
    "additions": 4,
    "deletions": 4
  }
]
 No newline at end of file
+95 −0
Original line number Diff line number Diff line
package delete

import (
	"net/http"
	"testing"

	"github.com/stretchr/testify/assert"
	"gitlab.com/gitlab-org/cli/pkg/httpmock"

	"gitlab.com/gitlab-org/cli/commands/cmdtest"

	"gitlab.com/gitlab-org/cli/test"
)

func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, error) {
	ios, _, stdout, stderr := cmdtest.InitIOStreams(isTTY, "")

	factory := cmdtest.InitFactory(ios, rt)

	_, _ = factory.HttpClient()

	cmd := NewCmdDelete(factory)

	return cmdtest.ExecuteCommand(cmd, cli, stdout, stderr)
}

func TestProjectDelete(t *testing.T) {
	type httpMock struct {
		method string
		path   string
		status int
		body   string
	}

	tests := []struct {
		name     string
		cli      string
		httpMock httpMock

		expectedOutput string
	}{
		{
			name: "delete my project",
			cli:  "--yes",
			httpMock: httpMock{
				http.MethodDelete,
				"/api/v4/projects/OWNER/REPO",
				http.StatusAccepted,
				`{"message":"202 Accepted"}`,
			},
			expectedOutput: "- Deleting project OWNER/REPO\n",
		},
		{
			name: "delete project",
			cli:  "foo/bar --yes",
			httpMock: httpMock{
				http.MethodDelete,
				"/api/v4/projects/foo/bar",
				http.StatusAccepted,
				`{"message":"202 Accepted"}`,
			},
			expectedOutput: "- Deleting project foo/bar\n",
		},
		{
			name: "delete group's project",
			cli:  "group/foo/bar --yes",
			httpMock: httpMock{
				http.MethodDelete,
				"/api/v4/projects/group/foo/bar",
				http.StatusAccepted,
				`{"message":"202 Accepted"}`,
			},
			expectedOutput: "- Deleting project group/foo/bar\n",
		},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			fakeHTTP := &httpmock.Mocker{
				MatchURL: httpmock.PathAndQuerystring,
			}
			defer fakeHTTP.Verify(t)

			fakeHTTP.RegisterResponder(tc.httpMock.method, tc.httpMock.path,
				httpmock.NewStringResponse(tc.httpMock.status, tc.httpMock.body))

			output, err := runCommand(fakeHTTP, true, tc.cli)

			if assert.NoErrorf(t, err, "error running command `project delete %s`: %v", tc.cli, err) {
				assert.Equal(t, tc.expectedOutput, output.Stderr())
				assert.Empty(t, output.String())
			}
		})
	}
}
+52 −45
Original line number Diff line number Diff line
@@ -31,76 +31,84 @@ func TestProjectList(t *testing.T) {
		body   string
	}

	projectResponse := `[{
							"id": 123,
 							"description": "This is a test project",
 							"path_with_namespace": "gitlab-org/incubation-engineering/service-desk/meta"
					}]`

	tests := []struct {
		name        string
		httpMocks   []httpMock
		httpMock    httpMock
		args        string
		expectedOut string
	}{
		{
			name: "when no projects are found shows an empty list",
			httpMocks: []httpMock{
				{
			httpMock: httpMock{
				http.MethodGet,
				"/api/v4/projects?order_by=last_activity_at&owned=true&page=1&per_page=30",
				http.StatusOK,
				"[]",
			},
			},
			args:        "",
			expectedOut: "Showing 0 of 0 projects (Page 0 of 0)\n\n\n",
		},
		{
			name: "when projects are found shows list",
			httpMocks: []httpMock{
				{
			httpMock: httpMock{
				http.MethodGet,
				"/api/v4/projects?order_by=last_activity_at&owned=true&page=1&per_page=30",
				http.StatusOK,
					`[{
							"id": 123,
 							"description": "This is a test project",
 							"path_with_namespace": "gitlab-org/incubation-engineering/service-desk/meta"
					}]`,
				},
				projectResponse,
			},
			args:        "",
			expectedOut: "Showing 1 of 0 projects (Page 0 of 0)\n\ngitlab-org/incubation-engineering/service-desk/meta\t\tThis is a test project\n\n",
		},
		{
			name: "when starred is passed as an arg filters by starred",
			httpMocks: []httpMock{
				{
			httpMock: httpMock{
				http.MethodGet,
				"/api/v4/projects?order_by=last_activity_at&owned=true&page=1&per_page=30&starred=true",
				http.StatusOK,
					`[{
							"id": 123,
 							"description": "This is a test project",
 							"path_with_namespace": "gitlab-org/incubation-engineering/service-desk/meta"
					}]`,
				},
				projectResponse,
			},
			args:        "--starred",
			expectedOut: "Showing 1 of 0 projects (Page 0 of 0)\n\ngitlab-org/incubation-engineering/service-desk/meta\t\tThis is a test project\n\n",
		},
		{
			name: "when member is passed as an arg filters by member",
			httpMocks: []httpMock{
				{
			httpMock: httpMock{
				http.MethodGet,
				"/api/v4/projects?membership=true&order_by=last_activity_at&owned=true&page=1&per_page=30",
				http.StatusOK,
					`[{
							"id": 123,
 							"description": "This is a test project",
 							"path_with_namespace": "gitlab-org/incubation-engineering/service-desk/meta"
					}]`,
				},
				projectResponse,
			},
			args:        "--member",
			expectedOut: "Showing 1 of 0 projects (Page 0 of 0)\n\ngitlab-org/incubation-engineering/service-desk/meta\t\tThis is a test project\n\n",
		},
		{
			name: "view all projects",
			httpMock: httpMock{
				http.MethodGet,
				"/api/v4/projects?order_by=last_activity_at&page=1&per_page=30",
				http.StatusOK,
				projectResponse,
			},
			args:        "--all",
			expectedOut: "Showing 1 of 0 projects (Page 0 of 0)\n\ngitlab-org/incubation-engineering/service-desk/meta\t\tThis is a test project\n\n",
		},
		{
			name: "view all projects ordered by created_at date sorted descending",
			httpMock: httpMock{
				http.MethodGet,
				"/api/v4/projects?order_by=created_at&owned=true&page=1&per_page=30&sort=desc",
				http.StatusOK,
				projectResponse,
			},
			args:        "--order created_at --sort desc",
			expectedOut: "Showing 1 of 0 projects (Page 0 of 0)\n\ngitlab-org/incubation-engineering/service-desk/meta\t\tThis is a test project\n\n",
		},
	}

	for _, tc := range tests {
@@ -110,13 +118,12 @@ func TestProjectList(t *testing.T) {
			}
			defer fakeHTTP.Verify(t)

			for _, mock := range tc.httpMocks {
				fakeHTTP.RegisterResponder(mock.method, mock.path, httpmock.NewStringResponse(mock.status, mock.body))
			}
			fakeHTTP.RegisterResponder(tc.httpMock.method, tc.httpMock.path,
				httpmock.NewStringResponse(tc.httpMock.status, tc.httpMock.body))

			output, err := runCommand(fakeHTTP, false, tc.args)

			if assert.NoErrorf(t, err, "error running command `project list %s`: %v", err) {
			if assert.NoErrorf(t, err, "error running command `project list %s`: %v", tc.args, err) {
				out := output.String()

				assert.Equal(t, tc.expectedOut, out)
+245 −0
Original line number Diff line number Diff line
package view

import (
	"net/http"
	"testing"

	"github.com/MakeNowJust/heredoc"

	"github.com/stretchr/testify/assert"
	"gitlab.com/gitlab-org/cli/pkg/httpmock"

	"gitlab.com/gitlab-org/cli/commands/cmdtest"

	"gitlab.com/gitlab-org/cli/test"
)

func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, error) {
	ios, _, stdout, stderr := cmdtest.InitIOStreams(isTTY, "")

	factory := cmdtest.InitFactory(ios, rt)

	factory.Branch = func() (string, error) {
		return "current-branch", nil
	}

	_, _ = factory.HttpClient()

	cmd := NewCmdView(factory)

	return cmdtest.ExecuteCommand(cmd, cli, stdout, stderr)
}

func TestProjectView(t *testing.T) {
	type httpMock struct {
		method string
		path   string
		status int
		body   string
	}

	tests := []struct {
		name      string
		cli       string
		httpMocks []httpMock

		expectedOutput string
	}{
		{
			name: "view the project details for the current project",
			cli:  "",
			httpMocks: []httpMock{
				{
					http.MethodGet,
					"/api/v4/projects/OWNER/REPO?license=true&statistics=true&with_custom_attributes=true",
					http.StatusOK,
					`{
							  "id": 37777023,
							  "description": "this is a test description",
							  "name": "REPO",
							  "name_with_namespace": "Test User / REPO",
							  "path": "REPO",
							  "path_with_namespace": "OWNER/REPO",
							  "created_at": "2022-07-13T02:04:56.151Z",
							  "default_branch": "main",
							  "http_url_to_repo": "https://gitlab.com/OWNER/REPO.git",
							  "web_url": "https://gitlab.com/OWNER/REPO",
							  "readme_url": "https://gitlab.com/OWNER/REPO/-/blob/main/README.md"
							}`,
				},
				{
					http.MethodGet,
					"/api/v4/projects/OWNER/REPO/repository/files/README%2Emd?ref=current-branch",
					http.StatusOK,
					`{"file_name": "README.md",
							  "file_path": "README.md",
							  "encoding": "base64",
							  "ref": "main",
							  "execute_filemode": false,
							  "content": "dGVzdCByZWFkbWUK"
							}`,
				},
			},
			expectedOutput: heredoc.Doc(`name:	Test User / REPO
												description:	this is a test description
												---
												test readme

										`),
		},
		{
			name: "view the details of a project owned by the current user",
			cli:  "foo",
			httpMocks: []httpMock{
				{
					http.MethodGet,
					"/api/v4/user",
					http.StatusOK,
					`{ "username": "test_user" }`,
				},
				{
					http.MethodGet,
					"/api/v4/projects/test_user/foo?license=true&statistics=true&with_custom_attributes=true",
					http.StatusOK,
					`{
							  "id": 37777023,
							  "description": "this is a test description",
							  "name": "foo",
							  "name_with_namespace": "test_user / foo",
							  "path": "foo",
							  "path_with_namespace": "test_user/foo",
							  "created_at": "2022-07-13T02:04:56.151Z",
							  "default_branch": "main",
							  "http_url_to_repo": "https://gitlab.com/test_user/foo.git",
							  "web_url": "https://gitlab.com/test_user/foo",
							  "readme_url": "https://gitlab.com/test_user/foo/-/blob/main/README.md"
							}`,
				},
				{
					http.MethodGet,
					"/api/v4/projects/test_user/foo/repository/files/README%2Emd?ref=main",
					http.StatusOK,
					`{"file_name": "README.md",
							  "file_path": "README.md",
							  "encoding": "base64",
							  "ref": "main",
							  "execute_filemode": false,
							  "content": "dGVzdCByZWFkbWUK"
							}`,
				},
			},
			expectedOutput: heredoc.Doc(`name:	test_user / foo
												description:	this is a test description
												---
												test readme

										`),
		},
		{
			name: "view a specific project's details",
			cli:  "foo/bar",
			httpMocks: []httpMock{
				{
					http.MethodGet,
					"/api/v4/projects/foo/bar?license=true&statistics=true&with_custom_attributes=true",
					http.StatusOK,
					`{
							  "id": 37777023,
							  "description": "this is a test description",
							  "name": "bar",
							  "name_with_namespace": "foo / bar",
							  "path": "bar",
							  "path_with_namespace": "foo/bar",
							  "created_at": "2022-07-13T02:04:56.151Z",
							  "default_branch": "main",
							  "http_url_to_repo": "https://gitlab.com/foo/bar.git",
							  "web_url": "https://gitlab.com/foo/bar",
							  "readme_url": "https://gitlab.com/foo/bar/-/blob/main/README.md"
							}`,
				},
				{
					http.MethodGet,
					"/api/v4/projects/foo/bar/repository/files/README%2Emd?ref=main",
					http.StatusOK,
					`{
							"file_name": "README.md",
							"file_path": "README.md",
							"encoding": "base64",
							"ref": "main",
							"execute_filemode": false,
							"content": "dGVzdCByZWFkbWUK"
							}`,
				},
			},
			expectedOutput: heredoc.Doc(`name:	foo / bar
												description:	this is a test description
												---
												test readme

										`),
		},
		{
			name: "view a group's specific project details",
			cli:  "group/foo/bar",
			httpMocks: []httpMock{
				{
					http.MethodGet,
					"/api/v4/projects/group/foo/bar?license=true&statistics=true&with_custom_attributes=true",
					http.StatusOK,
					`{
							  "id": 37777023,
							  "description": "this is a test description",
							  "name": "bar",
							  "name_with_namespace": "group / foo / bar",
							  "path": "bar",
							  "path_with_namespace": "group/foo/bar",
							  "created_at": "2022-07-13T02:04:56.151Z",
							  "default_branch": "main",
							  "http_url_to_repo": "https://gitlab.com/group/foo/bar.git",
							  "web_url": "https://gitlab.com/group/foo/bar",
							  "readme_url": "https://gitlab.com/group/foo/bar/-/blob/main/README.md"
							}`,
				},
				{
					http.MethodGet,
					"/api/v4/projects/group/foo/bar/repository/files/README%2Emd?ref=main",
					http.StatusOK,
					`{
							"file_name": "README.md",
							"file_path": "README.md",
							"encoding": "base64",
							"ref": "main",
							"execute_filemode": false,
							"content": "dGVzdCByZWFkbWUK"
							}`,
				},
			},
			expectedOutput: heredoc.Doc(`name:	group / foo / bar
												description:	this is a test description
												---
												test readme

										`),
		},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			fakeHTTP := &httpmock.Mocker{
				MatchURL: httpmock.PathAndQuerystring,
			}
			defer fakeHTTP.Verify(t)

			for _, mock := range tc.httpMocks {
				fakeHTTP.RegisterResponder(mock.method, mock.path, httpmock.NewStringResponse(mock.status, mock.body))
			}

			output, err := runCommand(fakeHTTP, false, tc.cli)

			if assert.NoErrorf(t, err, "error running command `project view %s`: %v", tc.cli, err) {
				assert.Equal(t, tc.expectedOutput, output.String())
				assert.Empty(t, output.Stderr())
			}
		})
	}
}