Commit fb66f975 authored by Vitaly Slobodin's avatar Vitaly Slobodin

Merge branch 'tomquirk/344887-move-jira-connect-user-link-to-vue' into 'master'

Move Jira Connect user link to Vue

See merge request gitlab-org/gitlab!74972
parents e0bb9f2a d46e1f00
......@@ -5,7 +5,7 @@ import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
export default async function initJiraConnectBranches() {
export default function initJiraConnectBranches() {
const el = document.querySelector('.js-jira-connect-create-branch');
if (!el) {
return null;
......
......@@ -7,6 +7,7 @@ import { SET_ALERT } from '../store/mutation_types';
import SubscriptionsList from './subscriptions_list.vue';
import AddNamespaceButton from './add_namespace_button.vue';
import SignInButton from './sign_in_button.vue';
import UserLink from './user_link.vue';
export default {
name: 'JiraConnectApp',
......@@ -18,6 +19,7 @@ export default {
SubscriptionsList,
AddNamespaceButton,
SignInButton,
UserLink,
},
inject: {
usersPath: {
......@@ -74,6 +76,8 @@ export default {
</template>
</gl-alert>
<user-link :user-signed-in="userSignedIn" :has-subscriptions="hasSubscriptions" />
<h2 class="gl-text-center gl-mb-7">{{ s__('JiraService|GitLab for Jira Configuration') }}</h2>
<div class="jira-connect-app-body gl-mx-auto gl-px-5 gl-mb-7">
<template v-if="hasSubscriptions">
......
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { __ } from '~/locale';
import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils';
export default {
components: {
GlLink,
GlSprintf,
},
inject: {
usersPath: {
default: '',
},
gitlabUserPath: {
default: '',
},
},
props: {
userSignedIn: {
type: Boolean,
required: true,
},
hasSubscriptions: {
type: Boolean,
required: true,
},
},
data() {
return {
signInURL: '',
};
},
computed: {
gitlabUserHandle() {
return `@${gon.current_username}`;
},
},
async created() {
this.signInURL = await getGitlabSignInURL(this.usersPath);
},
i18n: {
signInText: __('Sign in to GitLab'),
signedInAsUserText: __('Signed in to GitLab as %{user_link}'),
},
};
</script>
<template>
<div class="jira-connect-user gl-font-base">
<gl-sprintf v-if="userSignedIn" :message="$options.i18n.signedInAsUserText">
<template #user_link>
<gl-link data-testid="gitlab-user-link" :href="gitlabUserPath" target="_blank">
{{ gitlabUserHandle }}
</gl-link>
</template>
</gl-sprintf>
<gl-link
v-else-if="hasSubscriptions"
data-testid="sign-in-link"
:href="signInURL"
target="_blank"
>
{{ $options.i18n.signInText }}
</gl-link>
</div>
</template>
......@@ -7,25 +7,11 @@ import Translate from '~/vue_shared/translate';
import JiraConnectApp from './components/app.vue';
import createStore from './store';
import { getGitlabSignInURL, sizeToParent } from './utils';
import { sizeToParent } from './utils';
const store = createStore();
/**
* Add `return_to` query param to all HAML-defined GitLab sign in links.
*/
const updateSignInLinks = async () => {
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() {
await updateSignInLinks();
export function initJiraConnect() {
const el = document.querySelector('.js-jira-connect-app');
if (!el) {
return null;
......@@ -35,7 +21,7 @@ export async function initJiraConnect() {
Vue.use(Translate);
Vue.use(GlFeatureFlagsPlugin);
const { groupsPath, subscriptions, subscriptionsPath, usersPath } = el.dataset;
const { groupsPath, subscriptions, subscriptionsPath, usersPath, gitlabUserPath } = el.dataset;
sizeToParent();
return new Vue({
......@@ -46,6 +32,7 @@ export async function initJiraConnect() {
subscriptions: JSON.parse(subscriptions),
subscriptionsPath,
usersPath,
gitlabUserPath,
},
render(createElement) {
return createElement(JiraConnectApp);
......
......@@ -8,7 +8,8 @@ module JiraConnectHelper
groups_path: api_v4_groups_path(params: { min_access_level: Gitlab::Access::MAINTAINER, skip_groups: skip_groups }),
subscriptions: subscriptions.map { |s| serialize_subscription(s) }.to_json,
subscriptions_path: jira_connect_subscriptions_path,
users_path: current_user ? nil : jira_connect_users_path
users_path: current_user ? nil : jira_connect_users_path, # users_path is used to determine if user is signed in
gitlab_user_path: current_user ? user_path(current_user) : nil
}
end
......
%header.jira-connect-header.gl-display-flex.gl-align-items-center.gl-justify-content-center.gl-px-5.gl-border-b-solid.gl-border-b-gray-100.gl-border-b-1.gl-bg-white
= link_to brand_header_logo, Gitlab.config.gitlab.url, target: '_blank', rel: 'noopener noreferrer'
.jira-connect-user.gl-font-base
- if current_user
- user_link = link_to(current_user.to_reference, jira_connect_users_path, target: '_blank', rel: 'noopener noreferrer', class: 'js-jira-connect-sign-in')
= _('Signed in to GitLab as %{user_link}').html_safe % { user_link: user_link }
- elsif @subscriptions.present?
= link_to _('Sign in to GitLab'), jira_connect_users_path, target: '_blank', rel: 'noopener noreferrer', class: 'js-jira-connect-sign-in'
%main.jira-connect-app.gl-px-5.gl-pt-7.gl-mx-auto
.js-jira-connect-app{ data: jira_connect_app_data(@subscriptions) }
......
......@@ -5,6 +5,7 @@ import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue';
import AddNamespaceButton from '~/jira_connect/subscriptions/components/add_namespace_button.vue';
import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue';
import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue';
import UserLink from '~/jira_connect/subscriptions/components/user_link.vue';
import createStore from '~/jira_connect/subscriptions/store';
import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types';
import { __ } from '~/locale';
......@@ -12,6 +13,7 @@ import { mockSubscription } from '../mock_data';
jest.mock('~/jira_connect/subscriptions/utils', () => ({
retrieveAlert: jest.fn().mockReturnValue({ message: 'error message' }),
getGitlabSignInURL: jest.fn(),
}));
describe('JiraConnectApp', () => {
......@@ -83,6 +85,22 @@ describe('JiraConnectApp', () => {
});
},
);
it('renders UserLink component', () => {
createComponent({
provide: {
usersPath: '/user',
subscriptions: [],
},
});
const userLink = wrapper.findComponent(UserLink);
expect(userLink.exists()).toBe(true);
expect(userLink.props()).toEqual({
hasSubscriptions: false,
userSignedIn: false,
});
});
});
describe('alert', () => {
......
import { GlSprintf } from '@gitlab/ui';
import UserLink from '~/jira_connect/subscriptions/components/user_link.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
jest.mock('~/jira_connect/subscriptions/utils', () => ({
getGitlabSignInURL: jest.fn().mockImplementation((path) => Promise.resolve(path)),
}));
describe('SubscriptionsList', () => {
let wrapper;
const createComponent = (propsData = {}, { provide } = {}) => {
wrapper = shallowMountExtended(UserLink, {
propsData,
provide,
stubs: {
GlSprintf,
},
});
};
const findSignInLink = () => wrapper.findByTestId('sign-in-link');
const findGitlabUserLink = () => wrapper.findByTestId('gitlab-user-link');
const findSprintf = () => wrapper.findComponent(GlSprintf);
afterEach(() => {
wrapper.destroy();
});
describe.each`
userSignedIn | hasSubscriptions | expectGlSprintf | expectGlLink
${true} | ${false} | ${true} | ${false}
${false} | ${true} | ${false} | ${true}
${true} | ${true} | ${true} | ${false}
${false} | ${false} | ${false} | ${false}
`(
'when `userSignedIn` is $userSignedIn and `hasSubscriptions` is $hasSubscriptions',
({ userSignedIn, hasSubscriptions, expectGlSprintf, expectGlLink }) => {
it('renders template correctly', () => {
createComponent({
userSignedIn,
hasSubscriptions,
});
expect(findSprintf().exists()).toBe(expectGlSprintf);
expect(findSignInLink().exists()).toBe(expectGlLink);
});
},
);
describe('sign in link', () => {
it('renders with correct href', async () => {
const mockUsersPath = '/user';
createComponent(
{
userSignedIn: false,
hasSubscriptions: true,
},
{ provide: { usersPath: mockUsersPath } },
);
await waitForPromises();
expect(findSignInLink().exists()).toBe(true);
expect(findSignInLink().attributes('href')).toBe(mockUsersPath);
});
});
describe('gitlab user link', () => {
window.gon = { current_username: 'root' };
beforeEach(() => {
createComponent(
{
userSignedIn: true,
hasSubscriptions: true,
},
{ provide: { gitlabUserPath: '/root' } },
);
});
it('renders with correct href', () => {
expect(findGitlabUserLink().attributes('href')).toBe('/root');
});
it('contains GitLab user handle', () => {
expect(findGitlabUserLink().text()).toBe('@root');
});
});
});
import { initJiraConnect } from '~/jira_connect/subscriptions';
import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils';
jest.mock('~/jira_connect/subscriptions/utils');
describe('initJiraConnect', () => {
const mockInitialHref = 'https://gitlab.com';
beforeEach(() => {
setFixtures(`
<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>
`);
});
const assertSignInLinks = (expectedLink) => {
Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => {
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);
});
});
});
......@@ -19,7 +19,9 @@ RSpec.describe JiraConnectHelper do
is_expected.to include(
:groups_path,
:subscriptions_path,
:users_path
:users_path,
:subscriptions,
:gitlab_user_path
)
end
......@@ -32,6 +34,10 @@ RSpec.describe JiraConnectHelper do
expect(subject[:groups_path]).to include("#{skip_groups_param}=#{subscription.namespace.id}")
end
it 'assigns gitlab_user_path to nil' do
expect(subject[:gitlab_user_path]).to be_nil
end
end
context 'user is logged in' do
......@@ -42,6 +48,10 @@ RSpec.describe JiraConnectHelper do
it 'assigns users_path to nil' do
expect(subject[:users_path]).to be_nil
end
it 'assigns gitlab_user_path correctly' do
expect(subject[:gitlab_user_path]).to eq(user_path(user))
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'jira_connect/subscriptions/index.html.haml' do
let(:user) { build_stubbed(:user) }
before do
allow(view).to receive(:current_user).and_return(user)
assign(:subscriptions, create_list(:jira_connect_subscription, 1))
end
context 'when the user is signed in' do
it 'shows link to user profile' do
render
expect(rendered).to have_link(user.to_reference)
end
end
context 'when the user is not signed in' do
let(:user) { nil }
it 'shows "Sign in" link' do
render
expect(rendered).to have_link('Sign in to GitLab')
end
end
end
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