diff options
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/concerns/internal_redirect_spec.rb | 25 | ||||
-rw-r--r-- | spec/controllers/projects/blob_controller_spec.rb | 19 | ||||
-rw-r--r-- | spec/features/issues/filtered_search/dropdown_assignee_spec.rb | 51 | ||||
-rw-r--r-- | spec/features/issues/user_uses_slash_commands_spec.rb | 4 | ||||
-rw-r--r-- | spec/features/projects/deploy_keys_spec.rb | 3 | ||||
-rw-r--r-- | spec/features/projects/diffs/diff_show_spec.rb | 3 | ||||
-rw-r--r-- | spec/graphql/resolvers/merge_request_resolver_spec.rb | 23 | ||||
-rw-r--r-- | spec/graphql/types/project_type_spec.rb | 9 | ||||
-rw-r--r-- | spec/graphql/types/query_type_spec.rb | 16 | ||||
-rw-r--r-- | spec/javascripts/ide/stores/modules/commit/actions_spec.js | 99 | ||||
-rw-r--r-- | spec/javascripts/ide/stores/utils_spec.js | 56 | ||||
-rw-r--r-- | spec/models/ci/build_trace_chunk_spec.rb | 8 | ||||
-rw-r--r-- | spec/requests/api/graphql/merge_request_query_spec.rb | 49 | ||||
-rw-r--r-- | spec/requests/api/graphql/project_query_spec.rb | 63 | ||||
-rw-r--r-- | spec/support/helpers/graphql_helpers.rb | 15 | ||||
-rw-r--r-- | spec/support/matchers/graphql_matchers.rb | 6 |
16 files changed, 249 insertions, 200 deletions
diff --git a/spec/controllers/concerns/internal_redirect_spec.rb b/spec/controllers/concerns/internal_redirect_spec.rb index a0ee13b2352..7e23b56356e 100644 --- a/spec/controllers/concerns/internal_redirect_spec.rb +++ b/spec/controllers/concerns/internal_redirect_spec.rb @@ -54,6 +54,31 @@ describe InternalRedirect do end end + describe '#sanitize_redirect' do + let(:valid_path) { '/hello/world?hello=world' } + let(:valid_url) { "http://test.host#{valid_path}" } + + it 'returns `nil` for invalid paths' do + invalid_path = '//not/valid' + + expect(controller.sanitize_redirect(invalid_path)).to eq nil + end + + it 'returns `nil` for invalid urls' do + input = 'http://test.host:3000/invalid' + + expect(controller.sanitize_redirect(input)).to eq nil + end + + it 'returns input for valid paths' do + expect(controller.sanitize_redirect(valid_path)).to eq valid_path + end + + it 'returns path for valid urls' do + expect(controller.sanitize_redirect(valid_url)).to eq valid_path + end + end + describe '#host_allowed?' do it 'allows uris with the same host and port' do expect(controller.host_allowed?(URI('http://test.host/test'))).to be(true) diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb index 00a7df6ccc8..9e696e9cb29 100644 --- a/spec/controllers/projects/blob_controller_spec.rb +++ b/spec/controllers/projects/blob_controller_spec.rb @@ -55,6 +55,25 @@ describe Projects::BlobController do expect(json_response).to have_key 'raw_path' end end + + context "with viewer=none" do + let(:id) { 'master/README.md' } + + before do + get(:show, + namespace_id: project.namespace, + project_id: project, + id: id, + format: :json, + viewer: 'none') + end + + it do + expect(response).to be_ok + expect(json_response).not_to have_key 'html' + expect(json_response).to have_key 'raw_path' + end + end end context 'with tree path' do diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb index cbd0949c192..c8115db9212 100644 --- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb @@ -31,7 +31,7 @@ describe 'Dropdown assignee', :js do describe 'behavior' do it 'opens when the search bar has assignee:' do - filtered_search.set('assignee:') + input_filtered_search('assignee:', submit: false, extra_space: false) expect(page).to have_css(js_dropdown_assignee, visible: true) end @@ -44,6 +44,7 @@ describe 'Dropdown assignee', :js do it 'should show loading indicator when opened' do slow_requests do + # We aren't using `input_filtered_search` because we want to see the loading indicator filtered_search.set('assignee:') expect(page).to have_css('#js-dropdown-assignee .filter-dropdown-loading', visible: true) @@ -51,19 +52,19 @@ describe 'Dropdown assignee', :js do end it 'should hide loading indicator when loaded' do - filtered_search.set('assignee:') + input_filtered_search('assignee:', submit: false, extra_space: false) expect(find(js_dropdown_assignee)).not_to have_css('.filter-dropdown-loading') end it 'should load all the assignees when opened' do - filtered_search.set('assignee:') + input_filtered_search('assignee:', submit: false, extra_space: false) expect(dropdown_assignee_size).to eq(4) end it 'shows current user at top of dropdown' do - filtered_search.set('assignee:') + input_filtered_search('assignee:', submit: false, extra_space: false) expect(filter_dropdown.first('.filter-dropdown-item')).to have_content(user.name) end @@ -71,7 +72,7 @@ describe 'Dropdown assignee', :js do describe 'filtering' do before do - filtered_search.set('assignee:') + input_filtered_search('assignee:', submit: false, extra_space: false) expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_john.name) expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name) @@ -79,23 +80,21 @@ describe 'Dropdown assignee', :js do end it 'filters by name' do - filtered_search.send_keys('j') + input_filtered_search('jac', submit: false, extra_space: false) - expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_john.name) expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name) expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_no_content(user.name) end it 'filters by case insensitive name' do - filtered_search.send_keys('J') + input_filtered_search('JAC', submit: false, extra_space: false) - expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_john.name) expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name) expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_no_content(user.name) end it 'filters by username with symbol' do - filtered_search.send_keys('@ot') + input_filtered_search('@ott', submit: false, extra_space: false) expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name) expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user.name) @@ -103,7 +102,7 @@ describe 'Dropdown assignee', :js do end it 'filters by case insensitive username with symbol' do - filtered_search.send_keys('@OT') + input_filtered_search('@OTT', submit: false, extra_space: false) expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name) expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user.name) @@ -111,7 +110,9 @@ describe 'Dropdown assignee', :js do end it 'filters by username without symbol' do - filtered_search.send_keys('ot') + input_filtered_search('ott', submit: false, extra_space: false) + + wait_for_requests expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name) expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user.name) @@ -119,7 +120,9 @@ describe 'Dropdown assignee', :js do end it 'filters by case insensitive username without symbol' do - filtered_search.send_keys('OT') + input_filtered_search('OTT', submit: false, extra_space: false) + + wait_for_requests expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user_jacob.name) expect(find("#{js_dropdown_assignee} .filter-dropdown")).to have_content(user.name) @@ -129,7 +132,7 @@ describe 'Dropdown assignee', :js do describe 'selecting from dropdown' do before do - filtered_search.set('assignee:') + input_filtered_search('assignee:', submit: false, extra_space: false) end it 'fills in the assignee username when the assignee has not been filtered' do @@ -143,7 +146,7 @@ describe 'Dropdown assignee', :js do end it 'fills in the assignee username when the assignee has been filtered' do - filtered_search.send_keys('roo') + input_filtered_search('roo', submit: false, extra_space: false) click_assignee(user.name) wait_for_requests @@ -165,7 +168,7 @@ describe 'Dropdown assignee', :js do describe 'selecting from dropdown without Ajax call' do before do Gitlab::Testing::RequestBlockerMiddleware.block_requests! - filtered_search.set('assignee:') + input_filtered_search('assignee:', submit: false, extra_space: false) end after do @@ -183,31 +186,31 @@ describe 'Dropdown assignee', :js do describe 'input has existing content' do it 'opens assignee dropdown with existing search term' do - filtered_search.set('searchTerm assignee:') + input_filtered_search('searchTerm assignee:', submit: false, extra_space: false) expect(page).to have_css(js_dropdown_assignee, visible: true) end it 'opens assignee dropdown with existing author' do - filtered_search.set('author:@user assignee:') + input_filtered_search('author:@user assignee:', submit: false, extra_space: false) expect(page).to have_css(js_dropdown_assignee, visible: true) end it 'opens assignee dropdown with existing label' do - filtered_search.set('label:~bug assignee:') + input_filtered_search('label:~bug assignee:', submit: false, extra_space: false) expect(page).to have_css(js_dropdown_assignee, visible: true) end it 'opens assignee dropdown with existing milestone' do - filtered_search.set('milestone:%v1.0 assignee:') + input_filtered_search('milestone:%v1.0 assignee:', submit: false, extra_space: false) expect(page).to have_css(js_dropdown_assignee, visible: true) end it 'opens assignee dropdown with existing my-reaction' do - filtered_search.set('my-reaction:star assignee:') + input_filtered_search('my-reaction:star assignee:', submit: false, extra_space: false) expect(page).to have_css(js_dropdown_assignee, visible: true) end @@ -215,8 +218,7 @@ describe 'Dropdown assignee', :js do describe 'caching requests' do it 'caches requests after the first load' do - filtered_search.set('assignee') - filtered_search.send_keys(':') + input_filtered_search('assignee:', submit: false, extra_space: false) initial_size = dropdown_assignee_size expect(initial_size).to be > 0 @@ -224,8 +226,7 @@ describe 'Dropdown assignee', :js do new_user = create(:user) project.add_master(new_user) find('.filtered-search-box .clear-search').click - filtered_search.set('assignee') - filtered_search.send_keys(':') + input_filtered_search('assignee:', submit: false, extra_space: false) expect(dropdown_assignee_size).to eq(initial_size) end diff --git a/spec/features/issues/user_uses_slash_commands_spec.rb b/spec/features/issues/user_uses_slash_commands_spec.rb index dacca494755..17818beb947 100644 --- a/spec/features/issues/user_uses_slash_commands_spec.rb +++ b/spec/features/issues/user_uses_slash_commands_spec.rb @@ -226,7 +226,9 @@ feature 'Issues > User uses quick actions', :js do it 'does not move the issue' do add_note("/move #{project_unauthorized.full_path}") - expect(page).not_to have_content 'Commands applied' + wait_for_requests + + expect(page).to have_content 'Commands applied' expect(issue.reload).to be_open end end diff --git a/spec/features/projects/deploy_keys_spec.rb b/spec/features/projects/deploy_keys_spec.rb index 43a23c42f83..1552a3512dd 100644 --- a/spec/features/projects/deploy_keys_spec.rb +++ b/spec/features/projects/deploy_keys_spec.rb @@ -22,7 +22,8 @@ describe 'Project deploy keys', :js do accept_confirm { find('.ic-remove').click() } - expect(page).not_to have_selector('.fa-spinner', count: 0) + wait_for_requests + expect(page).to have_selector('.deploy-key', count: 0) end end diff --git a/spec/features/projects/diffs/diff_show_spec.rb b/spec/features/projects/diffs/diff_show_spec.rb index c1307ab640f..9bfcb1e816a 100644 --- a/spec/features/projects/diffs/diff_show_spec.rb +++ b/spec/features/projects/diffs/diff_show_spec.rb @@ -166,8 +166,7 @@ feature 'Diff file viewer', :js do context 'expanding the diff' do before do - # We can't use `click_link` because the "link" doesn't have an `href`. - find('a.click-to-expand').click + click_button 'Click to expand it.' wait_for_requests end diff --git a/spec/graphql/resolvers/merge_request_resolver_spec.rb b/spec/graphql/resolvers/merge_request_resolver_spec.rb index af015533209..73993b3a039 100644 --- a/spec/graphql/resolvers/merge_request_resolver_spec.rb +++ b/spec/graphql/resolvers/merge_request_resolver_spec.rb @@ -10,49 +10,36 @@ describe Resolvers::MergeRequestResolver do set(:other_project) { create(:project, :repository) } set(:other_merge_request) { create(:merge_request, source_project: other_project, target_project: other_project) } - let(:full_path) { project.full_path } let(:iid_1) { merge_request_1.iid } let(:iid_2) { merge_request_2.iid } - let(:other_full_path) { other_project.full_path } let(:other_iid) { other_merge_request.iid } describe '#resolve' do it 'batch-resolves merge requests by target project full path and IID' do - path = full_path # avoid database query - result = batch(max_queries: 2) do - [resolve_mr(path, iid_1), resolve_mr(path, iid_2)] + [resolve_mr(project, iid_1), resolve_mr(project, iid_2)] end expect(result).to contain_exactly(merge_request_1, merge_request_2) end it 'can batch-resolve merge requests from different projects' do - path = project.full_path # avoid database queries - other_path = other_full_path - result = batch(max_queries: 3) do - [resolve_mr(path, iid_1), resolve_mr(path, iid_2), resolve_mr(other_path, other_iid)] + [resolve_mr(project, iid_1), resolve_mr(project, iid_2), resolve_mr(other_project, other_iid)] end expect(result).to contain_exactly(merge_request_1, merge_request_2, other_merge_request) end it 'resolves an unknown iid to nil' do - result = batch { resolve_mr(full_path, -1) } - - expect(result).to be_nil - end - - it 'resolves a known iid for an unknown full_path to nil' do - result = batch { resolve_mr('unknown/project', iid_1) } + result = batch { resolve_mr(project, -1) } expect(result).to be_nil end end - def resolve_mr(full_path, iid) - resolve(described_class, args: { full_path: full_path, iid: iid }) + def resolve_mr(project, iid) + resolve(described_class, obj: project, args: { iid: iid }) end end diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb index e0f89105b86..b4eeca2e3f1 100644 --- a/spec/graphql/types/project_type_spec.rb +++ b/spec/graphql/types/project_type_spec.rb @@ -2,4 +2,13 @@ require 'spec_helper' describe GitlabSchema.types['Project'] do it { expect(described_class.graphql_name).to eq('Project') } + + describe 'nested merge request' do + it { expect(described_class).to have_graphql_field(:merge_request) } + + it 'authorizes the merge request' do + expect(described_class.fields['mergeRequest']) + .to require_graphql_authorizations(:read_merge_request) + end + end end diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb index 8488252fd59..e1df6f9811d 100644 --- a/spec/graphql/types/query_type_spec.rb +++ b/spec/graphql/types/query_type_spec.rb @@ -5,7 +5,7 @@ describe GitlabSchema.types['Query'] do expect(described_class.graphql_name).to eq('Query') end - it { is_expected.to have_graphql_fields(:project, :merge_request, :echo) } + it { is_expected.to have_graphql_fields(:project, :echo) } describe 'project field' do subject { described_class.fields['project'] } @@ -20,18 +20,4 @@ describe GitlabSchema.types['Query'] do is_expected.to require_graphql_authorizations(:read_project) end end - - describe 'merge_request field' do - subject { described_class.fields['mergeRequest'] } - - it 'finds MRs by project and IID' do - is_expected.to have_graphql_arguments(:full_path, :iid) - is_expected.to have_graphql_type(Types::MergeRequestType) - is_expected.to have_graphql_resolver(Resolvers::MergeRequestResolver) - end - - it 'authorizes with read_merge_request' do - is_expected.to require_graphql_authorizations(:read_merge_request) - end - end end diff --git a/spec/javascripts/ide/stores/modules/commit/actions_spec.js b/spec/javascripts/ide/stores/modules/commit/actions_spec.js index a2869ff378b..133ad627f34 100644 --- a/spec/javascripts/ide/stores/modules/commit/actions_spec.js +++ b/spec/javascripts/ide/stores/modules/commit/actions_spec.js @@ -108,77 +108,6 @@ describe('IDE commit module actions', () => { }); }); - describe('checkCommitStatus', () => { - beforeEach(() => { - store.state.currentProjectId = 'abcproject'; - store.state.currentBranchId = 'master'; - store.state.projects.abcproject = { - branches: { - master: { - workingReference: '1', - }, - }, - }; - }); - - it('calls service', done => { - spyOn(service, 'getBranchData').and.returnValue( - Promise.resolve({ - data: { - commit: { id: '123' }, - }, - }), - ); - - store - .dispatch('commit/checkCommitStatus') - .then(() => { - expect(service.getBranchData).toHaveBeenCalledWith('abcproject', 'master'); - - done(); - }) - .catch(done.fail); - }); - - it('returns true if current ref does not equal returned ID', done => { - spyOn(service, 'getBranchData').and.returnValue( - Promise.resolve({ - data: { - commit: { id: '123' }, - }, - }), - ); - - store - .dispatch('commit/checkCommitStatus') - .then(val => { - expect(val).toBeTruthy(); - - done(); - }) - .catch(done.fail); - }); - - it('returns false if current ref equals returned ID', done => { - spyOn(service, 'getBranchData').and.returnValue( - Promise.resolve({ - data: { - commit: { id: '1' }, - }, - }), - ); - - store - .dispatch('commit/checkCommitStatus') - .then(val => { - expect(val).toBeFalsy(); - - done(); - }) - .catch(done.fail); - }); - }); - describe('updateFilesAfterCommit', () => { const data = { id: '123', @@ -314,6 +243,7 @@ describe('IDE commit module actions', () => { ...file('changed'), type: 'blob', active: true, + lastCommitSha: '123456789', }; store.state.stagedFiles.push(f); store.state.changedFiles = [ @@ -366,6 +296,7 @@ describe('IDE commit module actions', () => { file_path: jasmine.anything(), content: jasmine.anything(), encoding: jasmine.anything(), + last_commit_id: undefined, }, ], start_branch: 'master', @@ -376,6 +307,32 @@ describe('IDE commit module actions', () => { .catch(done.fail); }); + it('sends lastCommit ID when not creating new branch', done => { + store.state.commit.commitAction = '1'; + + store + .dispatch('commit/commitChanges') + .then(() => { + expect(service.commit).toHaveBeenCalledWith('abcproject', { + branch: jasmine.anything(), + commit_message: 'testing 123', + actions: [ + { + action: 'update', + file_path: jasmine.anything(), + content: jasmine.anything(), + encoding: jasmine.anything(), + last_commit_id: '123456789', + }, + ], + start_branch: undefined, + }); + + done(); + }) + .catch(done.fail); + }); + it('sets last Commit Msg', done => { store .dispatch('commit/commitChanges') diff --git a/spec/javascripts/ide/stores/utils_spec.js b/spec/javascripts/ide/stores/utils_spec.js index f38ac6dd82f..a7bd443af51 100644 --- a/spec/javascripts/ide/stores/utils_spec.js +++ b/spec/javascripts/ide/stores/utils_spec.js @@ -1,4 +1,5 @@ import * as utils from '~/ide/stores/utils'; +import { file } from '../helpers'; describe('Multi-file store utils', () => { describe('setPageTitle', () => { @@ -63,4 +64,59 @@ describe('Multi-file store utils', () => { expect(foundEntry).toBeUndefined(); }); }); + + describe('createCommitPayload', () => { + it('returns API payload', () => { + const state = { + commitMessage: 'commit message', + }; + const rootState = { + stagedFiles: [ + { + ...file('staged'), + path: 'staged', + content: 'updated file content', + lastCommitSha: '123456789', + }, + { + ...file('newFile'), + path: 'added', + tempFile: true, + content: 'new file content', + base64: true, + lastCommitSha: '123456789', + }, + ], + currentBranchId: 'master', + }; + const payload = utils.createCommitPayload({ + branch: 'master', + newBranch: false, + state, + rootState, + }); + + expect(payload).toEqual({ + branch: 'master', + commit_message: 'commit message', + actions: [ + { + action: 'update', + file_path: 'staged', + content: 'updated file content', + encoding: 'text', + last_commit_id: '123456789', + }, + { + action: 'create', + file_path: 'added', + content: 'new file content', + encoding: 'base64', + last_commit_id: '123456789', + }, + ], + start_branch: undefined, + }); + }); + }); }); diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb index cbcf1e55979..b5a6d959ccb 100644 --- a/spec/models/ci/build_trace_chunk_spec.rb +++ b/spec/models/ci/build_trace_chunk_spec.rb @@ -54,14 +54,6 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do it { is_expected.to eq('Sample data in db') } end - - context 'when data_store is others' do - before do - build_trace_chunk.send(:write_attribute, :data_store, -1) - end - - it { expect { subject }.to raise_error('Unsupported data store') } - end end describe '#set_data' do diff --git a/spec/requests/api/graphql/merge_request_query_spec.rb b/spec/requests/api/graphql/merge_request_query_spec.rb deleted file mode 100644 index 12b1d5d18a2..00000000000 --- a/spec/requests/api/graphql/merge_request_query_spec.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'spec_helper' - -describe 'getting merge request information' do - include GraphqlHelpers - - let(:project) { create(:project, :repository) } - let(:merge_request) { create(:merge_request, source_project: project) } - let(:current_user) { create(:user) } - - let(:query) do - attributes = { - 'fullPath' => merge_request.project.full_path, - 'iid' => merge_request.iid - } - graphql_query_for('mergeRequest', attributes) - end - - context 'when the user has access to the merge request' do - before do - project.add_developer(current_user) - post_graphql(query, current_user: current_user) - end - - it 'returns the merge request' do - expect(graphql_data['mergeRequest']).not_to be_nil - end - - # This is a field coming from the `MergeRequestPresenter` - it 'includes a web_url' do - expect(graphql_data['mergeRequest']['webUrl']).to be_present - end - - it_behaves_like 'a working graphql query' - end - - context 'when the user does not have access to the merge request' do - before do - post_graphql(query, current_user: current_user) - end - - it 'returns an empty field' do - post_graphql(query, current_user: current_user) - - expect(graphql_data['mergeRequest']).to be_nil - end - - it_behaves_like 'a working graphql query' - end -end diff --git a/spec/requests/api/graphql/project_query_spec.rb b/spec/requests/api/graphql/project_query_spec.rb index 8196bcfa87c..796ffc9d569 100644 --- a/spec/requests/api/graphql/project_query_spec.rb +++ b/spec/requests/api/graphql/project_query_spec.rb @@ -13,27 +13,76 @@ describe 'getting project information' do context 'when the user has access to the project' do before do project.add_developer(current_user) - post_graphql(query, current_user: current_user) end it 'includes the project' do + post_graphql(query, current_user: current_user) + expect(graphql_data['project']).not_to be_nil end - it_behaves_like 'a working graphql query' - end + it_behaves_like 'a working graphql query' do + before do + post_graphql(query, current_user: current_user) + end + end - context 'when the user does not have access to the project' do - before do - post_graphql(query, current_user: current_user) + context 'when requesting a nested merge request' do + let(:merge_request) { create(:merge_request, source_project: project) } + let(:merge_request_graphql_data) { graphql_data['project']['mergeRequest'] } + + let(:query) do + graphql_query_for( + 'project', + { 'fullPath' => project.full_path }, + query_graphql_field('mergeRequest', iid: merge_request.iid) + ) + end + + it_behaves_like 'a working graphql query' do + before do + post_graphql(query, current_user: current_user) + end + end + + it 'contains merge request information' do + post_graphql(query, current_user: current_user) + + expect(merge_request_graphql_data).not_to be_nil + end + + # This is a field coming from the `MergeRequestPresenter` + it 'includes a web_url' do + post_graphql(query, current_user: current_user) + + expect(merge_request_graphql_data['webUrl']).to be_present + end + + context 'when the user does not have access to the merge request' do + let(:project) { create(:project, :public, :repository) } + + it 'returns nil' do + project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE) + + post_graphql(query) + + expect(merge_request_graphql_data).to be_nil + end + end end + end + context 'when the user does not have access to the project' do it 'returns an empty field' do post_graphql(query, current_user: current_user) expect(graphql_data['project']).to be_nil end - it_behaves_like 'a working graphql query' + it_behaves_like 'a working graphql query' do + before do + post_graphql(query, current_user: current_user) + end + end end end diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb index 30ff9a1196a..0930b9da368 100644 --- a/spec/support/helpers/graphql_helpers.rb +++ b/spec/support/helpers/graphql_helpers.rb @@ -34,14 +34,20 @@ module GraphqlHelpers end def graphql_query_for(name, attributes = {}, fields = nil) + <<~QUERY + { + #{query_graphql_field(name, attributes, fields)} + } + QUERY + end + + def query_graphql_field(name, attributes = {}, fields = nil) fields ||= all_graphql_fields_for(name.classify) attributes = attributes_to_graphql(attributes) <<~QUERY - { #{name}(#{attributes}) { #{fields} } - } QUERY end @@ -50,12 +56,15 @@ module GraphqlHelpers return "" unless type type.fields.map do |name, field| + # We can't guess arguments, so skip fields that require them + next if field.arguments.any? + if scalar?(field) name else "#{name} { #{all_graphql_fields_for(field_type(field))} }" end - end.join("\n") + end.compact.join("\n") end def attributes_to_graphql(attributes) diff --git a/spec/support/matchers/graphql_matchers.rb b/spec/support/matchers/graphql_matchers.rb index ba7a1c8cde0..d23cbaf4beb 100644 --- a/spec/support/matchers/graphql_matchers.rb +++ b/spec/support/matchers/graphql_matchers.rb @@ -13,6 +13,12 @@ RSpec::Matchers.define :have_graphql_fields do |*expected| end end +RSpec::Matchers.define :have_graphql_field do |field_name| + match do |kls| + expect(kls.fields.keys).to include(GraphqlHelpers.fieldnamerize(field_name)) + end +end + RSpec::Matchers.define :have_graphql_arguments do |*expected| include GraphqlHelpers |