summaryrefslogtreecommitdiff
path: root/spec/requests/api
diff options
context:
space:
mode:
Diffstat (limited to 'spec/requests/api')
-rw-r--r--spec/requests/api/commits_spec.rb6
-rw-r--r--spec/requests/api/groups_spec.rb24
-rw-r--r--spec/requests/api/internal_spec.rb31
-rw-r--r--spec/requests/api/jobs_spec.rb94
-rw-r--r--spec/requests/api/merge_request_diffs_spec.rb2
-rw-r--r--spec/requests/api/projects_spec.rb62
-rw-r--r--spec/requests/api/services_spec.rb13
-rw-r--r--spec/requests/api/v3/merge_request_diffs_spec.rb2
-rw-r--r--spec/requests/api/v3/projects_spec.rb1
-rw-r--r--spec/requests/api/wikis_spec.rb679
10 files changed, 885 insertions, 29 deletions
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index edbfaf510c5..f663719d28c 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -673,6 +673,12 @@ describe API::Commits do
it_behaves_like 'ref diff'
end
end
+
+ context 'when binary diff are treated as text' do
+ let(:commit_id) { TestEnv::BRANCH_SHA['add-pdf-text-binary'] }
+
+ it_behaves_like 'ref diff'
+ end
end
end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 77c43f92456..42f0079e173 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -431,6 +431,30 @@ describe API::Groups do
expect(response).to have_http_status(403)
end
+
+ context 'as owner', :nested_groups do
+ before do
+ group2.add_owner(user1)
+ end
+
+ it 'can create subgroups' do
+ post api("/groups", user1), parent_id: group2.id, name: 'foo', path: 'foo'
+
+ expect(response).to have_http_status(201)
+ end
+ end
+
+ context 'as master', :nested_groups do
+ before do
+ group2.add_master(user1)
+ end
+
+ it 'cannot create subgroups' do
+ post api("/groups", user1), parent_id: group2.id, name: 'foo', path: 'foo'
+
+ expect(response).to have_http_status(403)
+ end
+ end
end
context "when authenticated as user with group permissions" do
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index a6c804fb2b3..1274e66bb4c 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -5,13 +5,26 @@ describe API::Internal do
let(:key) { create(:key, user: user) }
let(:project) { create(:project, :repository) }
let(:secret_token) { Gitlab::Shell.secret_token }
+ let(:gl_repository) { "project-#{project.id}" }
+ let(:reference_counter) { double('ReferenceCounter') }
describe "GET /internal/check" do
it do
+ expect_any_instance_of(Redis).to receive(:ping).and_return('PONG')
+
get api("/internal/check"), secret_token: secret_token
expect(response).to have_http_status(200)
expect(json_response['api_version']).to eq(API::API.version)
+ expect(json_response['redis']).to be(true)
+ end
+
+ it 'returns false for field `redis` when redis is unavailable' do
+ expect_any_instance_of(Redis).to receive(:ping).and_raise(Errno::ENOENT)
+
+ get api("/internal/check"), secret_token: secret_token
+
+ expect(json_response['redis']).to be(false)
end
end
@@ -661,9 +674,7 @@ describe API::Internal do
# end
describe 'POST /internal/post_receive' do
- let(:gl_repository) { "project-#{project.id}" }
let(:identifier) { 'key-123' }
- let(:reference_counter) { double('ReferenceCounter') }
let(:valid_params) do
{
@@ -749,6 +760,22 @@ describe API::Internal do
end
end
+ describe 'POST /internal/pre_receive' do
+ let(:valid_params) do
+ { gl_repository: gl_repository, secret_token: secret_token }
+ end
+
+ it 'decreases the reference counter and returns the result' do
+ expect(Gitlab::ReferenceCounter).to receive(:new).with(gl_repository)
+ .and_return(reference_counter)
+ expect(reference_counter).to receive(:increase).and_return(true)
+
+ post api("/internal/pre_receive"), valid_params
+
+ expect(json_response['reference_counter_increased']).to be(true)
+ end
+ end
+
def project_with_repo_path(path)
double().tap do |fake_project|
allow(fake_project).to receive_message_chain('repository.path_to_repo' => path)
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index f56baf9663d..2d7cc1a1798 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -1,11 +1,11 @@
require 'spec_helper'
describe API::Jobs do
- let!(:project) do
+ set(:project) do
create(:project, :repository, public_builds: false)
end
- let!(:pipeline) do
+ set(:pipeline) do
create(:ci_empty_pipeline, project: project,
sha: project.commit.id,
ref: project.default_branch)
@@ -188,6 +188,84 @@ describe API::Jobs do
end
end
+ describe 'GET /projects/:id/jobs/:job_id/artifacts/:artifact_path' do
+ context 'when job has artifacts' do
+ let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) }
+
+ let(:artifact) do
+ 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif'
+ end
+
+ context 'when user is anonymous' do
+ let(:api_user) { nil }
+
+ context 'when project is public' do
+ it 'allows to access artifacts' do
+ project.update_column(:visibility_level,
+ Gitlab::VisibilityLevel::PUBLIC)
+ project.update_column(:public_builds, true)
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_http_status(200)
+ end
+ end
+
+ context 'when project is public with builds access disabled' do
+ it 'rejects access to artifacts' do
+ project.update_column(:visibility_level,
+ Gitlab::VisibilityLevel::PUBLIC)
+ project.update_column(:public_builds, false)
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_http_status(403)
+ end
+ end
+
+ context 'when project is private' do
+ it 'rejects access and hides existence of artifacts' do
+ project.update_column(:visibility_level,
+ Gitlab::VisibilityLevel::PRIVATE)
+ project.update_column(:public_builds, true)
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+ end
+
+ context 'when user is authorized' do
+ it 'returns a specific artifact file for a valid path' do
+ expect(Gitlab::Workhorse)
+ .to receive(:send_artifacts_entry)
+ .and_call_original
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_http_status(200)
+ expect(response.headers)
+ .to include('Content-Type' => 'application/json',
+ 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
+ end
+ end
+ end
+
+ context 'when job does not have artifacts' do
+ it 'does not return job artifact file' do
+ get_artifact_file('some/artifact')
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ def get_artifact_file(artifact_path)
+ get api("/projects/#{project.id}/jobs/#{job.id}/" \
+ "artifacts/#{artifact_path}", api_user)
+ end
+ end
+
describe 'GET /projects/:id/jobs/:job_id/artifacts' do
before do
get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
@@ -209,11 +287,12 @@ describe API::Jobs do
end
end
- context 'unauthorized user' do
+ context 'when anonymous user is accessing private artifacts' do
let(:api_user) { nil }
- it 'does not return specific job artifacts' do
- expect(response).to have_http_status(401)
+ it 'hides artifacts and rejects request' do
+ expect(project).to be_private
+ expect(response).to have_http_status(404)
end
end
end
@@ -242,8 +321,9 @@ describe API::Jobs do
get_for_ref
end
- it 'gives 401' do
- expect(response).to have_http_status(401)
+ it 'does not find a resource in a private project' do
+ expect(project).to be_private
+ expect(response).to have_http_status(404)
end
end
diff --git a/spec/requests/api/merge_request_diffs_spec.rb b/spec/requests/api/merge_request_diffs_spec.rb
index d1b22179888..d9da94d4713 100644
--- a/spec/requests/api/merge_request_diffs_spec.rb
+++ b/spec/requests/api/merge_request_diffs_spec.rb
@@ -14,7 +14,7 @@ describe API::MergeRequestDiffs, 'MergeRequestDiffs' do
describe 'GET /projects/:id/merge_requests/:merge_request_iid/versions' do
it 'returns 200 for a valid merge request' do
get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/versions", user)
- merge_request_diff = merge_request.merge_request_diffs.first
+ merge_request_diff = merge_request.merge_request_diffs.last
expect(response.status).to eq 200
expect(response).to include_pagination_headers
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 4490e50702b..9602584f546 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -414,6 +414,7 @@ describe API::Projects do
jobs_enabled: false,
merge_requests_enabled: false,
wiki_enabled: false,
+ resolve_outdated_diff_discussions: false,
only_allow_merge_if_pipeline_succeeds: false,
request_access_enabled: true,
only_allow_merge_if_all_discussions_are_resolved: false,
@@ -477,20 +478,40 @@ describe API::Projects do
expect(json_response['avatar_url']).to eq("http://localhost/uploads/-/system/project/avatar/#{project_id}/banana_sample.gif")
end
+ it 'sets a project as allowing outdated diff discussions to automatically resolve' do
+ project = attributes_for(:project, resolve_outdated_diff_discussions: false)
+
+ post api('/projects', user), project
+
+ expect(json_response['resolve_outdated_diff_discussions']).to be_falsey
+ end
+
+ it 'sets a project as allowing outdated diff discussions to automatically resolve if resolve_outdated_diff_discussions' do
+ project = attributes_for(:project, resolve_outdated_diff_discussions: true)
+
+ post api('/projects', user), project
+
+ expect(json_response['resolve_outdated_diff_discussions']).to be_truthy
+ end
+
it 'sets a project as allowing merge even if build fails' do
- project = attributes_for(:project, { only_allow_merge_if_pipeline_succeeds: false })
+ project = attributes_for(:project, only_allow_merge_if_pipeline_succeeds: false)
+
post api('/projects', user), project
+
expect(json_response['only_allow_merge_if_pipeline_succeeds']).to be_falsey
end
it 'sets a project as allowing merge only if merge_when_pipeline_succeeds' do
- project = attributes_for(:project, { only_allow_merge_if_pipeline_succeeds: true })
+ project = attributes_for(:project, only_allow_merge_if_pipeline_succeeds: true)
+
post api('/projects', user), project
+
expect(json_response['only_allow_merge_if_pipeline_succeeds']).to be_truthy
end
it 'sets a project as allowing merge even if discussions are unresolved' do
- project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: false })
+ project = attributes_for(:project, only_allow_merge_if_all_discussions_are_resolved: false)
post api('/projects', user), project
@@ -506,7 +527,7 @@ describe API::Projects do
end
it 'sets a project as allowing merge only if all discussions are resolved' do
- project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: true })
+ project = attributes_for(:project, only_allow_merge_if_all_discussions_are_resolved: true)
post api('/projects', user), project
@@ -514,7 +535,7 @@ describe API::Projects do
end
it 'ignores import_url when it is nil' do
- project = attributes_for(:project, { import_url: nil })
+ project = attributes_for(:project, import_url: nil)
post api('/projects', user), project
@@ -574,7 +595,7 @@ describe API::Projects do
expect { post api("/projects/user/#{user.id}", admin), name: 'Foo Project' }.to change {Project.count}.by(1)
expect(response).to have_http_status(201)
- project = Project.first
+ project = Project.last
expect(project.name).to eq('Foo Project')
expect(project.path).to eq('foo-project')
@@ -585,7 +606,7 @@ describe API::Projects do
.to change { Project.count }.by(1)
expect(response).to have_http_status(201)
- project = Project.first
+ project = Project.last
expect(project.name).to eq('Foo Project')
expect(project.path).to eq('path-project-Foo')
@@ -642,20 +663,36 @@ describe API::Projects do
expect(json_response['visibility']).to eq('private')
end
+ it 'sets a project as allowing outdated diff discussions to automatically resolve' do
+ project = attributes_for(:project, resolve_outdated_diff_discussions: false)
+
+ post api("/projects/user/#{user.id}", admin), project
+
+ expect(json_response['resolve_outdated_diff_discussions']).to be_falsey
+ end
+
+ it 'sets a project as allowing outdated diff discussions to automatically resolve' do
+ project = attributes_for(:project, resolve_outdated_diff_discussions: true)
+
+ post api("/projects/user/#{user.id}", admin), project
+
+ expect(json_response['resolve_outdated_diff_discussions']).to be_truthy
+ end
+
it 'sets a project as allowing merge even if build fails' do
- project = attributes_for(:project, { only_allow_merge_if_pipeline_succeeds: false })
+ project = attributes_for(:project, only_allow_merge_if_pipeline_succeeds: false)
post api("/projects/user/#{user.id}", admin), project
expect(json_response['only_allow_merge_if_pipeline_succeeds']).to be_falsey
end
- it 'sets a project as allowing merge only if merge_when_pipeline_succeeds' do
- project = attributes_for(:project, { only_allow_merge_if_pipeline_succeeds: true })
+ it 'sets a project as allowing merge only if pipeline succeeds' do
+ project = attributes_for(:project, only_allow_merge_if_pipeline_succeeds: true)
post api("/projects/user/#{user.id}", admin), project
expect(json_response['only_allow_merge_if_pipeline_succeeds']).to be_truthy
end
it 'sets a project as allowing merge even if discussions are unresolved' do
- project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: false })
+ project = attributes_for(:project, only_allow_merge_if_all_discussions_are_resolved: false)
post api("/projects/user/#{user.id}", admin), project
@@ -663,7 +700,7 @@ describe API::Projects do
end
it 'sets a project as allowing merge only if all discussions are resolved' do
- project = attributes_for(:project, { only_allow_merge_if_all_discussions_are_resolved: true })
+ project = attributes_for(:project, only_allow_merge_if_all_discussions_are_resolved: true)
post api("/projects/user/#{user.id}", admin), project
@@ -732,6 +769,7 @@ describe API::Projects do
expect(json_response['wiki_enabled']).to be_present
expect(json_response['jobs_enabled']).to be_present
expect(json_response['snippets_enabled']).to be_present
+ expect(json_response['resolve_outdated_diff_discussions']).to eq(project.resolve_outdated_diff_discussions)
expect(json_response['container_registry_enabled']).to be_present
expect(json_response['created_at']).to be_present
expect(json_response['last_activity_at']).to be_present
diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb
index 48d99841385..7e174903918 100644
--- a/spec/requests/api/services_spec.rb
+++ b/spec/requests/api/services_spec.rb
@@ -1,10 +1,13 @@
require "spec_helper"
describe API::Services do
- let(:user) { create(:user) }
- let(:admin) { create(:admin) }
- let(:user2) { create(:user) }
- let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
+ set(:user) { create(:user) }
+ set(:admin) { create(:admin) }
+ set(:user2) { create(:user) }
+
+ set(:project) do
+ create(:project, creator_id: user.id, namespace: user.namespace)
+ end
Service.available_services_names.each do |service|
describe "PUT /projects/:id/services/#{service.dasherize}" do
@@ -98,8 +101,6 @@ describe API::Services do
end
describe 'POST /projects/:id/services/:slug/trigger' do
- let!(:project) { create(:project) }
-
describe 'Mattermost Service' do
let(:service_name) { 'mattermost_slash_commands' }
diff --git a/spec/requests/api/v3/merge_request_diffs_spec.rb b/spec/requests/api/v3/merge_request_diffs_spec.rb
index 8020ddab4c8..3f21ff40726 100644
--- a/spec/requests/api/v3/merge_request_diffs_spec.rb
+++ b/spec/requests/api/v3/merge_request_diffs_spec.rb
@@ -14,7 +14,7 @@ describe API::V3::MergeRequestDiffs, 'MergeRequestDiffs' do
describe 'GET /projects/:id/merge_requests/:merge_request_id/versions' do
it 'returns 200 for a valid merge request' do
get v3_api("/projects/#{project.id}/merge_requests/#{merge_request.id}/versions", user)
- merge_request_diff = merge_request.merge_request_diffs.first
+ merge_request_diff = merge_request.merge_request_diffs.last
expect(response.status).to eq 200
expect(json_response.size).to eq(merge_request.merge_request_diffs.size)
diff --git a/spec/requests/api/v3/projects_spec.rb b/spec/requests/api/v3/projects_spec.rb
index a514166274a..cae2c3118da 100644
--- a/spec/requests/api/v3/projects_spec.rb
+++ b/spec/requests/api/v3/projects_spec.rb
@@ -687,6 +687,7 @@ describe API::V3::Projects do
expect(json_response['wiki_enabled']).to be_present
expect(json_response['builds_enabled']).to be_present
expect(json_response['snippets_enabled']).to be_present
+ expect(json_response['resolve_outdated_diff_discussions']).to eq(project.resolve_outdated_diff_discussions)
expect(json_response['container_registry_enabled']).to be_present
expect(json_response['created_at']).to be_present
expect(json_response['last_activity_at']).to be_present
diff --git a/spec/requests/api/wikis_spec.rb b/spec/requests/api/wikis_spec.rb
new file mode 100644
index 00000000000..9e889d1eecf
--- /dev/null
+++ b/spec/requests/api/wikis_spec.rb
@@ -0,0 +1,679 @@
+require 'spec_helper'
+
+# For every API endpoint we test 3 states of wikis:
+# - disabled
+# - enabled only for team members
+# - enabled for everyone who has access
+# Every state is tested for 3 user roles:
+# - guest
+# - developer
+# - master
+# because they are 3 edge cases of using wiki pages.
+
+describe API::Wikis do
+ let(:user) { create(:user) }
+ let(:payload) { { content: 'content', format: 'rdoc', title: 'title' } }
+ let(:expected_keys_with_content) { %w(content format slug title) }
+ let(:expected_keys_without_content) { %w(format slug title) }
+
+ shared_examples_for 'returns list of wiki pages' do
+ context 'when wiki has pages' do
+ let!(:pages) do
+ [create(:wiki_page, wiki: project.wiki, attrs: { title: 'page1', content: 'content of page1' }),
+ create(:wiki_page, wiki: project.wiki, attrs: { title: 'page2', content: 'content of page2' })]
+ end
+
+ it 'returns the list of wiki pages without content' do
+ get api(url, user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response.size).to eq(2)
+
+ json_response.each_with_index do |page, index|
+ expect(page.keys).to match_array(expected_keys_without_content)
+ expect(page['slug']).to eq(pages[index].slug)
+ expect(page['title']).to eq(pages[index].title)
+ end
+ end
+
+ it 'returns the list of wiki pages with content' do
+ get api(url, user), with_content: 1
+
+ expect(response).to have_http_status(200)
+ expect(json_response.size).to eq(2)
+
+ json_response.each_with_index do |page, index|
+ expect(page.keys).to match_array(expected_keys_with_content)
+ expect(page['content']).to eq(pages[index].content)
+ expect(page['slug']).to eq(pages[index].slug)
+ expect(page['title']).to eq(pages[index].title)
+ end
+ end
+ end
+
+ it 'return the empty list of wiki pages' do
+ get api(url, user)
+
+ expect(response).to have_http_status(200)
+ expect(json_response.size).to eq(0)
+ end
+ end
+
+ shared_examples_for 'returns wiki page' do
+ it 'returns the wiki page' do
+ expect(response).to have_http_status(200)
+ expect(json_response.size).to eq(4)
+ expect(json_response.keys).to match_array(expected_keys_with_content)
+ expect(json_response['content']).to eq(page.content)
+ expect(json_response['slug']).to eq(page.slug)
+ expect(json_response['title']).to eq(page.title)
+ end
+ end
+
+ shared_examples_for 'creates wiki page' do
+ it 'creates the wiki page' do
+ post(api(url, user), payload)
+
+ expect(response).to have_http_status(201)
+ expect(json_response.size).to eq(4)
+ expect(json_response.keys).to match_array(expected_keys_with_content)
+ expect(json_response['content']).to eq(payload[:content])
+ expect(json_response['slug']).to eq(payload[:title].tr(' ', '-'))
+ expect(json_response['title']).to eq(payload[:title])
+ expect(json_response['rdoc']).to eq(payload[:rdoc])
+ end
+
+ [:title, :content].each do |part|
+ it "responds with validation error on empty #{part}" do
+ payload.delete(part)
+
+ post(api(url, user), payload)
+
+ expect(response).to have_http_status(400)
+ expect(json_response.size).to eq(1)
+ expect(json_response['error']).to eq("#{part} is missing")
+ end
+ end
+ end
+
+ shared_examples_for 'updates wiki page' do
+ it 'updates the wiki page' do
+ expect(response).to have_http_status(200)
+ expect(json_response.size).to eq(4)
+ expect(json_response.keys).to match_array(expected_keys_with_content)
+ expect(json_response['content']).to eq(payload[:content])
+ expect(json_response['slug']).to eq(payload[:title].tr(' ', '-'))
+ expect(json_response['title']).to eq(payload[:title])
+ end
+ end
+
+ shared_examples_for '403 Forbidden' do
+ it 'returns 403 Forbidden' do
+ expect(response).to have_http_status(403)
+ expect(json_response.size).to eq(1)
+ expect(json_response['message']).to eq('403 Forbidden')
+ end
+ end
+
+ shared_examples_for '404 Wiki Page Not Found' do
+ it 'returns 404 Wiki Page Not Found' do
+ expect(response).to have_http_status(404)
+ expect(json_response.size).to eq(1)
+ expect(json_response['message']).to eq('404 Wiki Page Not Found')
+ end
+ end
+
+ shared_examples_for '404 Project Not Found' do
+ it 'returns 404 Project Not Found' do
+ expect(response).to have_http_status(404)
+ expect(json_response.size).to eq(1)
+ expect(json_response['message']).to eq('404 Project Not Found')
+ end
+ end
+
+ shared_examples_for '204 No Content' do
+ it 'returns 204 No Content' do
+ expect(response).to have_http_status(204)
+ end
+ end
+
+ describe 'GET /projects/:id/wikis' do
+ let(:url) { "/projects/#{project.id}/wikis" }
+
+ context 'when wiki is disabled' do
+ let(:project) { create(:project, :wiki_disabled) }
+
+ context 'when user is guest' do
+ before do
+ get api(url)
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+
+ get api(url, user)
+ end
+
+ include_examples '403 Forbidden'
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+
+ get api(url, user)
+ end
+
+ include_examples '403 Forbidden'
+ end
+ end
+
+ context 'when wiki is available only for team members' do
+ let(:project) { create(:project, :wiki_private) }
+
+ context 'when user is guest' do
+ before do
+ get api(url)
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ include_examples 'returns list of wiki pages'
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+ end
+
+ include_examples 'returns list of wiki pages'
+ end
+ end
+
+ context 'when wiki is available for everyone with access' do
+ let(:project) { create(:project) }
+
+ context 'when user is guest' do
+ before do
+ get api(url)
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ include_examples 'returns list of wiki pages'
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+ end
+
+ include_examples 'returns list of wiki pages'
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/wikis/:slug' do
+ let(:page) { create(:wiki_page, wiki: project.wiki) }
+ let(:url) { "/projects/#{project.id}/wikis/#{page.slug}" }
+
+ context 'when wiki is disabled' do
+ let(:project) { create(:project, :wiki_disabled) }
+
+ context 'when user is guest' do
+ before do
+ get api(url)
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+
+ get api(url, user)
+ end
+
+ include_examples '403 Forbidden'
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+
+ get api(url, user)
+ end
+
+ include_examples '403 Forbidden'
+ end
+ end
+
+ context 'when wiki is available only for team members' do
+ let(:project) { create(:project, :wiki_private) }
+
+ context 'when user is guest' do
+ before do
+ get api(url)
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+ get api(url, user)
+ end
+
+ include_examples 'returns wiki page'
+
+ context 'when page is not existing' do
+ let(:url) { "/projects/#{project.id}/wikis/unknown" }
+
+ include_examples '404 Wiki Page Not Found'
+ end
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+
+ get api(url, user)
+ end
+
+ include_examples 'returns wiki page'
+
+ context 'when page is not existing' do
+ let(:url) { "/projects/#{project.id}/wikis/unknown" }
+
+ include_examples '404 Wiki Page Not Found'
+ end
+ end
+ end
+
+ context 'when wiki is available for everyone with access' do
+ let(:project) { create(:project) }
+
+ context 'when user is guest' do
+ before do
+ get api(url)
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+
+ get api(url, user)
+ end
+
+ include_examples 'returns wiki page'
+
+ context 'when page is not existing' do
+ let(:url) { "/projects/#{project.id}/wikis/unknown" }
+
+ include_examples '404 Wiki Page Not Found'
+ end
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+
+ get api(url, user)
+ end
+
+ include_examples 'returns wiki page'
+
+ context 'when page is not existing' do
+ let(:url) { "/projects/#{project.id}/wikis/unknown" }
+
+ include_examples '404 Wiki Page Not Found'
+ end
+ end
+ end
+ end
+
+ describe 'POST /projects/:id/wikis' do
+ let(:payload) { { title: 'title', content: 'content' } }
+ let(:url) { "/projects/#{project.id}/wikis" }
+
+ context 'when wiki is disabled' do
+ let(:project) { create(:project, :wiki_disabled) }
+
+ context 'when user is guest' do
+ before do
+ post(api(url), payload)
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+ post(api(url, user), payload)
+ end
+
+ include_examples '403 Forbidden'
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+ post(api(url, user), payload)
+ end
+
+ include_examples '403 Forbidden'
+ end
+ end
+
+ context 'when wiki is available only for team members' do
+ let(:project) { create(:project, :wiki_private) }
+
+ context 'when user is guest' do
+ before do
+ post(api(url), payload)
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ include_examples 'creates wiki page'
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+ end
+
+ include_examples 'creates wiki page'
+ end
+ end
+
+ context 'when wiki is available for everyone with access' do
+ let(:project) { create(:project) }
+
+ context 'when user is guest' do
+ before do
+ post(api(url), payload)
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ include_examples 'creates wiki page'
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+ end
+
+ include_examples 'creates wiki page'
+ end
+ end
+ end
+
+ describe 'PUT /projects/:id/wikis/:slug' do
+ let(:page) { create(:wiki_page, wiki: project.wiki) }
+ let(:payload) { { title: 'new title', content: 'new content' } }
+ let(:url) { "/projects/#{project.id}/wikis/#{page.slug}" }
+
+ context 'when wiki is disabled' do
+ let(:project) { create(:project, :wiki_disabled) }
+
+ context 'when user is guest' do
+ before do
+ put(api(url), payload)
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+
+ put(api(url, user), payload)
+ end
+
+ include_examples '403 Forbidden'
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+
+ put(api(url, user), payload)
+ end
+
+ include_examples '403 Forbidden'
+ end
+ end
+
+ context 'when wiki is available only for team members' do
+ let(:project) { create(:project, :wiki_private) }
+
+ context 'when user is guest' do
+ before do
+ put(api(url), payload)
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+
+ put(api(url, user), payload)
+ end
+
+ include_examples 'updates wiki page'
+
+ context 'when page is not existing' do
+ let(:url) { "/projects/#{project.id}/wikis/unknown" }
+
+ include_examples '404 Wiki Page Not Found'
+ end
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+
+ put(api(url, user), payload)
+ end
+
+ include_examples 'updates wiki page'
+
+ context 'when page is not existing' do
+ let(:url) { "/projects/#{project.id}/wikis/unknown" }
+
+ include_examples '404 Wiki Page Not Found'
+ end
+ end
+ end
+
+ context 'when wiki is available for everyone with access' do
+ let(:project) { create(:project) }
+
+ context 'when user is guest' do
+ before do
+ put(api(url), payload)
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+
+ put(api(url, user), payload)
+ end
+
+ include_examples 'updates wiki page'
+
+ context 'when page is not existing' do
+ let(:url) { "/projects/#{project.id}/wikis/unknown" }
+
+ include_examples '404 Wiki Page Not Found'
+ end
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+
+ put(api(url, user), payload)
+ end
+
+ include_examples 'updates wiki page'
+
+ context 'when page is not existing' do
+ let(:url) { "/projects/#{project.id}/wikis/unknown" }
+
+ include_examples '404 Wiki Page Not Found'
+ end
+ end
+ end
+ end
+
+ describe 'DELETE /projects/:id/wikis/:slug' do
+ let(:page) { create(:wiki_page, wiki: project.wiki) }
+ let(:url) { "/projects/#{project.id}/wikis/#{page.slug}" }
+
+ context 'when wiki is disabled' do
+ let(:project) { create(:project, :wiki_disabled) }
+
+ context 'when user is guest' do
+ before do
+ delete(api(url))
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+
+ delete(api(url, user))
+ end
+
+ include_examples '403 Forbidden'
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+
+ delete(api(url, user))
+ end
+
+ include_examples '403 Forbidden'
+ end
+ end
+
+ context 'when wiki is available only for team members' do
+ let(:project) { create(:project, :wiki_private) }
+
+ context 'when user is guest' do
+ before do
+ delete(api(url))
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+
+ delete(api(url, user))
+ end
+
+ include_examples '403 Forbidden'
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+
+ delete(api(url, user))
+ end
+
+ include_examples '204 No Content'
+ end
+ end
+
+ context 'when wiki is available for everyone with access' do
+ let(:project) { create(:project) }
+
+ context 'when user is guest' do
+ before do
+ delete(api(url))
+ end
+
+ include_examples '404 Project Not Found'
+ end
+
+ context 'when user is developer' do
+ before do
+ project.add_developer(user)
+
+ delete(api(url, user))
+ end
+
+ include_examples '403 Forbidden'
+ end
+
+ context 'when user is master' do
+ before do
+ project.add_master(user)
+
+ delete(api(url, user))
+ end
+
+ include_examples '204 No Content'
+
+ context 'when page is not existing' do
+ let(:url) { "/projects/#{project.id}/wikis/unknown" }
+
+ include_examples '404 Wiki Page Not Found'
+ end
+ end
+ end
+ end
+end