Commit f7016509 authored by Tom Quirk's avatar Tom Quirk Committed by Miguel Rincon

Add browser support alert in Jira Connect app

Behind feature flag jira_connect_oauth.
Display an alert if crypto or localStorage isn't available
in the user's browser.
parent 2a779800
...@@ -3,12 +3,15 @@ import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui'; ...@@ -3,12 +3,15 @@ import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { mapState, mapMutations } from 'vuex'; import { mapState, mapMutations } from 'vuex';
import { retrieveAlert } from '~/jira_connect/subscriptions/utils'; import { retrieveAlert } from '~/jira_connect/subscriptions/utils';
import AccessorUtilities from '~/lib/utils/accessor';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { I18N_DEFAULT_SIGN_IN_ERROR_MESSAGE } from '../constants'; import { I18N_DEFAULT_SIGN_IN_ERROR_MESSAGE } from '../constants';
import { SET_ALERT } from '../store/mutation_types'; import { SET_ALERT } from '../store/mutation_types';
import SignInPage from '../pages/sign_in.vue'; import SignInPage from '../pages/sign_in.vue';
import SubscriptionsPage from '../pages/subscriptions.vue'; import SubscriptionsPage from '../pages/subscriptions.vue';
import UserLink from './user_link.vue'; import UserLink from './user_link.vue';
import CompatibilityAlert from './compatibility_alert.vue'; import CompatibilityAlert from './compatibility_alert.vue';
import BrowserSupportAlert from './browser_support_alert.vue';
export default { export default {
name: 'JiraConnectApp', name: 'JiraConnectApp',
...@@ -18,9 +21,11 @@ export default { ...@@ -18,9 +21,11 @@ export default {
GlSprintf, GlSprintf,
UserLink, UserLink,
CompatibilityAlert, CompatibilityAlert,
BrowserSupportAlert,
SignInPage, SignInPage,
SubscriptionsPage, SubscriptionsPage,
}, },
mixins: [glFeatureFlagMixin()],
inject: { inject: {
usersPath: { usersPath: {
default: '', default: '',
...@@ -45,6 +50,16 @@ export default { ...@@ -45,6 +50,16 @@ export default {
userSignedIn() { userSignedIn() {
return Boolean(!this.usersPath || this.user); return Boolean(!this.usersPath || this.user);
}, },
isOauthEnabled() {
return this.glFeatures.jiraConnectOauth;
},
/**
* Returns false if the GitLab for Jira app doesn't support the user's browser.
* Any web API that the GitLab for Jira app depends on should be checked here.
*/
isBrowserSupported() {
return !this.isOauthEnabled || AccessorUtilities.canUseCrypto();
},
}, },
created() { created() {
this.setInitialAlert(); this.setInitialAlert();
...@@ -71,12 +86,12 @@ export default { ...@@ -71,12 +86,12 @@ export default {
</script> </script>
<template> <template>
<div> <browser-support-alert v-if="!isBrowserSupported" class="gl-mb-7" />
<compatibility-alert /> <div v-else data-testid="jira-connect-app">
<compatibility-alert class="gl-mb-7" />
<gl-alert <gl-alert
v-if="shouldShowAlert" v-if="shouldShowAlert"
class="gl-mb-7"
:variant="alert.variant" :variant="alert.variant"
:title="alert.title" :title="alert.title"
data-testid="jira-connect-persisted-alert" data-testid="jira-connect-persisted-alert"
......
<script>
import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
import { s__ } from '~/locale';
import { helpPagePath } from '~/helpers/help_page_helper';
export default {
name: 'BrowserSupportAlert',
components: {
GlAlert,
GlSprintf,
GlLink,
},
i18n: {
title: s__('Integrations|Your browser is not supported'),
body: s__(
'Integrations|You must use a %{linkStart}supported browser%{linkEnd} to use the GitLab for Jira app.',
),
},
DOCS_LINK_URL: helpPagePath('install/requirements', { anchor: 'supported-web-browsers' }),
};
</script>
<template>
<gl-alert variant="danger" :title="$options.i18n.title" :dismissible="false">
<gl-sprintf :message="$options.i18n.body">
<template #link="{ content }">
<gl-link :href="$options.DOCS_LINK_URL" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</gl-alert>
</template>
...@@ -46,16 +46,13 @@ export default { ...@@ -46,16 +46,13 @@ export default {
> >
<gl-alert <gl-alert
v-if="shouldShowAlert" v-if="shouldShowAlert"
class="gl-mb-7"
variant="info" variant="info"
:title="$options.i18n.title" :title="$options.i18n.title"
@dismiss="dismissAlert" @dismiss="dismissAlert"
> >
<gl-sprintf :message="$options.i18n.body"> <gl-sprintf :message="$options.i18n.body">
<template #link="{ content }"> <template #link="{ content }">
<gl-link :href="$options.DOCS_LINK_URL" target="_blank" rel="noopener noreferrer">{{ <gl-link :href="$options.DOCS_LINK_URL" target="_blank">{{ content }}</gl-link>
content
}}</gl-link>
</template> </template>
</gl-sprintf> </gl-sprintf>
</gl-alert> </gl-alert>
......
...@@ -20281,12 +20281,18 @@ msgstr "" ...@@ -20281,12 +20281,18 @@ msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces." msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
msgstr "" msgstr ""
msgid "Integrations|You must use a %{linkStart}supported browser%{linkEnd} to use the GitLab for Jira app."
msgstr ""
msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}" msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
msgstr "" msgstr ""
msgid "Integrations|You've activated every integration 🎉" msgid "Integrations|You've activated every integration 🎉"
msgstr "" msgstr ""
msgid "Integrations|Your browser is not supported"
msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao." msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr "" msgstr ""
......
...@@ -6,10 +6,12 @@ import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue'; ...@@ -6,10 +6,12 @@ import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue';
import SignInPage from '~/jira_connect/subscriptions/pages/sign_in.vue'; import SignInPage from '~/jira_connect/subscriptions/pages/sign_in.vue';
import SubscriptionsPage from '~/jira_connect/subscriptions/pages/subscriptions.vue'; import SubscriptionsPage from '~/jira_connect/subscriptions/pages/subscriptions.vue';
import UserLink from '~/jira_connect/subscriptions/components/user_link.vue'; import UserLink from '~/jira_connect/subscriptions/components/user_link.vue';
import BrowserSupportAlert from '~/jira_connect/subscriptions/components/browser_support_alert.vue';
import createStore from '~/jira_connect/subscriptions/store'; import createStore from '~/jira_connect/subscriptions/store';
import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types'; import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types';
import { I18N_DEFAULT_SIGN_IN_ERROR_MESSAGE } from '~/jira_connect/subscriptions/constants'; import { I18N_DEFAULT_SIGN_IN_ERROR_MESSAGE } from '~/jira_connect/subscriptions/constants';
import { __ } from '~/locale'; import { __ } from '~/locale';
import AccessorUtilities from '~/lib/utils/accessor';
import { mockSubscription } from '../mock_data'; import { mockSubscription } from '../mock_data';
jest.mock('~/jira_connect/subscriptions/utils', () => ({ jest.mock('~/jira_connect/subscriptions/utils', () => ({
...@@ -26,6 +28,7 @@ describe('JiraConnectApp', () => { ...@@ -26,6 +28,7 @@ describe('JiraConnectApp', () => {
const findSignInPage = () => wrapper.findComponent(SignInPage); const findSignInPage = () => wrapper.findComponent(SignInPage);
const findSubscriptionsPage = () => wrapper.findComponent(SubscriptionsPage); const findSubscriptionsPage = () => wrapper.findComponent(SubscriptionsPage);
const findUserLink = () => wrapper.findComponent(UserLink); const findUserLink = () => wrapper.findComponent(UserLink);
const findBrowserSupportAlert = () => wrapper.findComponent(BrowserSupportAlert);
const createComponent = ({ provide, mountFn = shallowMountExtended } = {}) => { const createComponent = ({ provide, mountFn = shallowMountExtended } = {}) => {
store = createStore(); store = createStore();
...@@ -207,4 +210,29 @@ describe('JiraConnectApp', () => { ...@@ -207,4 +210,29 @@ describe('JiraConnectApp', () => {
}); });
}); });
}); });
describe.each`
jiraConnectOauthEnabled | canUseCrypto | shouldShowAlert
${false} | ${false} | ${false}
${false} | ${true} | ${false}
${true} | ${false} | ${true}
${true} | ${true} | ${false}
`(
'when `jiraConnectOauth` feature flag is $jiraConnectOauthEnabled and `AccessorUtilities.canUseCrypto` returns $canUseCrypto',
({ jiraConnectOauthEnabled, canUseCrypto, shouldShowAlert }) => {
beforeEach(() => {
jest.spyOn(AccessorUtilities, 'canUseCrypto').mockReturnValue(canUseCrypto);
createComponent({ provide: { glFeatures: { jiraConnectOauth: jiraConnectOauthEnabled } } });
});
it(`does ${shouldShowAlert ? '' : 'not'} render BrowserSupportAlert component`, () => {
expect(findBrowserSupportAlert().exists()).toBe(shouldShowAlert);
});
it(`does ${!shouldShowAlert ? '' : 'not'} render the main Jira Connect app template`, () => {
expect(wrapper.findByTestId('jira-connect-app').exists()).toBe(!shouldShowAlert);
});
},
);
}); });
import { GlAlert, GlLink } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
import BrowserSupportAlert from '~/jira_connect/subscriptions/components/browser_support_alert.vue';
describe('BrowserSupportAlert', () => {
let wrapper;
const createComponent = ({ mountFn = shallowMount } = {}) => {
wrapper = mountFn(BrowserSupportAlert);
};
const findAlert = () => wrapper.findComponent(GlAlert);
const findLink = () => wrapper.findComponent(GlLink);
afterEach(() => {
wrapper.destroy();
});
it('displays a non-dismissible alert', () => {
createComponent();
expect(findAlert().exists()).toBe(true);
expect(findAlert().props()).toMatchObject({
dismissible: false,
title: BrowserSupportAlert.i18n.title,
variant: 'danger',
});
});
it('renders help link with target="_blank" and rel="noopener noreferrer"', () => {
createComponent({ mountFn: mount });
expect(findLink().attributes()).toMatchObject({
target: '_blank',
rel: 'noopener',
});
});
});
...@@ -29,7 +29,7 @@ describe('CompatibilityAlert', () => { ...@@ -29,7 +29,7 @@ describe('CompatibilityAlert', () => {
createComponent({ mountFn: mount }); createComponent({ mountFn: mount });
expect(findLink().attributes()).toMatchObject({ expect(findLink().attributes()).toMatchObject({
target: '_blank', target: '_blank',
rel: 'noopener noreferrer', rel: 'noopener',
}); });
}); });
......
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