Commit 4965a720 authored by Tom Quirk's avatar Tom Quirk

Jira Connect: consolidate sign in link update logic

We have logic that adds a `return_to` parameter
to sign-in links in the JIra Connect app. This code
was previously duplicated.

This commit consolidates the code into a single helper
function.

There are no user facing changes.
parent d7bba2c7
<script>
import { GlButton } from '@gitlab/ui';
import { getLocation } from '~/jira_connect/subscriptions/utils';
import { objectToQuery } from '~/lib/utils/url_utility';
import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils';
export default {
components: {
......@@ -15,34 +14,21 @@ export default {
},
data() {
return {
location: '',
signInURL: '',
};
},
computed: {
usersPathWithReturnTo() {
if (this.location) {
const queryParams = {
return_to: this.location,
};
return `${this.usersPath}?${objectToQuery(queryParams)}`;
}
return this.usersPath;
},
},
created() {
this.setLocation();
this.setSignInURL();
},
methods: {
async setLocation() {
this.location = await getLocation();
async setSignInURL() {
this.signInURL = await getGitlabSignInURL(this.usersPath);
},
},
};
</script>
<template>
<gl-button category="primary" variant="info" :href="usersPathWithReturnTo" target="_blank">
<gl-button category="primary" variant="info" :href="signInURL" target="_blank">
<slot>
{{ s__('Integrations|Sign in to add namespaces') }}
</slot>
......
......@@ -7,7 +7,7 @@ import Translate from '~/vue_shared/translate';
import JiraConnectApp from './components/app.vue';
import createStore from './store';
import { getLocation, sizeToParent } from './utils';
import { getGitlabSignInURL, sizeToParent } from './utils';
const store = createStore();
......@@ -15,11 +15,12 @@ const store = createStore();
* Add `return_to` query param to all HAML-defined GitLab sign in links.
*/
const updateSignInLinks = async () => {
const location = await getLocation();
Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => {
const updatedLink = `${el.getAttribute('href')}?return_to=${location}`;
await Promise.all(
Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).map(async (el) => {
const updatedLink = await getGitlabSignInURL(el.getAttribute('href'));
el.setAttribute('href', updatedLink);
});
}),
);
};
export async function initJiraConnect() {
......
import AccessorUtilities from '~/lib/utils/accessor';
import { objectToQuery } from '~/lib/utils/url_utility';
import { ALERT_LOCALSTORAGE_KEY } from './constants';
const isFunction = (fn) => typeof fn === 'function';
......@@ -71,3 +72,17 @@ export const sizeToParent = () => {
AP.sizeToParent();
}
};
export const getGitlabSignInURL = async (signInURL) => {
const location = await getLocation();
if (location) {
const queryParams = {
return_to: location,
};
return `${signInURL}?${objectToQuery(queryParams)}`;
}
return signInURL;
};
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { getLocation } from '~/jira_connect/subscriptions/utils';
import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils';
import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue';
import waitForPromises from 'helpers/wait_for_promises';
......@@ -32,16 +32,14 @@ describe('SignInButton', () => {
});
describe.each`
getLocationValue | expectedHref
${''} | ${MOCK_USERS_PATH}
${undefined} | ${MOCK_USERS_PATH}
${'https://test.jira.com'} | ${`${MOCK_USERS_PATH}?return_to=${encodeURIComponent('https://test.jira.com')}`}
`('when getLocation resolves with `$getLocationValue`', ({ getLocationValue, expectedHref }) => {
expectedHref
${MOCK_USERS_PATH}
${`${MOCK_USERS_PATH}?return_to=${encodeURIComponent('https://test.jira.com')}`}
`('when getGitlabSignInURL resolves with `$expectedHref`', ({ expectedHref }) => {
it(`sets button href to ${expectedHref}`, async () => {
getLocation.mockResolvedValue(getLocationValue);
getGitlabSignInURL.mockResolvedValue(expectedHref);
createComponent();
expect(getLocation).toHaveBeenCalled();
await waitForPromises();
expect(findButton().attributes('href')).toBe(expectedHref);
......
import { initJiraConnect } from '~/jira_connect/subscriptions';
import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils';
jest.mock('~/jira_connect/subscriptions/utils', () => ({
getLocation: jest.fn().mockResolvedValue('test/location'),
}));
jest.mock('~/jira_connect/subscriptions/utils');
describe('initJiraConnect', () => {
beforeEach(async () => {
const mockInitialHref = 'https://gitlab.com';
beforeEach(() => {
setFixtures(`
<a class="js-jira-connect-sign-in" href="https://gitlab.com">Sign In</a>
<a class="js-jira-connect-sign-in" href="https://gitlab.com">Another Sign In</a>
<a class="js-jira-connect-sign-in" href="${mockInitialHref}">Sign In</a>
<a class="js-jira-connect-sign-in" href="${mockInitialHref}">Another Sign In</a>
`);
await initJiraConnect();
});
describe('Sign in links', () => {
it('have `return_to` query parameter', () => {
const assertSignInLinks = (expectedLink) => {
Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => {
expect(el.href).toContain('return_to=test/location');
expect(el.getAttribute('href')).toBe(expectedLink);
});
};
describe('Sign in links', () => {
it('are updated on initialization', async () => {
const mockSignInLink = `https://gitlab.com?return_to=${encodeURIComponent('/test/location')}`;
getGitlabSignInURL.mockResolvedValue(mockSignInLink);
// assert the initial state
assertSignInLinks(mockInitialHref);
await initJiraConnect();
// assert the update has occurred
assertSignInLinks(mockSignInLink);
});
});
});
......@@ -8,6 +8,7 @@ import {
getLocation,
reloadPage,
sizeToParent,
getGitlabSignInURL,
} from '~/jira_connect/subscriptions/utils';
describe('JiraConnect utils', () => {
......@@ -137,4 +138,25 @@ describe('JiraConnect utils', () => {
});
});
});
describe('getGitlabSignInURL', () => {
const mockSignInURL = 'https://gitlab.com/sign_in';
it.each`
returnTo | expectResult
${undefined} | ${mockSignInURL}
${''} | ${mockSignInURL}
${'/test/location'} | ${`${mockSignInURL}?return_to=${encodeURIComponent('/test/location')}`}
`(
'returns `$expectResult` when `AP.getLocation` resolves to `$returnTo`',
async ({ returnTo, expectResult }) => {
global.AP = {
getLocation: jest.fn().mockImplementation((cb) => cb(returnTo)),
};
const url = await getGitlabSignInURL(mockSignInURL);
expect(url).toBe(expectResult);
},
);
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment