diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-11 15:10:20 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-11 15:10:20 +0300 |
commit | c33a9adb709ffb40f816e66eb0c98cc750d6cd43 (patch) | |
tree | 1a5b3e103d8d9677dc9a3271cd6093454c898bd8 /spec | |
parent | 7fa274753de913596db0d3eff5c7a3896c6fdd0a (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
8 files changed, 179 insertions, 16 deletions
diff --git a/spec/features/admin/users/users_spec.rb b/spec/features/admin/users/users_spec.rb index e38376b0741..36907d4aa60 100644 --- a/spec/features/admin/users/users_spec.rb +++ b/spec/features/admin/users/users_spec.rb @@ -547,6 +547,32 @@ RSpec.describe 'Admin::Users' do end end + # TODO: Move to main GET /admin/users block once feature flag is removed. Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/290737 + context 'with vue_admin_users feature flag enabled', :js do + before do + stub_feature_flags(vue_admin_users: true) + end + + describe 'GET /admin/users' do + context 'user group count', :js do + before do + group = create(:group) + group.add_developer(current_user) + project = create(:project, group: create(:group)) + project.add_reporter(current_user) + end + + it 'displays count of the users authorized groups' do + visit admin_users_path + + wait_for_requests + + expect(page.find("[data-testid='user-group-count-#{current_user.id}']").text).to eq("2") + end + end + end + end + def click_user_dropdown_toggle(user_id) page.within("[data-testid='user-actions-#{user_id}']") do find("[data-testid='dropdown-toggle']").click diff --git a/spec/features/projects/new_project_from_template_spec.rb b/spec/features/projects/new_project_from_template_spec.rb new file mode 100644 index 00000000000..1c8647d859a --- /dev/null +++ b/spec/features/projects/new_project_from_template_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'New project from template', :js do + let(:user) { create(:user) } + + before do + sign_in(user) + + visit new_project_path + end + + context 'create from template' do + before do + page.find('a[href="#create_from_template"]').click + wait_for_requests + end + + it 'shows template tabs' do + page.within('#create-from-template-pane') do + expect(page).to have_link('Built-in', href: '#built-in') + end + end + end +end diff --git a/spec/frontend/admin/users/components/users_table_spec.js b/spec/frontend/admin/users/components/users_table_spec.js index 424b0deebd3..708c9e1979e 100644 --- a/spec/frontend/admin/users/components/users_table_spec.js +++ b/spec/frontend/admin/users/components/users_table_spec.js @@ -1,16 +1,36 @@ -import { GlTable } from '@gitlab/ui'; -import { mount } from '@vue/test-utils'; +import { GlTable, GlSkeletonLoader } from '@gitlab/ui'; +import { createLocalVue } from '@vue/test-utils'; +import VueApollo from 'vue-apollo'; + +import createMockApollo from 'helpers/mock_apollo_helper'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; import AdminUserActions from '~/admin/users/components/user_actions.vue'; import AdminUserAvatar from '~/admin/users/components/user_avatar.vue'; import AdminUsersTable from '~/admin/users/components/users_table.vue'; +import getUsersGroupCountsQuery from '~/admin/users/graphql/queries/get_users_group_counts.query.graphql'; +import createFlash from '~/flash'; import AdminUserDate from '~/vue_shared/components/user_date.vue'; -import { users, paths } from '../mock_data'; +import { users, paths, createGroupCountResponse } from '../mock_data'; + +jest.mock('~/flash'); + +const localVue = createLocalVue(); +localVue.use(VueApollo); describe('AdminUsersTable component', () => { let wrapper; + const user = users[0]; + const createFetchGroupCount = (data) => + jest.fn().mockResolvedValue(createGroupCountResponse(data)); + const fetchGroupCountsLoading = jest.fn().mockResolvedValue(new Promise(() => {})); + const fetchGroupCountsError = jest.fn().mockRejectedValue(new Error('Network error')); + const fetchGroupCountsResponse = createFetchGroupCount([{ id: user.id, groupCount: 5 }]); + + const findUserGroupCount = (id) => wrapper.findByTestId(`user-group-count-${id}`); + const findUserGroupCountLoader = (id) => findUserGroupCount(id).find(GlSkeletonLoader); const getCellByLabel = (trIdx, label) => { return wrapper .find(GlTable) @@ -20,8 +40,16 @@ describe('AdminUsersTable component', () => { .find(`[data-label="${label}"][role="cell"]`); }; - const initComponent = (props = {}) => { - wrapper = mount(AdminUsersTable, { + function createMockApolloProvider(resolverMock) { + const requestHandlers = [[getUsersGroupCountsQuery, resolverMock]]; + + return createMockApollo(requestHandlers); + } + + const initComponent = (props = {}, resolverMock = fetchGroupCountsResponse) => { + wrapper = mountExtended(AdminUsersTable, { + localVue, + apolloProvider: createMockApolloProvider(resolverMock), propsData: { users, paths, @@ -36,8 +64,6 @@ describe('AdminUsersTable component', () => { }); describe('when there are users', () => { - const user = users[0]; - beforeEach(() => { initComponent(); }); @@ -69,4 +95,51 @@ describe('AdminUsersTable component', () => { expect(wrapper.text()).toContain('No users found'); }); }); + + describe('group counts', () => { + describe('when fetching the data', () => { + beforeEach(() => { + initComponent({}, fetchGroupCountsLoading); + }); + + it('renders a loader for each user', () => { + expect(findUserGroupCountLoader(user.id).exists()).toBe(true); + }); + }); + + describe('when the data has been fetched', () => { + beforeEach(() => { + initComponent(); + }); + + it("renders the user's group count", () => { + expect(findUserGroupCount(user.id).text()).toBe('5'); + }); + + describe("and a user's group count is null", () => { + beforeEach(() => { + initComponent({}, createFetchGroupCount([{ id: user.id, groupCount: null }])); + }); + + it("renders the user's group count as 0", () => { + expect(findUserGroupCount(user.id).text()).toBe('0'); + }); + }); + }); + + describe('when there is an error while fetching the data', () => { + beforeEach(() => { + initComponent({}, fetchGroupCountsError); + }); + + it('creates a flash message and captures the error', () => { + expect(createFlash).toHaveBeenCalledTimes(1); + expect(createFlash).toHaveBeenCalledWith({ + message: 'Could not load user group counts. Please refresh the page to try again.', + captureError: true, + error: expect.any(Error), + }); + }); + }); + }); }); diff --git a/spec/frontend/admin/users/mock_data.js b/spec/frontend/admin/users/mock_data.js index c3918ef5173..4689ab36773 100644 --- a/spec/frontend/admin/users/mock_data.js +++ b/spec/frontend/admin/users/mock_data.js @@ -10,7 +10,7 @@ export const users = [ 'https://secure.gravatar.com/avatar/054f062d8b1a42b123f17e13a173cda8?s=80\\u0026d=identicon', badges: [ { text: 'Admin', variant: 'success' }, - { text: "It's you!", variant: null }, + { text: "It's you!", variant: 'muted' }, ], projectsCount: 0, actions: [], @@ -31,3 +31,16 @@ export const paths = { deleteWithContributions: '/admin/users/id', adminUser: '/admin/users/id', }; + +export const createGroupCountResponse = (groupCounts) => ({ + data: { + users: { + nodes: groupCounts.map(({ id, groupCount }) => ({ + id: `gid://gitlab/User/${id}`, + groupCount, + __typename: 'UserCore', + })), + __typename: 'UserCoreConnection', + }, + }, +}); diff --git a/spec/lib/gitlab/conan_token_spec.rb b/spec/lib/gitlab/conan_token_spec.rb index 00683cf6e47..b6180f69044 100644 --- a/spec/lib/gitlab/conan_token_spec.rb +++ b/spec/lib/gitlab/conan_token_spec.rb @@ -20,7 +20,7 @@ RSpec.describe Gitlab::ConanToken do JSONWebToken::HMACToken.new(jwt_secret).tap do |jwt| jwt['access_token'] = access_token_id jwt['user_id'] = user_id || user_id - jwt.expire_time = expire_time || jwt.issued_at + 1.hour + jwt.expire_time = expire_time || jwt.issued_at + ::Gitlab::ConanToken::CONAN_TOKEN_EXPIRE_TIME end end @@ -75,7 +75,7 @@ RSpec.describe Gitlab::ConanToken do it 'returns nil for expired JWT' do jwt = build_jwt(access_token_id: 123, user_id: 456, - expire_time: Time.zone.now - 2.hours) + expire_time: Time.zone.now - (::Gitlab::ConanToken::CONAN_TOKEN_EXPIRE_TIME + 1.hour)) expect(described_class.decode(jwt.encoded)).to be_nil end diff --git a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb index a94fd6acd32..41a6c06f9c9 100644 --- a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb +++ b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb @@ -20,15 +20,34 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do end describe '.default_settings_hash' do - it 'returns empty defaults' do + it 'returns defaults for all keys' do settings = described_class.default_settings_hash - expect(settings['enabled']).to be_falsey + expect(settings['enabled']).to be_truthy expect(settings['report_only']).to be_falsey - described_class::DIRECTIVES.each do |directive| - expect(settings['directives'].has_key?(directive)).to be_truthy - expect(settings['directives'][directive]).to be_nil + directives = settings['directives'] + directive_names = (described_class::DIRECTIVES - ['report_uri']) + directive_names.each do |directive| + expect(directives.has_key?(directive)).to be_truthy + expect(directives[directive]).to be_truthy + end + + expect(directives.has_key?('report_uri')).to be_truthy + expect(directives['report_uri']).to be_nil + end + + context 'when GITLAB_CDN_HOST is set' do + before do + stub_env('GITLAB_CDN_HOST', 'https://example.com') + end + + it 'adds GITLAB_CDN_HOST to CSP' do + settings = described_class.default_settings_hash + directives = settings['directives'] + + expect(directives['script_src']).to eq("'strict-dynamic' 'self' 'unsafe-inline' 'unsafe-eval' https://www.recaptcha.net https://apis.google.com https://example.com") + expect(directives['style_src']).to eq("'self' 'unsafe-inline' https://example.com") end end end diff --git a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb index 1afe8eafa5f..c938c6432fe 100644 --- a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb @@ -106,7 +106,7 @@ RSpec.shared_examples 'conan authenticate endpoint' do expect(payload['user_id']).to eq(personal_access_token.user_id) duration = payload['exp'] - payload['iat'] - expect(duration).to eq(1.hour) + expect(duration).to eq(::Gitlab::ConanToken::CONAN_TOKEN_EXPIRE_TIME) end end end diff --git a/spec/views/layouts/_head.html.haml_spec.rb b/spec/views/layouts/_head.html.haml_spec.rb index 6752bdc8337..ef0bd97cbcf 100644 --- a/spec/views/layouts/_head.html.haml_spec.rb +++ b/spec/views/layouts/_head.html.haml_spec.rb @@ -62,6 +62,12 @@ RSpec.describe 'layouts/_head' do expect(rendered).to match('<link rel="stylesheet" media="print" href="/stylesheets/highlight/themes/solarised-light.css" />') end + it 'preloads Monaco' do + render + + expect(rendered).to match('<link rel="preload" href="/assets/webpack/monaco.chunk.js" as="script" type="text/javascript">') + end + context 'when an asset_host is set and snowplow url is set' do let(:asset_host) { 'http://test.host' } let(:snowplow_collector_hostname) { 'www.snow.plow' } |