1# frozen_string_literal: true
2
3require 'spec_helper'
4
5RSpec.shared_examples 'Signup name validation' do |field, max_length, label|
6  before do
7    visit new_user_registration_path
8  end
9
10  describe "#{field} validation", :js do
11    it "does not show an error border if the user's fullname length is not longer than #{max_length} characters" do
12      fill_in field, with: 'u' * max_length
13
14      expect(find('.name')).not_to have_css '.gl-field-error-outline'
15    end
16
17    it 'shows an error border if the user\'s fullname contains an emoji' do
18      simulate_input("##{field}", 'Ehsan ��')
19
20      expect(find('.name')).to have_css '.gl-field-error-outline'
21    end
22
23    it "shows an error border if the user\'s fullname is longer than #{max_length} characters" do
24      fill_in field, with: 'n' * (max_length + 1)
25
26      expect(find('.name')).to have_css '.gl-field-error-outline'
27    end
28
29    it "shows an error message if the user\'s #{label} is longer than #{max_length} characters" do
30      fill_in field, with: 'n' * (max_length + 1)
31
32      expect(page).to have_content("#{label} is too long (maximum is #{max_length} characters).")
33    end
34
35    it 'shows an error message if the username contains emojis' do
36      simulate_input("##{field}", 'Ehsan ��')
37
38      expect(page).to have_content("Invalid input, please avoid emojis")
39    end
40  end
41end
42
43RSpec.describe 'Signup' do
44  include TermsHelper
45
46  before do
47    stub_application_setting(require_admin_approval_after_user_signup: false)
48  end
49
50  let(:new_user) { build_stubbed(:user) }
51
52  def fill_in_signup_form
53    fill_in 'new_user_username', with: new_user.username
54    fill_in 'new_user_email', with: new_user.email
55    fill_in 'new_user_first_name', with: new_user.first_name
56    fill_in 'new_user_last_name', with: new_user.last_name
57    fill_in 'new_user_password', with: new_user.password
58  end
59
60  def confirm_email
61    new_user_token = User.find_by_email(new_user.email).confirmation_token
62
63    visit user_confirmation_path(confirmation_token: new_user_token)
64  end
65
66  describe 'username validation', :js do
67    before do
68      visit new_user_registration_path
69    end
70
71    it 'does not show an error border if the username is available' do
72      fill_in 'new_user_username', with: 'new-user'
73      wait_for_requests
74
75      expect(find('.username')).not_to have_css '.gl-field-error-outline'
76    end
77
78    it 'does not show an error border if the username contains dots (.)' do
79      simulate_input('#new_user_username', 'new.user.username')
80      wait_for_requests
81
82      expect(find('.username')).not_to have_css '.gl-field-error-outline'
83    end
84
85    it 'does not show an error border if the username length is not longer than 255 characters' do
86      fill_in 'new_user_username', with: 'u' * 255
87      wait_for_requests
88
89      expect(find('.username')).not_to have_css '.gl-field-error-outline'
90    end
91
92    it 'shows an error border if the username already exists' do
93      existing_user = create(:user)
94
95      fill_in 'new_user_username', with: existing_user.username
96      wait_for_requests
97
98      expect(find('.username')).to have_css '.gl-field-error-outline'
99    end
100
101    it 'shows a success border if the username is available' do
102      fill_in 'new_user_username', with: 'new-user'
103      wait_for_requests
104
105      expect(find('.username')).to have_css '.gl-field-success-outline'
106    end
107
108    it 'shows an error border if the username contains special characters' do
109      fill_in 'new_user_username', with: 'new$user!username'
110      wait_for_requests
111
112      expect(find('.username')).to have_css '.gl-field-error-outline'
113    end
114
115    it 'shows an error border if the username is longer than 255 characters' do
116      fill_in 'new_user_username', with: 'u' * 256
117      wait_for_requests
118
119      expect(find('.username')).to have_css '.gl-field-error-outline'
120    end
121
122    it 'shows an error message if the username is longer than 255 characters' do
123      fill_in 'new_user_username', with: 'u' * 256
124      wait_for_requests
125
126      expect(page).to have_content("Username is too long (maximum is 255 characters).")
127    end
128
129    it 'shows an error message if the username is less than 2 characters' do
130      fill_in 'new_user_username', with: 'u'
131      wait_for_requests
132
133      expect(page).to have_content("Username is too short (minimum is 2 characters).")
134    end
135
136    it 'shows an error message on submit if the username contains special characters' do
137      fill_in 'new_user_username', with: 'new$user!username'
138      wait_for_requests
139
140      click_button "Register"
141
142      expect(page).to have_content("Please create a username with only alphanumeric characters.")
143    end
144
145    it 'shows an error border if the username contains emojis' do
146      simulate_input('#new_user_username', 'ehsan��')
147
148      expect(find('.username')).to have_css '.gl-field-error-outline'
149    end
150
151    it 'shows an error message if the username contains emojis' do
152      simulate_input('#new_user_username', 'ehsan��')
153
154      expect(page).to have_content("Invalid input, please avoid emojis")
155    end
156
157    it 'shows a pending message if the username availability is being fetched', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/31484' do
158      fill_in 'new_user_username', with: 'new-user'
159
160      expect(find('.username > .validation-pending')).not_to have_css '.hide'
161    end
162
163    it 'shows a success message if the username is available' do
164      fill_in 'new_user_username', with: 'new-user'
165      wait_for_requests
166
167      expect(find('.username > .validation-success')).not_to have_css '.hide'
168    end
169
170    it 'shows an error message if the username is unavailable' do
171      existing_user = create(:user)
172
173      fill_in 'new_user_username', with: existing_user.username
174      wait_for_requests
175
176      expect(find('.username > .validation-error')).not_to have_css '.hide'
177    end
178
179    it 'shows a success message if the username is corrected and then available' do
180      fill_in 'new_user_username', with: 'new-user$'
181      wait_for_requests
182      fill_in 'new_user_username', with: 'new-user'
183      wait_for_requests
184
185      expect(page).to have_content("Username is available.")
186    end
187  end
188
189  context 'with no errors' do
190    context 'when sending confirmation email' do
191      before do
192        stub_application_setting(send_user_confirmation_email: true)
193      end
194
195      context 'when soft email confirmation is not enabled' do
196        before do
197          stub_feature_flags(soft_email_confirmation: false)
198        end
199
200        it 'creates the user account and sends a confirmation email, and pre-fills email address after confirming' do
201          visit new_user_registration_path
202
203          fill_in_signup_form
204
205          expect { click_button 'Register' }.to change { User.count }.by(1)
206          expect(current_path).to eq users_almost_there_path
207          expect(page).to have_content("Please check your email (#{new_user.email}) to confirm your account")
208
209          confirm_email
210
211          expect(find_field('Username or email').value).to eq(new_user.email)
212        end
213      end
214
215      context 'when soft email confirmation is enabled' do
216        before do
217          stub_feature_flags(soft_email_confirmation: true)
218        end
219
220        it 'creates the user account and sends a confirmation email' do
221          visit new_user_registration_path
222
223          fill_in_signup_form
224
225          expect { click_button 'Register' }.to change { User.count }.by(1)
226          expect(current_path).to eq users_sign_up_welcome_path
227        end
228      end
229    end
230
231    context "when not sending confirmation email" do
232      before do
233        stub_application_setting(send_user_confirmation_email: false)
234      end
235
236      it 'creates the user account and goes to dashboard' do
237        visit new_user_registration_path
238
239        fill_in_signup_form
240        click_button "Register"
241
242        expect(current_path).to eq users_sign_up_welcome_path
243      end
244    end
245
246    context 'with required admin approval enabled' do
247      before do
248        stub_application_setting(require_admin_approval_after_user_signup: true)
249      end
250
251      it 'creates the user but does not sign them in' do
252        visit new_user_registration_path
253
254        fill_in_signup_form
255
256        expect { click_button 'Register' }.to change { User.count }.by(1)
257        expect(current_path).to eq new_user_session_path
258        expect(page).to have_content("You have signed up successfully. However, we could not sign you in because your account is awaiting approval from your GitLab administrator")
259      end
260    end
261  end
262
263  context 'with errors' do
264    it "displays the errors" do
265      create(:user, email: new_user.email)
266      visit new_user_registration_path
267
268      fill_in_signup_form
269      click_button "Register"
270
271      expect(current_path).to eq user_registration_path
272      expect(page).to have_content("error prohibited this user from being saved")
273      expect(page).to have_content("Email has already been taken")
274    end
275
276    it 'does not redisplay the password' do
277      create(:user, email: new_user.email)
278      visit new_user_registration_path
279
280      fill_in_signup_form
281      click_button "Register"
282
283      expect(current_path).to eq user_registration_path
284      expect(page.body).not_to match(/#{new_user.password}/)
285    end
286  end
287
288  context 'when terms are enforced' do
289    before do
290      enforce_terms
291    end
292
293    it 'renders text that the user confirms terms by clicking register' do
294      visit new_user_registration_path
295
296      expect(page).to have_content(/By clicking Register, I agree that I have read and accepted the Terms of Use and Privacy Policy/)
297
298      fill_in_signup_form
299      click_button 'Register'
300
301      expect(current_path).to eq users_sign_up_welcome_path
302    end
303  end
304
305  context 'when reCAPTCHA and invisible captcha are enabled' do
306    before do
307      stub_application_setting(invisible_captcha_enabled: true)
308      stub_application_setting(recaptcha_enabled: true)
309      allow_next_instance_of(RegistrationsController) do |instance|
310        allow(instance).to receive(:verify_recaptcha).and_return(true)
311      end
312    end
313
314    context 'when reCAPTCHA detects malicious behaviour' do
315      before do
316        allow_next_instance_of(RegistrationsController) do |instance|
317          allow(instance).to receive(:verify_recaptcha).and_return(false)
318        end
319      end
320
321      it 'prevents from signing up' do
322        visit new_user_registration_path
323
324        fill_in_signup_form
325
326        expect { click_button 'Register' }.not_to change { User.count }
327        expect(page).to have_content('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.')
328      end
329    end
330
331    context 'when invisible captcha detects malicious behaviour' do
332      it 'prevents from signing up' do
333        visit new_user_registration_path
334
335        fill_in_signup_form
336
337        expect { click_button 'Register' }.not_to change { User.count }
338        expect(page).to have_content('That was a bit too quick! Please resubmit.')
339      end
340    end
341  end
342
343  it 'redirects to step 2 of the signup process, sets the role and redirects back' do
344    visit new_user_registration_path
345
346    fill_in_signup_form
347    click_button 'Register'
348
349    visit new_project_path
350
351    expect(page).to have_current_path(users_sign_up_welcome_path)
352
353    select 'Software Developer', from: 'user_role'
354    click_button 'Get started!'
355
356    created_user = User.find_by_username(new_user.username)
357
358    expect(created_user.software_developer_role?).to be_truthy
359    expect(created_user.setup_for_company).to be_nil
360    expect(page).to have_current_path(new_project_path)
361  end
362
363  it_behaves_like 'Signup name validation', 'new_user_first_name', 127, 'First name'
364  it_behaves_like 'Signup name validation', 'new_user_last_name', 127, 'Last name'
365end
366