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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-29 09:08:16 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-29 09:08:16 +0300
commit2958635884b1dc5c8c01b5f00f0b7b7359556c37 (patch)
treefc875db03082af0ea8861a9cbf32d7c58e98d461 /spec/frontend/authentication
parentc70ed55242619ebd139c029a1f3c531d6b81a327 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/authentication')
-rw-r--r--spec/frontend/authentication/u2f/authenticate_spec.js109
-rw-r--r--spec/frontend/authentication/u2f/mock_u2f_device.js23
-rw-r--r--spec/frontend/authentication/u2f/register_spec.js83
-rw-r--r--spec/frontend/authentication/u2f/util_spec.js61
4 files changed, 276 insertions, 0 deletions
diff --git a/spec/frontend/authentication/u2f/authenticate_spec.js b/spec/frontend/authentication/u2f/authenticate_spec.js
new file mode 100644
index 00000000000..36cc6fb7c63
--- /dev/null
+++ b/spec/frontend/authentication/u2f/authenticate_spec.js
@@ -0,0 +1,109 @@
+import $ from 'jquery';
+import U2FAuthenticate from '~/authentication/u2f/authenticate';
+import 'vendor/u2f';
+import MockU2FDevice from './mock_u2f_device';
+
+describe('U2FAuthenticate', () => {
+ let u2fDevice;
+ let container;
+ let component;
+
+ preloadFixtures('u2f/authenticate.html');
+
+ beforeEach(() => {
+ loadFixtures('u2f/authenticate.html');
+ u2fDevice = new MockU2FDevice();
+ container = $('#js-authenticate-u2f');
+ component = new U2FAuthenticate(
+ container,
+ '#js-login-u2f-form',
+ {
+ sign_requests: [],
+ },
+ document.querySelector('#js-login-2fa-device'),
+ document.querySelector('.js-2fa-form'),
+ );
+ });
+
+ describe('with u2f unavailable', () => {
+ let oldu2f;
+
+ beforeEach(() => {
+ jest.spyOn(component, 'switchToFallbackUI').mockImplementation(() => {});
+ oldu2f = window.u2f;
+ window.u2f = null;
+ });
+
+ afterEach(() => {
+ window.u2f = oldu2f;
+ });
+
+ it('falls back to normal 2fa', done => {
+ component
+ .start()
+ .then(() => {
+ expect(component.switchToFallbackUI).toHaveBeenCalled();
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+
+ describe('with u2f available', () => {
+ beforeEach(done => {
+ // bypass automatic form submission within renderAuthenticated
+ jest.spyOn(component, 'renderAuthenticated').mockReturnValue(true);
+ u2fDevice = new MockU2FDevice();
+
+ component
+ .start()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('allows authenticating via a U2F device', () => {
+ const inProgressMessage = container.find('p');
+
+ expect(inProgressMessage.text()).toContain('Trying to communicate with your device');
+ u2fDevice.respondToAuthenticateRequest({
+ deviceData: 'this is data from the device',
+ });
+
+ expect(component.renderAuthenticated).toHaveBeenCalledWith(
+ '{"deviceData":"this is data from the device"}',
+ );
+ });
+
+ describe('errors', () => {
+ it('displays an error message', () => {
+ const setupButton = container.find('#js-login-u2f-device');
+ setupButton.trigger('click');
+ u2fDevice.respondToAuthenticateRequest({
+ errorCode: 'error!',
+ });
+ const errorMessage = container.find('p');
+
+ expect(errorMessage.text()).toContain('There was a problem communicating with your device');
+ });
+
+ it('allows retrying authentication after an error', () => {
+ let setupButton = container.find('#js-login-u2f-device');
+ setupButton.trigger('click');
+ u2fDevice.respondToAuthenticateRequest({
+ errorCode: 'error!',
+ });
+ const retryButton = container.find('#js-u2f-try-again');
+ retryButton.trigger('click');
+ setupButton = container.find('#js-login-u2f-device');
+ setupButton.trigger('click');
+ u2fDevice.respondToAuthenticateRequest({
+ deviceData: 'this is data from the device',
+ });
+
+ expect(component.renderAuthenticated).toHaveBeenCalledWith(
+ '{"deviceData":"this is data from the device"}',
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/authentication/u2f/mock_u2f_device.js b/spec/frontend/authentication/u2f/mock_u2f_device.js
new file mode 100644
index 00000000000..ec8425a4e3e
--- /dev/null
+++ b/spec/frontend/authentication/u2f/mock_u2f_device.js
@@ -0,0 +1,23 @@
+/* eslint-disable no-unused-expressions */
+
+export default class MockU2FDevice {
+ constructor() {
+ this.respondToAuthenticateRequest = this.respondToAuthenticateRequest.bind(this);
+ this.respondToRegisterRequest = this.respondToRegisterRequest.bind(this);
+ window.u2f || (window.u2f = {});
+ window.u2f.register = (appId, registerRequests, signRequests, callback) => {
+ this.registerCallback = callback;
+ };
+ window.u2f.sign = (appId, challenges, signRequests, callback) => {
+ this.authenticateCallback = callback;
+ };
+ }
+
+ respondToRegisterRequest(params) {
+ return this.registerCallback(params);
+ }
+
+ respondToAuthenticateRequest(params) {
+ return this.authenticateCallback(params);
+ }
+}
diff --git a/spec/frontend/authentication/u2f/register_spec.js b/spec/frontend/authentication/u2f/register_spec.js
new file mode 100644
index 00000000000..3c2ecdbba66
--- /dev/null
+++ b/spec/frontend/authentication/u2f/register_spec.js
@@ -0,0 +1,83 @@
+import $ from 'jquery';
+import U2FRegister from '~/authentication/u2f/register';
+import 'vendor/u2f';
+import MockU2FDevice from './mock_u2f_device';
+
+describe('U2FRegister', () => {
+ let u2fDevice;
+ let container;
+ let component;
+
+ preloadFixtures('u2f/register.html');
+
+ beforeEach(done => {
+ loadFixtures('u2f/register.html');
+ u2fDevice = new MockU2FDevice();
+ container = $('#js-register-u2f');
+ component = new U2FRegister(container, $('#js-register-u2f-templates'), {}, 'token');
+ component
+ .start()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('allows registering a U2F device', () => {
+ const setupButton = container.find('#js-setup-u2f-device');
+
+ expect(setupButton.text()).toBe('Set up new U2F device');
+ setupButton.trigger('click');
+ const inProgressMessage = container.children('p');
+
+ expect(inProgressMessage.text()).toContain('Trying to communicate with your device');
+ u2fDevice.respondToRegisterRequest({
+ deviceData: 'this is data from the device',
+ });
+ const registeredMessage = container.find('p');
+ const deviceResponse = container.find('#js-device-response');
+
+ expect(registeredMessage.text()).toContain('Your device was successfully set up!');
+ expect(deviceResponse.val()).toBe('{"deviceData":"this is data from the device"}');
+ });
+
+ describe('errors', () => {
+ it("doesn't allow the same device to be registered twice (for the same user", () => {
+ const setupButton = container.find('#js-setup-u2f-device');
+ setupButton.trigger('click');
+ u2fDevice.respondToRegisterRequest({
+ errorCode: 4,
+ });
+ const errorMessage = container.find('p');
+
+ expect(errorMessage.text()).toContain('already been registered with us');
+ });
+
+ it('displays an error message for other errors', () => {
+ const setupButton = container.find('#js-setup-u2f-device');
+ setupButton.trigger('click');
+ u2fDevice.respondToRegisterRequest({
+ errorCode: 'error!',
+ });
+ const errorMessage = container.find('p');
+
+ expect(errorMessage.text()).toContain('There was a problem communicating with your device');
+ });
+
+ it('allows retrying registration after an error', () => {
+ let setupButton = container.find('#js-setup-u2f-device');
+ setupButton.trigger('click');
+ u2fDevice.respondToRegisterRequest({
+ errorCode: 'error!',
+ });
+ const retryButton = container.find('#U2FTryAgain');
+ retryButton.trigger('click');
+ setupButton = container.find('#js-setup-u2f-device');
+ setupButton.trigger('click');
+ u2fDevice.respondToRegisterRequest({
+ deviceData: 'this is data from the device',
+ });
+ const registeredMessage = container.find('p');
+
+ expect(registeredMessage.text()).toContain('Your device was successfully set up!');
+ });
+ });
+});
diff --git a/spec/frontend/authentication/u2f/util_spec.js b/spec/frontend/authentication/u2f/util_spec.js
new file mode 100644
index 00000000000..67fd4c73243
--- /dev/null
+++ b/spec/frontend/authentication/u2f/util_spec.js
@@ -0,0 +1,61 @@
+import { canInjectU2fApi } from '~/authentication/u2f/util';
+
+describe('U2F Utils', () => {
+ describe('canInjectU2fApi', () => {
+ it('returns false for Chrome < 41', () => {
+ const userAgent =
+ 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.28 Safari/537.36';
+
+ expect(canInjectU2fApi(userAgent)).toBe(false);
+ });
+
+ it('returns true for Chrome >= 41', () => {
+ const userAgent =
+ 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36';
+
+ expect(canInjectU2fApi(userAgent)).toBe(true);
+ });
+
+ it('returns false for Opera < 40', () => {
+ const userAgent =
+ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 OPR/32.0.1948.25';
+
+ expect(canInjectU2fApi(userAgent)).toBe(false);
+ });
+
+ it('returns true for Opera >= 40', () => {
+ const userAgent =
+ 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 OPR/43.0.2442.991';
+
+ expect(canInjectU2fApi(userAgent)).toBe(true);
+ });
+
+ it('returns false for Safari', () => {
+ const userAgent =
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4';
+
+ expect(canInjectU2fApi(userAgent)).toBe(false);
+ });
+
+ it('returns false for Chrome on Android', () => {
+ const userAgent =
+ 'Mozilla/5.0 (Linux; Android 7.0; VS988 Build/NRD90U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3145.0 Mobile Safari/537.36';
+
+ expect(canInjectU2fApi(userAgent)).toBe(false);
+ });
+
+ it('returns false for Chrome on iOS', () => {
+ const userAgent =
+ 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1';
+
+ expect(canInjectU2fApi(userAgent)).toBe(false);
+ });
+
+ it('returns false for Safari on iOS', () => {
+ const userAgent =
+ 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A356 Safari/604.1';
+
+ expect(canInjectU2fApi(userAgent)).toBe(false);
+ });
+ });
+});