diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-07 00:11:11 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-07 00:11:11 +0000 |
commit | d4f8f25db649b973f1ae344cb0f8a407862d106b (patch) | |
tree | f71f2d2243dc768a1ec44e79556d8020bff51dc7 /spec | |
parent | 5f0e3773e9695fd0c9e92ea9180c8a1f5cfaa5c5 (diff) | |
download | gitlab-ce-d4f8f25db649b973f1ae344cb0f8a407862d106b.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/projects/pipelines_controller_spec.rb | 66 | ||||
-rw-r--r-- | spec/features/commits/user_view_commits_spec.rb | 22 | ||||
-rw-r--r-- | spec/finders/releases_finder_spec.rb | 11 | ||||
-rw-r--r-- | spec/frontend/pipelines/components/pipelines_filtered_search_spec.js | 74 | ||||
-rw-r--r-- | spec/frontend/pipelines/mock_data.js | 59 | ||||
-rw-r--r-- | spec/frontend/pipelines/pipelines_spec.js | 28 | ||||
-rw-r--r-- | spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js | 63 | ||||
-rw-r--r-- | spec/graphql/resolvers/release_resolver_spec.rb | 51 | ||||
-rw-r--r-- | spec/graphql/resolvers/releases_resolver_spec.rb | 42 | ||||
-rw-r--r-- | spec/graphql/types/project_type_spec.rb | 16 | ||||
-rw-r--r-- | spec/graphql/types/release_type_spec.rb | 37 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/reports/accessibility_reports_comparer_spec.rb | 270 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/reports/accessibility_reports_spec.rb | 34 |
13 files changed, 766 insertions, 7 deletions
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index 8dc337e3a3d..3c34d41504d 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -145,11 +145,61 @@ describe Projects::PipelinesController do end end - def get_pipelines_index_json + context 'filter by scope' do + it 'returns matched pipelines' do + get_pipelines_index_json(scope: 'running') + + check_pipeline_response(returned: 2, all: 6, running: 2, pending: 1, finished: 3) + end + + context 'scope is branches or tags' do + before do + create(:ci_pipeline, :failed, project: project, ref: 'v1.0.0', tag: true) + end + + context 'when scope is branches' do + it 'returns matched pipelines' do + get_pipelines_index_json(scope: 'branches') + + check_pipeline_response(returned: 1, all: 7, running: 2, pending: 1, finished: 4) + end + end + + context 'when scope is tags' do + it 'returns matched pipelines' do + get_pipelines_index_json(scope: 'tags') + + check_pipeline_response(returned: 1, all: 7, running: 2, pending: 1, finished: 4) + end + end + end + end + + context 'filter by username' do + let!(:pipeline) { create(:ci_pipeline, :running, project: project, user: user) } + + context 'when username exists' do + it 'returns matched pipelines' do + get_pipelines_index_json(username: user.username) + + check_pipeline_response(returned: 1, all: 1, running: 1, pending: 0, finished: 0) + end + end + + context 'when username does not exist' do + it 'returns empty' do + get_pipelines_index_json(username: 'invalid-username') + + check_pipeline_response(returned: 0, all: 0, running: 0, pending: 0, finished: 0) + end + end + end + + def get_pipelines_index_json(params = {}) get :index, params: { namespace_id: project.namespace, project_id: project - }, + }.merge(params), format: :json end @@ -199,6 +249,18 @@ describe Projects::PipelinesController do user: user ) end + + def check_pipeline_response(returned:, all:, running:, pending:, finished:) + aggregate_failures do + expect(response).to match_response_schema('pipeline') + + expect(json_response['pipelines'].count).to eq returned + expect(json_response['count']['all'].to_i).to eq all + expect(json_response['count']['running'].to_i).to eq running + expect(json_response['count']['pending'].to_i).to eq pending + expect(json_response['count']['finished'].to_i).to eq finished + end + end end describe 'GET show.json' do diff --git a/spec/features/commits/user_view_commits_spec.rb b/spec/features/commits/user_view_commits_spec.rb new file mode 100644 index 00000000000..133baca8b1c --- /dev/null +++ b/spec/features/commits/user_view_commits_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Commit > User view commits' do + let_it_be(:project) { create(:project, :public, :repository) } + let_it_be(:user) { project.creator } + + before do + visit project_commits_path(project) + end + + describe 'Commits List' do + it 'displays the correct number of commits per day in the header' do + expect(first('.js-commit-header').find('.commits-count').text).to eq('1 commit') + end + + it 'lists the correct number of commits' do + expect(page).to have_selector('#commits-list > li:nth-child(2) > ul', count: 1) + end + end +end diff --git a/spec/finders/releases_finder_spec.rb b/spec/finders/releases_finder_spec.rb index 3da5ee47b6b..cb4e5fed816 100644 --- a/spec/finders/releases_finder_spec.rb +++ b/spec/finders/releases_finder_spec.rb @@ -5,10 +5,11 @@ require 'spec_helper' describe ReleasesFinder do let(:user) { create(:user) } let(:project) { create(:project, :repository) } + let(:params) { {} } let(:repository) { project.repository } let(:v1_0_0) { create(:release, project: project, tag: 'v1.0.0') } let(:v1_1_0) { create(:release, project: project, tag: 'v1.1.0') } - let(:finder) { described_class.new(project, user) } + let(:finder) { described_class.new(project, user, params) } before do v1_0_0.update_attribute(:released_at, 2.days.ago) @@ -64,6 +65,14 @@ describe ReleasesFinder do expect(subject).to eq([v1_1_0]) end end + + context 'when a tag parameter is passed' do + let(:params) { { tag: 'v1.0.0' } } + + it 'only returns the release with the matching tag' do + expect(subject).to eq([v1_0_0]) + end + end end end end diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js new file mode 100644 index 00000000000..ea98a20f3d0 --- /dev/null +++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js @@ -0,0 +1,74 @@ +import Api from '~/api'; +import { mount } from '@vue/test-utils'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; +import PipelinesFilteredSearch from '~/pipelines/components/pipelines_filtered_search.vue'; +import { users, mockSearch, pipelineWithStages } from '../mock_data'; +import { GlFilteredSearch } from '@gitlab/ui'; + +describe('Pipelines filtered search', () => { + let wrapper; + let mock; + + const findFilteredSearch = () => wrapper.find(GlFilteredSearch); + const getSearchToken = type => + findFilteredSearch() + .props('availableTokens') + .find(token => token.type === type); + + const createComponent = () => { + wrapper = mount(PipelinesFilteredSearch, { + propsData: { + pipelines: [pipelineWithStages], + projectId: '21', + }, + attachToDocument: true, + }); + }; + + beforeEach(() => { + mock = new MockAdapter(axios); + + jest.spyOn(Api, 'projectUsers').mockResolvedValue(users); + + createComponent(); + }); + + afterEach(() => { + mock.restore(); + wrapper.destroy(); + wrapper = null; + }); + + it('displays UI elements', () => { + expect(wrapper.isVueInstance()).toBe(true); + expect(wrapper.isEmpty()).toBe(false); + + expect(findFilteredSearch().exists()).toBe(true); + }); + + it('displays search tokens', () => { + expect(getSearchToken('username')).toMatchObject({ + type: 'username', + icon: 'user', + title: 'Trigger author', + dataType: 'username', + unique: true, + triggerAuthors: users, + operators: [expect.objectContaining({ value: '=' })], + }); + }); + + it('fetches and sets project users', () => { + expect(Api.projectUsers).toHaveBeenCalled(); + + expect(wrapper.vm.projectUsers).toEqual(users); + }); + + it('emits filterPipelines on submit with correct filter', () => { + findFilteredSearch().vm.$emit('submit', mockSearch); + + expect(wrapper.emitted('filterPipelines')).toBeTruthy(); + expect(wrapper.emitted('filterPipelines')[0]).toEqual([mockSearch]); + }); +}); diff --git a/spec/frontend/pipelines/mock_data.js b/spec/frontend/pipelines/mock_data.js index f876987cd88..81503192350 100644 --- a/spec/frontend/pipelines/mock_data.js +++ b/spec/frontend/pipelines/mock_data.js @@ -421,3 +421,62 @@ export const stageReply = { path: '/twitter/flight/pipelines/13#deploy', dropdown_path: '/twitter/flight/pipelines/13/stage.json?stage=deploy', }; + +export const users = [ + { + id: 1, + name: 'Administrator', + username: 'root', + state: 'active', + avatar_url: + 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://192.168.1.22:3000/root', + }, + { + id: 10, + name: 'Angel Spinka', + username: 'shalonda', + state: 'active', + avatar_url: + 'https://www.gravatar.com/avatar/709df1b65ad06764ee2b0edf1b49fc27?s=80\u0026d=identicon', + web_url: 'http://192.168.1.22:3000/shalonda', + }, + { + id: 11, + name: 'Art Davis', + username: 'deja.green', + state: 'active', + avatar_url: + 'https://www.gravatar.com/avatar/bb56834c061522760e7a6dd7d431a306?s=80\u0026d=identicon', + web_url: 'http://192.168.1.22:3000/deja.green', + }, + { + id: 32, + name: 'Arnold Mante', + username: 'reported_user_10', + state: 'active', + avatar_url: + 'https://www.gravatar.com/avatar/ab558033a82466d7905179e837d7723a?s=80\u0026d=identicon', + web_url: 'http://192.168.1.22:3000/reported_user_10', + }, + { + id: 38, + name: 'Cher Wintheiser', + username: 'reported_user_16', + state: 'active', + avatar_url: + 'https://www.gravatar.com/avatar/2640356e8b5bc4314133090994ed162b?s=80\u0026d=identicon', + web_url: 'http://192.168.1.22:3000/reported_user_16', + }, + { + id: 39, + name: 'Bethel Wolf', + username: 'reported_user_17', + state: 'active', + avatar_url: + 'https://www.gravatar.com/avatar/4b948694fadba4b01e4acfc06b065e8e?s=80\u0026d=identicon', + web_url: 'http://192.168.1.22:3000/reported_user_17', + }, +]; + +export const mockSearch = { type: 'username', value: { data: 'root', operator: '=' } }; diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js index 40cd0ad9047..40c493e3aa5 100644 --- a/spec/frontend/pipelines/pipelines_spec.js +++ b/spec/frontend/pipelines/pipelines_spec.js @@ -1,10 +1,12 @@ +import Api from '~/api'; import { mount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; import waitForPromises from 'helpers/wait_for_promises'; import PipelinesComponent from '~/pipelines/components/pipelines.vue'; import Store from '~/pipelines/stores/pipelines_store'; -import { pipelineWithStages, stageReply } from './mock_data'; +import { pipelineWithStages, stageReply, users, mockSearch } from './mock_data'; +import { GlFilteredSearch } from '@gitlab/ui'; describe('Pipelines', () => { const jsonFixtureName = 'pipelines/pipelines.json'; @@ -42,10 +44,14 @@ describe('Pipelines', () => { ...paths, }; + const findFilteredSearch = () => wrapper.find(GlFilteredSearch); + const createComponent = (props = defaultProps, methods) => { wrapper = mount(PipelinesComponent, { + provide: { glFeatures: { filterPipelinesSearch: true } }, propsData: { store: new Store(), + projectId: '21', ...props, }, methods: { @@ -57,6 +63,7 @@ describe('Pipelines', () => { beforeEach(() => { mock = new MockAdapter(axios); pipelines = getJSONFixture(jsonFixtureName); + jest.spyOn(Api, 'projectUsers').mockResolvedValue(users); }); afterEach(() => { @@ -656,4 +663,23 @@ describe('Pipelines', () => { }); }); }); + + describe('Pipeline filters', () => { + beforeEach(() => { + mock.onGet(paths.endpoint).reply(200, pipelines); + createComponent(); + + return waitForPromises(); + }); + + it('updates request data and query params on filter submit', () => { + const updateContentMock = jest.spyOn(wrapper.vm, 'updateContent'); + const expectedQueryParams = { page: '1', scope: 'all', username: 'root' }; + + findFilteredSearch().vm.$emit('submit', [mockSearch]); + + expect(wrapper.vm.requestData).toEqual(expectedQueryParams); + expect(updateContentMock).toHaveBeenCalledWith(expectedQueryParams); + }); + }); }); diff --git a/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js b/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js new file mode 100644 index 00000000000..56aba62ede2 --- /dev/null +++ b/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js @@ -0,0 +1,63 @@ +import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import PipelineTriggerAuthorToken from '~/pipelines/components/tokens/pipeline_trigger_author_token.vue'; +import { users } from '../mock_data'; + +describe('Pipeline Trigger Author Token', () => { + let wrapper; + + const findFilteredSearchToken = () => wrapper.find(GlFilteredSearchToken); + const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion); + + const stubs = { + GlFilteredSearchToken: { + template: `<div><slot name="suggestions"></slot></div>`, + }, + }; + + const defaultProps = { + config: { + type: 'username', + icon: 'user', + title: 'Trigger author', + dataType: 'username', + unique: true, + triggerAuthors: users, + }, + }; + + const createComponent = (props = {}, options) => { + wrapper = shallowMount(PipelineTriggerAuthorToken, { + propsData: { + ...props, + ...defaultProps, + }, + ...options, + }); + }; + + beforeEach(() => { + createComponent({ value: { data: '' } }); + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('passes config correctly', () => { + expect(findFilteredSearchToken().props('config')).toEqual(defaultProps.config); + }); + + describe('shows trigger authors correctly', () => { + it('renders all trigger authors', () => { + createComponent({ value: { data: '' } }, { stubs }); + expect(findAllFilteredSearchSuggestions()).toHaveLength(7); + }); + + it('renders only the trigger author searched for', () => { + createComponent({ value: { data: 'root' } }, { stubs }); + expect(findAllFilteredSearchSuggestions()).toHaveLength(2); + }); + }); +}); diff --git a/spec/graphql/resolvers/release_resolver_spec.rb b/spec/graphql/resolvers/release_resolver_spec.rb new file mode 100644 index 00000000000..71aa4bbb439 --- /dev/null +++ b/spec/graphql/resolvers/release_resolver_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Resolvers::ReleaseResolver do + include GraphqlHelpers + + let_it_be(:project) { create(:project, :private) } + let_it_be(:release) { create(:release, project: project) } + let_it_be(:developer) { create(:user) } + let_it_be(:public_user) { create(:user) } + + let(:args) { { tag_name: release.tag } } + + before do + project.add_developer(developer) + end + + describe '#resolve' do + context 'when the user does not have access to the project' do + let(:current_user) { public_user } + + it 'returns nil' do + expect(resolve_release).to be_nil + end + end + + context "when the user has full access to the project's releases" do + let(:current_user) { developer } + + it 'returns the release associated with the specified tag' do + expect(resolve_release).to eq(release) + end + + context 'when no tag_name argument was passed' do + let(:args) { {} } + + it 'raises an error' do + expect { resolve_release }.to raise_error(ArgumentError, "missing keyword: tag_name") + end + end + end + end + + private + + def resolve_release + context = { current_user: current_user } + resolve(described_class, obj: project, args: args, ctx: context) + end +end diff --git a/spec/graphql/resolvers/releases_resolver_spec.rb b/spec/graphql/resolvers/releases_resolver_spec.rb new file mode 100644 index 00000000000..9de539b417a --- /dev/null +++ b/spec/graphql/resolvers/releases_resolver_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Resolvers::ReleasesResolver do + include GraphqlHelpers + + let_it_be(:project) { create(:project, :private) } + let_it_be(:release_v1) { create(:release, project: project, tag: 'v1.0.0') } + let_it_be(:release_v2) { create(:release, project: project, tag: 'v2.0.0') } + let_it_be(:developer) { create(:user) } + let_it_be(:public_user) { create(:user) } + + before do + project.add_developer(developer) + end + + describe '#resolve' do + context 'when the user does not have access to the project' do + let(:current_user) { public_user } + + it 'returns an empty array' do + expect(resolve_releases).to eq([]) + end + end + + context "when the user has full access to the project's releases" do + let(:current_user) { developer } + + it 'returns all releases associated to the project' do + expect(resolve_releases).to eq([release_v1, release_v2]) + end + end + end + + private + + def resolve_releases + context = { current_user: current_user } + resolve(described_class, obj: project, args: {}, ctx: context) + end +end diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb index 6ea852190c9..e05c5d5e6ad 100644 --- a/spec/graphql/types/project_type_spec.rb +++ b/spec/graphql/types/project_type_spec.rb @@ -24,7 +24,7 @@ describe GitlabSchema.types['Project'] do namespace group statistics repository merge_requests merge_request issues issue pipelines removeSourceBranchAfterMerge sentryDetailedError snippets grafanaIntegration autocloseReferencedIssues suggestion_commit_message environments - boards jira_import_status jira_imports services + boards jira_import_status jira_imports services releases release ] expect(described_class).to include_graphql_fields(*expected_fields) @@ -96,4 +96,18 @@ describe GitlabSchema.types['Project'] do it { is_expected.to have_graphql_type(Types::Projects::ServiceType.connection_type) } end + + describe 'releases field' do + subject { described_class.fields['release'] } + + it { is_expected.to have_graphql_type(Types::ReleaseType) } + it { is_expected.to have_graphql_resolver(Resolvers::ReleaseResolver) } + end + + describe 'release field' do + subject { described_class.fields['releases'] } + + it { is_expected.to have_graphql_type(Types::ReleaseType.connection_type) } + it { is_expected.to have_graphql_resolver(Resolvers::ReleasesResolver) } + end end diff --git a/spec/graphql/types/release_type_spec.rb b/spec/graphql/types/release_type_spec.rb new file mode 100644 index 00000000000..e68b8cd549d --- /dev/null +++ b/spec/graphql/types/release_type_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe GitlabSchema.types['Release'] do + it { expect(described_class).to require_graphql_authorizations(:read_release) } + + it 'has the expected fields' do + expected_fields = %w[ + tag_name tag_path + description description_html + name evidence_sha milestones author commit + created_at released_at + ] + + expect(described_class).to include_graphql_fields(*expected_fields) + end + + describe 'milestones field' do + subject { described_class.fields['milestones'] } + + it { is_expected.to have_graphql_type(Types::MilestoneType.connection_type) } + end + + describe 'author field' do + subject { described_class.fields['author'] } + + it { is_expected.to have_graphql_type(Types::UserType) } + end + + describe 'commit field' do + subject { described_class.fields['commit'] } + + it { is_expected.to have_graphql_type(Types::CommitType) } + it { is_expected.to require_graphql_authorizations(:reporter_access) } + end +end diff --git a/spec/lib/gitlab/ci/reports/accessibility_reports_comparer_spec.rb b/spec/lib/gitlab/ci/reports/accessibility_reports_comparer_spec.rb new file mode 100644 index 00000000000..31a330f46b1 --- /dev/null +++ b/spec/lib/gitlab/ci/reports/accessibility_reports_comparer_spec.rb @@ -0,0 +1,270 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Ci::Reports::AccessibilityReportsComparer do + let(:comparer) { described_class.new(base_reports, head_reports) } + let(:base_reports) { Gitlab::Ci::Reports::AccessibilityReports.new } + let(:head_reports) { Gitlab::Ci::Reports::AccessibilityReports.new } + let(:url) { "https://gitlab.com" } + let(:single_error) do + [ + { + "code" => "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent", + "type" => "error", + "typeCode" => 1, + "message" => "Anchor element found with a valid href attribute, but no link content has been supplied.", + "context" => %{<a href="/" class="navbar-brand animated"><svg height="36" viewBox="0 0 1...</a>}, + "selector" => "#main-nav > div:nth-child(1) > a", + "runner" => "htmlcs", + "runnerExtras" => {} + } + ] + end + let(:different_error) do + [ + { + "code" => "WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail", + "type" => "error", + "typeCode" => 1, + "message" => "This element has insufficient contrast at this conformance level.", + "context" => %{<a href="/stages-devops-lifecycle/" class="main-nav-link">Product</a>}, + "selector" => "#main-nav > div:nth-child(2) > ul > li:nth-child(1) > a", + "runner" => "htmlcs", + "runnerExtras" => {} + } + ] + end + + describe '#status' do + subject { comparer.status } + + context 'when head report has an error' do + before do + head_reports.add_url(url, single_error) + end + + it 'returns status failed' do + expect(subject).to eq(described_class::STATUS_FAILED) + end + end + + context 'when head reports does not have errors' do + before do + head_reports.add_url(url, []) + end + + it 'returns status success' do + expect(subject).to eq(described_class::STATUS_SUCCESS) + end + end + end + + describe '#errors_count' do + subject { comparer.errors_count } + + context 'when head report has an error' do + before do + head_reports.add_url(url, single_error) + end + + it 'returns the number of new errors' do + expect(subject).to eq(1) + end + end + + context 'when head reports does not have an error' do + before do + head_reports.add_url(url, []) + end + + it 'returns the number new errors' do + expect(subject).to eq(0) + end + end + end + + describe '#resolved_count' do + subject { comparer.resolved_count } + + context 'when base reports has an error and head has a different error' do + before do + base_reports.add_url(url, single_error) + head_reports.add_url(url, different_error) + end + + it 'returns the resolved count' do + expect(subject).to eq(1) + end + end + + context 'when base reports has errors head has no errors' do + before do + base_reports.add_url(url, single_error) + head_reports.add_url(url, []) + end + + it 'returns the resolved count' do + expect(subject).to eq(1) + end + end + + context 'when base reports has errors and head has the same error' do + before do + base_reports.add_url(url, single_error) + head_reports.add_url(url, single_error) + end + + it 'returns zero' do + expect(subject).to eq(0) + end + end + + context 'when base reports does not have errors and head has errors' do + before do + head_reports.add_url(url, single_error) + end + + it 'returns the number of resolved errors' do + expect(subject).to eq(0) + end + end + end + + describe '#total_count' do + subject { comparer.total_count } + + context 'when base reports has an error' do + before do + base_reports.add_url(url, single_error) + end + + it 'returns the error count' do + expect(subject).to eq(1) + end + end + + context 'when head report has an error' do + before do + head_reports.add_url(url, single_error) + end + + it 'returns the error count' do + expect(subject).to eq(1) + end + end + + context 'when base report has errors and head report has errors' do + before do + base_reports.add_url(url, single_error) + head_reports.add_url(url, different_error) + end + + it 'returns the error count' do + expect(subject).to eq(2) + end + end + end + + describe '#existing_errors' do + subject { comparer.existing_errors } + + context 'when base report has errors and head has a different error' do + before do + base_reports.add_url(url, single_error) + head_reports.add_url(url, different_error) + end + + it 'returns the existing errors' do + expect(subject.size).to eq(1) + expect(subject.first["code"]).to eq("WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent") + end + end + + context 'when base report does not have errors and head has errors' do + before do + base_reports.add_url(url, []) + head_reports.add_url(url, single_error) + end + + it 'returns an empty array' do + expect(subject).to be_empty + end + end + end + + describe '#new_errors' do + subject { comparer.new_errors } + + context 'when base reports has errors and head has more errors' do + before do + base_reports.add_url(url, single_error) + head_reports.add_url(url, single_error + different_error) + end + + it 'returns new errors between base and head reports' do + expect(subject.size).to eq(1) + expect(subject.first["code"]).to eq("WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail") + end + end + + context 'when base reports has an error and head has no errors' do + before do + base_reports.add_url(url, single_error) + head_reports.add_url(url, []) + end + + it 'returns an empty array' do + expect(subject).to be_empty + end + end + + context 'when base reports does not have errors and head has errors' do + before do + head_reports.add_url(url, single_error) + end + + it 'returns the new error' do + expect(subject.size).to eq(1) + expect(subject.first["code"]).to eq("WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent") + end + end + end + + describe '#resolved_errors' do + subject { comparer.resolved_errors } + + context 'when base report has errors and head has more errors' do + before do + base_reports.add_url(url, single_error) + head_reports.add_url(url, single_error + different_error) + end + + it 'returns an empty array' do + expect(subject).to be_empty + end + end + + context 'when base reports has errors and head has a different error' do + before do + base_reports.add_url(url, single_error) + head_reports.add_url(url, different_error) + end + + it 'returns the resolved errors' do + expect(subject.size).to eq(1) + expect(subject.first["code"]).to eq("WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent") + end + end + + context 'when base reports does not have errors and head has errors' do + before do + head_reports.add_url(url, single_error) + end + + it 'returns an empty array' do + expect(subject).to be_empty + end + end + end +end diff --git a/spec/lib/gitlab/ci/reports/accessibility_reports_spec.rb b/spec/lib/gitlab/ci/reports/accessibility_reports_spec.rb index e7771ed15a4..0dc13b464b1 100644 --- a/spec/lib/gitlab/ci/reports/accessibility_reports_spec.rb +++ b/spec/lib/gitlab/ci/reports/accessibility_reports_spec.rb @@ -12,7 +12,7 @@ describe Gitlab::Ci::Reports::AccessibilityReports do "type": "error", "typeCode": 1, "message": "Anchor element found with a valid href attribute, but no link content has been supplied.", - "context": "<a href=\"/customers/worldline\">\n<svg viewBox=\"0 0 509 89\" xmln...</a>", + "context": %{<a href="/customers/worldline"><svg viewBox="0 0 509 89" xmln...</a>}, "selector": "html > body > div:nth-child(9) > div:nth-child(2) > a:nth-child(17)", "runner": "htmlcs", "runnerExtras": {} @@ -22,7 +22,7 @@ describe Gitlab::Ci::Reports::AccessibilityReports do "type": "error", "typeCode": 1, "message": "Anchor element found with a valid href attribute, but no link content has been supplied.", - "context": "<a href=\"/customers/equinix\">\n<svg xmlns=\"http://www.w3.org/...</a>", + "context": %{<a href="/customers/equinix"><svg xmlns="http://www.w3.org/...</a>}, "selector": "html > body > div:nth-child(9) > div:nth-child(2) > a:nth-child(18)", "runner": "htmlcs", "runnerExtras": {} @@ -199,4 +199,34 @@ describe Gitlab::Ci::Reports::AccessibilityReports do end end end + + describe '#all_errors' do + subject { accessibility_report.all_errors } + + context 'when data has errors' do + before do + accessibility_report.add_url(url, data) + end + + it 'returns all errors' do + expect(subject.size).to eq(2) + end + end + + context 'when data has no errors' do + before do + accessibility_report.add_url(url, []) + end + + it 'returns an empty array' do + expect(subject).to eq([]) + end + end + + context 'when accessibility report has no data' do + it 'returns an empty array' do + expect(subject).to eq([]) + end + end + end end |