Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-03-09 00:07:52 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-09 00:07:52 +0300
commit6cb5b3a92d526e8b675aba2d1455e7e00b8656f5 (patch)
tree74533f94c28cab59705346299132cd362bbc6a99 /spec
parent9885b7e33ece32ac3bfbf077bb2dc53c459dbc0e (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/webauthn_spec.rb245
-rw-r--r--spec/frontend/authentication/webauthn/components/registration_spec.js5
-rw-r--r--spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js4
-rw-r--r--spec/frontend/commit/components/commit_box_pipeline_status_spec.js4
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js4
-rw-r--r--spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js8
-rw-r--r--spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js6
-rw-r--r--spec/frontend/sidebar/components/crm_contacts/crm_contacts_spec.js4
-rw-r--r--spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js6
-rw-r--r--spec/frontend/sidebar/components/incidents/sidebar_escalation_status_spec.js4
-rw-r--r--spec/frontend/sidebar/components/labels/labels_select_vue/store/actions_spec.js8
-rw-r--r--spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view_spec.js4
-rw-r--r--spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_labels_view_spec.js4
-rw-r--r--spec/frontend/sidebar/components/labels/labels_select_widget/labels_select_root_spec.js6
-rw-r--r--spec/frontend/sidebar/components/lock/edit_form_buttons_spec.js8
-rw-r--r--spec/frontend/sidebar/components/move/move_issue_button_spec.js6
-rw-r--r--spec/frontend/sidebar/components/move/move_issues_button_spec.js20
-rw-r--r--spec/frontend/sidebar/components/severity/sidebar_severity_spec.js4
-rw-r--r--spec/frontend/sidebar/components/subscriptions/sidebar_subscriptions_widget_spec.js6
-rw-r--r--spec/frontend/sidebar/components/time_tracking/report_spec.js4
-rw-r--r--spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js6
-rw-r--r--spec/frontend/sidebar/sidebar_mediator_spec.js2
-rw-r--r--spec/models/ci/pipeline_schedule_spec.rb17
-rw-r--r--spec/support/helpers/features/two_factor_helpers.rb31
24 files changed, 285 insertions, 131 deletions
diff --git a/spec/features/webauthn_spec.rb b/spec/features/webauthn_spec.rb
index 093609e5610..fbbc746c0b0 100644
--- a/spec/features/webauthn_spec.rb
+++ b/spec/features/webauthn_spec.rb
@@ -10,6 +10,113 @@ RSpec.describe 'Using WebAuthn Devices for Authentication', :js, feature_categor
WebAuthn.configuration.origin = app_id
end
+ context 'when the webauth_without_totp feature flag is enabled' do
+ # Some of the shared tests don't apply. After removing U2F support and the `webauthn_without_totp` feature flag, refactor the shared tests.
+ # TODO: it_behaves_like 'hardware device for 2fa', 'WebAuthn'
+
+ describe 'registration' do
+ let(:user) { create(:user) }
+
+ before do
+ gitlab_sign_in(user)
+ end
+
+ it 'shows an error when using a wrong password' do
+ visit profile_account_path
+
+ # First device
+ enable_two_factor_authentication
+ webauthn_device_registration(password: 'fake')
+ expect(page).to have_content(_('You must provide a valid current password.'))
+ end
+
+ it 'allows registering more than one device' do
+ visit profile_account_path
+
+ # First device
+ enable_two_factor_authentication
+ first_device = webauthn_device_registration(password: user.password)
+ expect(page).to have_content('Your WebAuthn device was registered!')
+ copy_recovery_codes
+ manage_two_factor_authentication
+
+ # Second device
+ second_device = webauthn_device_registration(name: 'My other device', password: user.password)
+ expect(page).to have_content('Your WebAuthn device was registered!')
+
+ expect(page).to have_content(first_device.name)
+ expect(page).to have_content(second_device.name)
+ expect(WebauthnRegistration.count).to eq(2)
+ end
+
+ it 'allows the same device to be registered for multiple users' do
+ # First user
+ visit profile_account_path
+ enable_two_factor_authentication
+ webauthn_device = webauthn_device_registration(password: user.password)
+ expect(page).to have_content('Your WebAuthn device was registered!')
+ gitlab_sign_out
+
+ # Second user
+ user = gitlab_sign_in(:user)
+ visit profile_account_path
+ enable_two_factor_authentication
+ webauthn_device_registration(webauthn_device: webauthn_device, name: 'My other device', password: user.password)
+ expect(page).to have_content('Your WebAuthn device was registered!')
+
+ expect(WebauthnRegistration.count).to eq(2)
+ end
+
+ context 'when there are form errors' do
+ let(:mock_register_js) do
+ <<~JS
+ const mockResponse = {
+ type: 'public-key',
+ id: '',
+ rawId: '',
+ response: {
+ clientDataJSON: '',
+ attestationObject: '',
+ },
+ getClientExtensionResults: () => {},
+ };
+ navigator.credentials.create = () => Promise.resolve(mockResponse);
+ JS
+ end
+
+ it "doesn't register the device if there are errors" do
+ visit profile_account_path
+ enable_two_factor_authentication
+
+ # Have the "webauthn device" respond with bad data
+ page.execute_script(mock_register_js)
+ click_on _('Set up new device')
+ webauthn_fill_form_and_submit(password: user.password)
+ expect(page).to have_content(_('Your WebAuthn device did not send a valid JSON response.'))
+
+ expect(WebauthnRegistration.count).to eq(0)
+ end
+
+ it 'allows retrying registration' do
+ visit profile_account_path
+ enable_two_factor_authentication
+
+ # Failed registration
+ page.execute_script(mock_register_js)
+ click_on _('Set up new device')
+ webauthn_fill_form_and_submit(password: user.password)
+ expect(page).to have_content(_('Your WebAuthn device did not send a valid JSON response.'))
+
+ # Successful registration
+ webauthn_device_registration(password: user.password)
+
+ expect(page).to have_content('Your WebAuthn device was registered!')
+ expect(WebauthnRegistration.count).to eq(1)
+ end
+ end
+ end
+ end
+
context 'when the webauth_without_totp feature flag is disabled' do
before do
stub_feature_flags(webauthn_without_totp: false)
@@ -114,99 +221,99 @@ RSpec.describe 'Using WebAuthn Devices for Authentication', :js, feature_categor
end
end
end
+ end
- describe 'authentication' do
- let(:otp_required_for_login) { true }
- let(:user) { create(:user, webauthn_xid: WebAuthn.generate_user_id, otp_required_for_login: otp_required_for_login) }
- let!(:webauthn_device) do
- add_webauthn_device(app_id, user)
- end
+ describe 'authentication' do
+ let(:otp_required_for_login) { true }
+ let(:user) { create(:user, webauthn_xid: WebAuthn.generate_user_id, otp_required_for_login: otp_required_for_login) }
+ let!(:webauthn_device) do
+ add_webauthn_device(app_id, user)
+ end
- describe 'when 2FA via OTP is disabled' do
- let(:otp_required_for_login) { false }
+ describe 'when 2FA via OTP is disabled' do
+ let(:otp_required_for_login) { false }
- it 'allows logging in with the WebAuthn device' do
- gitlab_sign_in(user)
+ it 'allows logging in with the WebAuthn device' do
+ gitlab_sign_in(user)
- webauthn_device.respond_to_webauthn_authentication
+ webauthn_device.respond_to_webauthn_authentication
- expect(page).to have_css('.sign-out-link', visible: false)
- end
+ expect(page).to have_css('.sign-out-link', visible: false)
end
+ end
- describe 'when 2FA via OTP is enabled' do
- it 'allows logging in with the WebAuthn device' do
- gitlab_sign_in(user)
+ describe 'when 2FA via OTP is enabled' do
+ it 'allows logging in with the WebAuthn device' do
+ gitlab_sign_in(user)
- webauthn_device.respond_to_webauthn_authentication
+ webauthn_device.respond_to_webauthn_authentication
- expect(page).to have_css('.sign-out-link', visible: false)
- end
+ expect(page).to have_css('.sign-out-link', visible: false)
end
+ end
- describe 'when a given WebAuthn device has already been registered by another user' do
- describe 'but not the current user' do
- let(:other_user) { create(:user, webauthn_xid: WebAuthn.generate_user_id, otp_required_for_login: otp_required_for_login) }
+ describe 'when a given WebAuthn device has already been registered by another user' do
+ describe 'but not the current user' do
+ let(:other_user) { create(:user, webauthn_xid: WebAuthn.generate_user_id, otp_required_for_login: otp_required_for_login) }
- it 'does not allow logging in with that particular device' do
- # Register other user with a different WebAuthn device
- other_device = add_webauthn_device(app_id, other_user)
+ it 'does not allow logging in with that particular device' do
+ # Register other user with a different WebAuthn device
+ other_device = add_webauthn_device(app_id, other_user)
- # Try authenticating user with the old WebAuthn device
- gitlab_sign_in(user)
- other_device.respond_to_webauthn_authentication
- expect(page).to have_content('Authentication via WebAuthn device failed')
- end
+ # Try authenticating user with the old WebAuthn device
+ gitlab_sign_in(user)
+ other_device.respond_to_webauthn_authentication
+ expect(page).to have_content('Authentication via WebAuthn device failed')
end
+ end
+
+ describe "and also the current user" do
+ # TODO Uncomment once WebAuthn::FakeClient supports passing credential options
+ # (especially allow_credentials, as this is needed to specify which credential the
+ # fake client should use. Currently, the first credential is always used).
+ # There is an issue open for this: https://github.com/cedarcode/webauthn-ruby/issues/259
+ it "allows logging in with that particular device" do
+ pending("support for passing credential options in FakeClient")
+ # Register current user with the same WebAuthn device
+ current_user = gitlab_sign_in(:user)
+ visit profile_account_path
+ manage_two_factor_authentication
+ register_webauthn_device(webauthn_device)
+ gitlab_sign_out
+
+ # Try authenticating user with the same WebAuthn device
+ gitlab_sign_in(current_user)
+ webauthn_device.respond_to_webauthn_authentication
- describe "and also the current user" do
- # TODO Uncomment once WebAuthn::FakeClient supports passing credential options
- # (especially allow_credentials, as this is needed to specify which credential the
- # fake client should use. Currently, the first credential is always used).
- # There is an issue open for this: https://github.com/cedarcode/webauthn-ruby/issues/259
- it "allows logging in with that particular device" do
- pending("support for passing credential options in FakeClient")
- # Register current user with the same WebAuthn device
- current_user = gitlab_sign_in(:user)
- visit profile_account_path
- manage_two_factor_authentication
- register_webauthn_device(webauthn_device)
- gitlab_sign_out
-
- # Try authenticating user with the same WebAuthn device
- gitlab_sign_in(current_user)
- webauthn_device.respond_to_webauthn_authentication
-
- expect(page).to have_css('.sign-out-link', visible: false)
- end
+ expect(page).to have_css('.sign-out-link', visible: false)
end
end
+ end
- describe 'when a given WebAuthn device has not been registered' do
- it 'does not allow logging in with that particular device' do
- unregistered_device = FakeWebauthnDevice.new(page, 'My device')
- gitlab_sign_in(user)
- unregistered_device.respond_to_webauthn_authentication
+ describe 'when a given WebAuthn device has not been registered' do
+ it 'does not allow logging in with that particular device' do
+ unregistered_device = FakeWebauthnDevice.new(page, 'My device')
+ gitlab_sign_in(user)
+ unregistered_device.respond_to_webauthn_authentication
- expect(page).to have_content('Authentication via WebAuthn device failed')
- end
+ expect(page).to have_content('Authentication via WebAuthn device failed')
end
+ end
- describe 'when more than one device has been registered by the same user' do
- it 'allows logging in with either device' do
- first_device = add_webauthn_device(app_id, user)
- second_device = add_webauthn_device(app_id, user)
+ describe 'when more than one device has been registered by the same user' do
+ it 'allows logging in with either device' do
+ first_device = add_webauthn_device(app_id, user)
+ second_device = add_webauthn_device(app_id, user)
- # Authenticate as both devices
- [first_device, second_device].each do |device|
- gitlab_sign_in(user)
- # register_webauthn_device(device)
- device.respond_to_webauthn_authentication
+ # Authenticate as both devices
+ [first_device, second_device].each do |device|
+ gitlab_sign_in(user)
+ # register_webauthn_device(device)
+ device.respond_to_webauthn_authentication
- expect(page).to have_css('.sign-out-link', visible: false)
+ expect(page).to have_css('.sign-out-link', visible: false)
- gitlab_sign_out
- end
+ gitlab_sign_out
end
end
end
diff --git a/spec/frontend/authentication/webauthn/components/registration_spec.js b/spec/frontend/authentication/webauthn/components/registration_spec.js
index 1dcf7de4bc7..1221626db7d 100644
--- a/spec/frontend/authentication/webauthn/components/registration_spec.js
+++ b/spec/frontend/authentication/webauthn/components/registration_spec.js
@@ -43,8 +43,9 @@ describe('Registration', () => {
describe(`when ${STATE_UNSUPPORTED} state`, () => {
it('shows an error if using unsecure scheme (HTTP)', () => {
+ // `supported` function returns false for HTTP because `navigator.credentials` is undefined.
+ WebAuthnUtils.supported.mockReturnValue(false);
WebAuthnUtils.isHTTPS.mockReturnValue(false);
- WebAuthnUtils.supported.mockReturnValue(true);
createComponent();
const alert = wrapper.findComponent(GlAlert);
@@ -53,8 +54,8 @@ describe('Registration', () => {
});
it('shows an error if using unsupported browser', () => {
- WebAuthnUtils.isHTTPS.mockReturnValue(true);
WebAuthnUtils.supported.mockReturnValue(false);
+ WebAuthnUtils.isHTTPS.mockReturnValue(true);
createComponent();
const alert = wrapper.findComponent(GlAlert);
diff --git a/spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js b/spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js
index debd10de118..c2a4e675e5e 100644
--- a/spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js
+++ b/spec/frontend/commit/commit_box_pipeline_mini_graph_spec.js
@@ -5,7 +5,7 @@ import { shallowMount } from '@vue/test-utils';
import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import CommitBoxPipelineMiniGraph from '~/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue';
import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
import { COMMIT_BOX_POLL_INTERVAL } from '~/projects/commit_box/info/constants';
@@ -20,7 +20,7 @@ import {
mockUpstreamQueryResponse,
} from './mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
Vue.use(VueApollo);
diff --git a/spec/frontend/commit/components/commit_box_pipeline_status_spec.js b/spec/frontend/commit/components/commit_box_pipeline_status_spec.js
index 8d455f8a3d7..8a46f8dedc1 100644
--- a/spec/frontend/commit/components/commit_box_pipeline_status_spec.js
+++ b/spec/frontend/commit/components/commit_box_pipeline_status_spec.js
@@ -4,7 +4,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import CommitBoxPipelineStatus from '~/projects/commit_box/info/components/commit_box_pipeline_status.vue';
import {
@@ -23,7 +23,7 @@ const mockProvide = {
Vue.use(VueApollo);
-jest.mock('~/flash');
+jest.mock('~/alert');
describe('Commit box pipeline status', () => {
let wrapper;
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
index 7d6647fa6fd..20792494d75 100644
--- a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
+++ b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
@@ -5,7 +5,7 @@ import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import { TYPE_MERGE_REQUEST } from '~/issues/constants';
import SidebarAssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue';
import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
@@ -17,7 +17,7 @@ import updateIssueAssigneesMutation from '~/sidebar/queries/update_issue_assigne
import UserSelect from '~/vue_shared/components/user_select/user_select.vue';
import { issuableQueryResponse, updateIssueAssigneesMutationResponse } from '../../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
const updateIssueAssigneesMutationSuccess = jest
.fn()
diff --git a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js
index b27f7c6b4e1..53640f668a4 100644
--- a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js
+++ b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js
@@ -2,11 +2,11 @@ import { GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import SidebarConfidentialityForm from '~/sidebar/components/confidential/sidebar_confidentiality_form.vue';
import { confidentialityQueries } from '~/sidebar/constants';
-jest.mock('~/flash');
+jest.mock('~/alert');
describe('Sidebar Confidentiality Form', () => {
let wrapper;
@@ -58,7 +58,7 @@ describe('Sidebar Confidentiality Form', () => {
expect(findConfidentialToggle().props('loading')).toBe(true);
});
- it('creates a flash if mutation is rejected', async () => {
+ it('creates an alert if mutation is rejected', async () => {
createComponent({ mutate: jest.fn().mockRejectedValue('Error!') });
findConfidentialToggle().vm.$emit('click', new MouseEvent('click'));
await waitForPromises();
@@ -68,7 +68,7 @@ describe('Sidebar Confidentiality Form', () => {
});
});
- it('creates a flash if mutation contains errors', async () => {
+ it('creates an alert if mutation contains errors', async () => {
createComponent({
mutate: jest.fn().mockResolvedValue({
data: { issuableSetConfidential: { errors: ['Houston, we have a problem!'] } },
diff --git a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
index e486a8e9ec7..a6b094ad6ec 100644
--- a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
+++ b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
@@ -4,7 +4,7 @@ import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import SidebarConfidentialityContent from '~/sidebar/components/confidential/sidebar_confidentiality_content.vue';
import SidebarConfidentialityForm from '~/sidebar/components/confidential/sidebar_confidentiality_form.vue';
import SidebarConfidentialityWidget, {
@@ -14,7 +14,7 @@ import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'
import issueConfidentialQuery from '~/sidebar/queries/issue_confidential.query.graphql';
import { issueConfidentialityResponse } from '../../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
Vue.use(VueApollo);
@@ -120,7 +120,7 @@ describe('Sidebar Confidentiality Widget', () => {
});
});
- it('displays a flash message when query is rejected', async () => {
+ it('displays an alert message when query is rejected', async () => {
createComponent({
confidentialQueryHandler: jest.fn().mockRejectedValue('Houston, we have a problem'),
});
diff --git a/spec/frontend/sidebar/components/crm_contacts/crm_contacts_spec.js b/spec/frontend/sidebar/components/crm_contacts/crm_contacts_spec.js
index ca43c219d92..6ed6d0276fa 100644
--- a/spec/frontend/sidebar/components/crm_contacts/crm_contacts_spec.js
+++ b/spec/frontend/sidebar/components/crm_contacts/crm_contacts_spec.js
@@ -3,7 +3,7 @@ import VueApollo from 'vue-apollo';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import CrmContacts from '~/sidebar/components/crm_contacts/crm_contacts.vue';
import getIssueCrmContactsQuery from '~/sidebar/queries/get_issue_crm_contacts.query.graphql';
import issueCrmContactsSubscription from '~/sidebar/queries/issue_crm_contacts.subscription.graphql';
@@ -13,7 +13,7 @@ import {
issueCrmContactsUpdateNullResponse,
} from '../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
describe('Issue crm contacts component', () => {
Vue.use(VueApollo);
diff --git a/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js b/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js
index 67413cffdda..e0bac8785e1 100644
--- a/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js
+++ b/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js
@@ -4,7 +4,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue';
import SidebarFormattedDate from '~/sidebar/components/date/sidebar_formatted_date.vue';
import SidebarInheritDate from '~/sidebar/components/date/sidebar_inherit_date.vue';
@@ -13,7 +13,7 @@ import epicStartDateQuery from '~/sidebar/queries/epic_start_date.query.graphql'
import issueDueDateQuery from '~/sidebar/queries/issue_due_date.query.graphql';
import { issuableDueDateResponse, issuableStartDateResponse } from '../../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
Vue.use(VueApollo);
@@ -159,7 +159,7 @@ describe('Sidebar date Widget', () => {
expect(wrapper.findComponent(SidebarInheritDate).exists()).toBe(false);
});
- it('displays a flash message when query is rejected', async () => {
+ it('displays an alert message when query is rejected', async () => {
createComponent({
dueDateQueryHandler: jest.fn().mockRejectedValue('Houston, we have a problem'),
});
diff --git a/spec/frontend/sidebar/components/incidents/sidebar_escalation_status_spec.js b/spec/frontend/sidebar/components/incidents/sidebar_escalation_status_spec.js
index 5e0e9f48926..00b57b4916e 100644
--- a/spec/frontend/sidebar/components/incidents/sidebar_escalation_status_spec.js
+++ b/spec/frontend/sidebar/components/incidents/sidebar_escalation_status_spec.js
@@ -18,11 +18,11 @@ import {
} from '~/sidebar/constants';
import waitForPromises from 'helpers/wait_for_promises';
import EscalationStatus from 'ee_else_ce/sidebar/components/incidents/escalation_status.vue';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import { logError } from '~/lib/logger';
jest.mock('~/lib/logger');
-jest.mock('~/flash');
+jest.mock('~/alert');
Vue.use(VueApollo);
diff --git a/spec/frontend/sidebar/components/labels/labels_select_vue/store/actions_spec.js b/spec/frontend/sidebar/components/labels/labels_select_vue/store/actions_spec.js
index 55651bccaa8..c27afb75375 100644
--- a/spec/frontend/sidebar/components/labels/labels_select_vue/store/actions_spec.js
+++ b/spec/frontend/sidebar/components/labels/labels_select_vue/store/actions_spec.js
@@ -1,14 +1,14 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import axios from '~/lib/utils/axios_utils';
import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
import * as actions from '~/sidebar/components/labels/labels_select_vue/store/actions';
import * as types from '~/sidebar/components/labels/labels_select_vue/store/mutation_types';
import defaultState from '~/sidebar/components/labels/labels_select_vue/store/state';
-jest.mock('~/flash');
+jest.mock('~/alert');
describe('LabelsSelect Actions', () => {
let state;
@@ -100,7 +100,7 @@ describe('LabelsSelect Actions', () => {
);
});
- it('shows flash error', () => {
+ it('shows alert error', () => {
actions.receiveLabelsFailure({ commit: () => {} });
expect(createAlert).toHaveBeenCalledWith({ message: 'Error fetching labels.' });
@@ -184,7 +184,7 @@ describe('LabelsSelect Actions', () => {
);
});
- it('shows flash error', () => {
+ it('shows alert error', () => {
actions.receiveCreateLabelFailure({ commit: () => {} });
expect(createAlert).toHaveBeenCalledWith({ message: 'Error creating label.' });
diff --git a/spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view_spec.js b/spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view_spec.js
index 79b164b0ea7..0615ca1453f 100644
--- a/spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view_spec.js
+++ b/spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view_spec.js
@@ -4,7 +4,7 @@ import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import { workspaceLabelsQueries } from '~/sidebar/constants';
import DropdownContentsCreateView from '~/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view.vue';
import createLabelMutation from '~/sidebar/components/labels/labels_select_widget/graphql/create_label.mutation.graphql';
@@ -15,7 +15,7 @@ import {
workspaceLabelsQueryResponse,
} from './mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
const colors = Object.keys(mockSuggestedColors);
diff --git a/spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_labels_view_spec.js b/spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_labels_view_spec.js
index 913badccbe4..5c49b66216c 100644
--- a/spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_labels_view_spec.js
+++ b/spec/frontend/sidebar/components/labels/labels_select_widget/dropdown_contents_labels_view_spec.js
@@ -9,7 +9,7 @@ import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { DropdownVariant } from '~/sidebar/components/labels/labels_select_widget/constants';
import DropdownContentsLabelsView from '~/sidebar/components/labels/labels_select_widget/dropdown_contents_labels_view.vue';
@@ -17,7 +17,7 @@ import projectLabelsQuery from '~/sidebar/components/labels/labels_select_widget
import LabelItem from '~/sidebar/components/labels/labels_select_widget/label_item.vue';
import { mockConfig, workspaceLabelsQueryResponse } from './mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
Vue.use(VueApollo);
diff --git a/spec/frontend/sidebar/components/labels/labels_select_widget/labels_select_root_spec.js b/spec/frontend/sidebar/components/labels/labels_select_widget/labels_select_root_spec.js
index ae7c4068069..4dcab4b1b5b 100644
--- a/spec/frontend/sidebar/components/labels/labels_select_widget/labels_select_root_spec.js
+++ b/spec/frontend/sidebar/components/labels/labels_select_widget/labels_select_root_spec.js
@@ -3,7 +3,7 @@ import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import { TYPE_EPIC, TYPE_ISSUE, TYPE_MERGE_REQUEST, TYPE_TEST_CASE } from '~/issues/constants';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import DropdownContents from '~/sidebar/components/labels/labels_select_widget/dropdown_contents.vue';
@@ -25,7 +25,7 @@ import {
mockRegularLabel,
} from './mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
Vue.use(VueApollo);
@@ -150,7 +150,7 @@ describe('LabelsSelectRoot', () => {
});
});
- it('creates flash with error message when query is rejected', async () => {
+ it('creates alert with error message when query is rejected', async () => {
createComponent({ queryHandler: errorQueryHandler });
await waitForPromises();
expect(createAlert).toHaveBeenCalledWith({ message: 'Error fetching labels.' });
diff --git a/spec/frontend/sidebar/components/lock/edit_form_buttons_spec.js b/spec/frontend/sidebar/components/lock/edit_form_buttons_spec.js
index 2abb0c24d7d..9151c5e60ab 100644
--- a/spec/frontend/sidebar/components/lock/edit_form_buttons_spec.js
+++ b/spec/frontend/sidebar/components/lock/edit_form_buttons_spec.js
@@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import { createStore as createMrStore } from '~/mr_notes/stores';
import createStore from '~/notes/stores';
import EditFormButtons from '~/sidebar/components/lock/edit_form_buttons.vue';
@@ -8,7 +8,7 @@ import eventHub from '~/sidebar/event_hub';
import { ISSUABLE_TYPE_ISSUE, ISSUABLE_TYPE_MR } from './constants';
jest.mock('~/sidebar/event_hub', () => ({ $emit: jest.fn() }));
-jest.mock('~/flash');
+jest.mock('~/alert');
describe('EditFormButtons', () => {
let wrapper;
@@ -128,7 +128,7 @@ describe('EditFormButtons', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('closeLockForm');
});
- it('does not flash an error message', () => {
+ it('does not alert an error message', () => {
expect(createAlert).not.toHaveBeenCalled();
});
});
@@ -161,7 +161,7 @@ describe('EditFormButtons', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('closeLockForm');
});
- it('calls flash with the correct message', () => {
+ it('calls alert with the correct message', () => {
expect(createAlert).toHaveBeenCalledWith({
message: `Something went wrong trying to change the locked state of this ${issuableDisplayName}`,
});
diff --git a/spec/frontend/sidebar/components/move/move_issue_button_spec.js b/spec/frontend/sidebar/components/move/move_issue_button_spec.js
index acd6b23c1f5..eb5e23c6047 100644
--- a/spec/frontend/sidebar/components/move/move_issue_button_spec.js
+++ b/spec/frontend/sidebar/components/move/move_issue_button_spec.js
@@ -4,14 +4,14 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { visitUrl } from '~/lib/utils/url_utility';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import ProjectSelect from '~/sidebar/components/move/issuable_move_dropdown.vue';
import MoveIssueButton from '~/sidebar/components/move/move_issue_button.vue';
import moveIssueMutation from '~/sidebar/queries/move_issue.mutation.graphql';
Vue.use(VueApollo);
-jest.mock('~/flash');
+jest.mock('~/alert');
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn(),
}));
@@ -118,7 +118,7 @@ describe('MoveIssueButton', () => {
expect(findProjectSelect().props('moveInProgress')).toBe(false);
});
- it('creates a flash and logs errors when a mutation returns errors', async () => {
+ it('creates an alert and logs errors when a mutation returns errors', async () => {
createComponent(resolvedMutationWithErrorsMock);
emitProjectSelectEvent();
diff --git a/spec/frontend/sidebar/components/move/move_issues_button_spec.js b/spec/frontend/sidebar/components/move/move_issues_button_spec.js
index c65bad642a0..a5d46293c38 100644
--- a/spec/frontend/sidebar/components/move/move_issues_button_spec.js
+++ b/spec/frontend/sidebar/components/move/move_issues_button_spec.js
@@ -6,7 +6,7 @@ import { GlAlert } from '@gitlab/ui';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import { logError } from '~/lib/logger';
import IssuableMoveDropdown from '~/sidebar/components/move/issuable_move_dropdown.vue';
import issuableEventHub from '~/issues/list/eventhub';
@@ -22,7 +22,7 @@ import {
WORK_ITEM_TYPE_ENUM_TEST_CASE,
} from '~/work_items/constants';
-jest.mock('~/flash');
+jest.mock('~/alert');
jest.mock('~/lib/logger');
useMockLocationHelper();
@@ -389,7 +389,7 @@ describe('MoveIssuesButton', () => {
});
describe('shows errors', () => {
- it('does not create flashes or logs errors when no issue is selected', async () => {
+ it('does not create alerts or logs errors when no issue is selected', async () => {
createComponent();
emitMoveIssuablesEvent();
@@ -399,7 +399,7 @@ describe('MoveIssuesButton', () => {
expect(createAlert).not.toHaveBeenCalled();
});
- it('does not create flashes or logs errors when only tasks are selected', async () => {
+ it('does not create alerts or logs errors when only tasks are selected', async () => {
createComponent({ selectedIssuables: selectedIssuesMocks.tasksOnly });
emitMoveIssuablesEvent();
@@ -409,7 +409,7 @@ describe('MoveIssuesButton', () => {
expect(createAlert).not.toHaveBeenCalled();
});
- it('does not create flashes or logs errors when only test cases are selected', async () => {
+ it('does not create alerts or logs errors when only test cases are selected', async () => {
createComponent({ selectedIssuables: selectedIssuesMocks.testCasesOnly });
emitMoveIssuablesEvent();
@@ -419,7 +419,7 @@ describe('MoveIssuesButton', () => {
expect(createAlert).not.toHaveBeenCalled();
});
- it('does not create flashes or logs errors when only tasks and test cases are selected', async () => {
+ it('does not create alerts or logs errors when only tasks and test cases are selected', async () => {
createComponent({ selectedIssuables: selectedIssuesMocks.tasksAndTestCases });
emitMoveIssuablesEvent();
@@ -429,7 +429,7 @@ describe('MoveIssuesButton', () => {
expect(createAlert).not.toHaveBeenCalled();
});
- it('does not create flashes or logs errors when issues are moved without errors', async () => {
+ it('does not create alerts or logs errors when issues are moved without errors', async () => {
createComponent(
{ selectedIssuables: selectedIssuesMocks.issuesTasksAndTestCases },
resolvedMutationWithoutErrorsMock,
@@ -442,7 +442,7 @@ describe('MoveIssuesButton', () => {
expect(createAlert).not.toHaveBeenCalled();
});
- it('creates a flash and logs errors when a mutation returns errors', async () => {
+ it('creates an alert and logs errors when a mutation returns errors', async () => {
createComponent(
{ selectedIssuables: selectedIssuesMocks.issuesTasksAndTestCases },
resolvedMutationWithErrorsMock,
@@ -462,14 +462,14 @@ describe('MoveIssuesButton', () => {
`Error moving issue. Error message: ${mockMutationErrorMessage}`,
);
- // Only one flash is created even if multiple errors are reported
+ // Only one alert is created even if multiple errors are reported
expect(createAlert).toHaveBeenCalledTimes(1);
expect(createAlert).toHaveBeenCalledWith({
message: 'There was an error while moving the issues.',
});
});
- it('creates a flash but not logs errors when a mutation is rejected', async () => {
+ it('creates an alert but not logs errors when a mutation is rejected', async () => {
createComponent({ selectedIssuables: selectedIssuesMocks.issuesTasksAndTestCases });
emitMoveIssuablesEvent();
diff --git a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
index 7580dc7307b..9ffb0da3f68 100644
--- a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
+++ b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
@@ -2,14 +2,14 @@ import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlTooltip, GlSprintf } from
import { nextTick } from 'vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import { TYPE_INCIDENT } from '~/issues/constants';
import { INCIDENT_SEVERITY } from '~/sidebar/constants';
import updateIssuableSeverity from '~/sidebar/queries/update_issuable_severity.mutation.graphql';
import SeverityToken from '~/sidebar/components/severity/severity.vue';
import SidebarSeverityWidget from '~/sidebar/components/severity/sidebar_severity_widget.vue';
-jest.mock('~/flash');
+jest.mock('~/alert');
describe('SidebarSeverity', () => {
let wrapper;
diff --git a/spec/frontend/sidebar/components/subscriptions/sidebar_subscriptions_widget_spec.js b/spec/frontend/sidebar/components/subscriptions/sidebar_subscriptions_widget_spec.js
index c94f9918243..6247da3a7df 100644
--- a/spec/frontend/sidebar/components/subscriptions/sidebar_subscriptions_widget_spec.js
+++ b/spec/frontend/sidebar/components/subscriptions/sidebar_subscriptions_widget_spec.js
@@ -4,7 +4,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import SidebarSubscriptionWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue';
import issueSubscribedQuery from '~/sidebar/queries/issue_subscribed.query.graphql';
@@ -15,7 +15,7 @@ import {
mergeRequestSubscriptionMutationResponse,
} from '../../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
jest.mock('~/vue_shared/plugins/global_toast');
Vue.use(VueApollo);
@@ -138,7 +138,7 @@ describe('Sidebar Subscriptions Widget', () => {
});
});
- it('displays a flash message when query is rejected', async () => {
+ it('displays an alert message when query is rejected', async () => {
createComponent({
subscriptionsQueryHandler: jest.fn().mockRejectedValue('Houston, we have a problem'),
});
diff --git a/spec/frontend/sidebar/components/time_tracking/report_spec.js b/spec/frontend/sidebar/components/time_tracking/report_spec.js
index 0259aee48f0..f87889658b6 100644
--- a/spec/frontend/sidebar/components/time_tracking/report_spec.js
+++ b/spec/frontend/sidebar/components/time_tracking/report_spec.js
@@ -6,7 +6,7 @@ import VueApollo from 'vue-apollo';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import Report from '~/sidebar/components/time_tracking/report.vue';
import getIssueTimelogsQuery from '~/sidebar/queries/get_issue_timelogs.query.graphql';
import getMrTimelogsQuery from '~/sidebar/queries/get_mr_timelogs.query.graphql';
@@ -17,7 +17,7 @@ import {
timelogToRemoveId,
} from './mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
describe('Issuable Time Tracking Report', () => {
Vue.use(VueApollo);
diff --git a/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js b/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
index 5bfe3b59eb3..cea14c39a37 100644
--- a/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
+++ b/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
@@ -4,13 +4,13 @@ import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
+import { createAlert } from '~/alert';
import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue';
import epicTodoQuery from '~/sidebar/queries/epic_todo.query.graphql';
import TodoButton from '~/sidebar/components/todo_toggle/todo_button.vue';
import { todosResponse, noTodosResponse } from '../../mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
Vue.use(VueApollo);
@@ -77,7 +77,7 @@ describe('Sidebar Todo Widget', () => {
});
});
- it('displays a flash message when query is rejected', async () => {
+ it('displays an alert message when query is rejected', async () => {
createComponent({
todosQueryHandler: jest.fn().mockRejectedValue('Houston, we have a problem'),
});
diff --git a/spec/frontend/sidebar/sidebar_mediator_spec.js b/spec/frontend/sidebar/sidebar_mediator_spec.js
index 77b1ccb4f9a..f2003aee96e 100644
--- a/spec/frontend/sidebar/sidebar_mediator_spec.js
+++ b/spec/frontend/sidebar/sidebar_mediator_spec.js
@@ -7,7 +7,7 @@ import SidebarMediator from '~/sidebar/sidebar_mediator';
import SidebarStore from '~/sidebar/stores/sidebar_store';
import Mock from './mock_data';
-jest.mock('~/flash');
+jest.mock('~/alert');
jest.mock('~/vue_shared/plugins/global_toast');
jest.mock('~/commons/nav/user_merge_requests');
diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb
index 9b70f7c2839..c441be58edf 100644
--- a/spec/models/ci/pipeline_schedule_spec.rb
+++ b/spec/models/ci/pipeline_schedule_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:owner) }
- it { is_expected.to have_many(:pipelines) }
+ it { is_expected.to have_many(:pipelines).dependent(:nullify) }
it { is_expected.to have_many(:variables) }
it { is_expected.to respond_to(:ref) }
@@ -281,4 +281,19 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
let!(:model) { create(:ci_pipeline_schedule, project: parent) }
end
end
+
+ describe 'before_destroy' do
+ let_it_be_with_reload(:pipeline_schedule) { create(:ci_pipeline_schedule, cron: ' 0 0 * * * ') }
+ let_it_be_with_reload(:pipeline) { create(:ci_pipeline, pipeline_schedule: pipeline_schedule) }
+
+ it 'nullifys associated pipelines' do
+ expect(pipeline_schedule).to receive(:nullify_dependent_associations_in_batches).and_call_original
+
+ result = pipeline_schedule.destroy
+
+ expect(result).to be_truthy
+ expect(pipeline.reload.pipeline_schedule).to be_nil
+ expect(described_class.find_by(id: pipeline_schedule.id)).to be_nil
+ end
+ end
end
diff --git a/spec/support/helpers/features/two_factor_helpers.rb b/spec/support/helpers/features/two_factor_helpers.rb
index 824ecddc392..d5f069a40ea 100644
--- a/spec/support/helpers/features/two_factor_helpers.rb
+++ b/spec/support/helpers/features/two_factor_helpers.rb
@@ -14,6 +14,17 @@ module Spec
module Helpers
module Features
module TwoFactorHelpers
+ def copy_recovery_codes
+ click_on _('Copy codes')
+ click_on _('Proceed')
+ end
+
+ def enable_two_factor_authentication
+ click_on _('Enable two-factor authentication')
+ expect(page).to have_content(_('Set up new device'))
+ wait_for_requests
+ end
+
def manage_two_factor_authentication
click_on 'Manage two-factor authentication'
expect(page).to have_content("Set up new device")
@@ -21,6 +32,7 @@ module Spec
end
# Registers webauthn device via UI
+ # Remove after `webauthn_without_totp` feature flag is deleted.
def register_webauthn_device(webauthn_device = nil, name: 'My device')
webauthn_device ||= FakeWebauthnDevice.new(page, name)
webauthn_device.respond_to_webauthn_registration
@@ -31,6 +43,25 @@ module Spec
webauthn_device
end
+ def webauthn_device_registration(webauthn_device: nil, name: 'My device', password: 'fake')
+ webauthn_device ||= FakeWebauthnDevice.new(page, name)
+ webauthn_device.respond_to_webauthn_registration
+ click_on _('Set up new device')
+ webauthn_fill_form_and_submit(name: name, password: password)
+ webauthn_device
+ end
+
+ def webauthn_fill_form_and_submit(name: 'My device', password: 'fake')
+ expect(page).to have_content(
+ _('Your device was successfully set up! Give it a name and register it with the GitLab server.')
+ )
+ within '[data-testid="create-webauthn"]' do
+ fill_in _('Device name'), with: name
+ fill_in _('Current password'), with: password
+ click_on _('Register device')
+ end
+ end
+
# Adds webauthn device directly via database
def add_webauthn_device(app_id, user, fake_device = nil, name: 'My device')
fake_device ||= WebAuthn::FakeClient.new(app_id)