Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
7d4bff6fe8
commit
77da08b6e8
|
@ -42,24 +42,15 @@ export default {
|
|||
isLoading: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
oauthEnabled() {
|
||||
return this.glFeatures.jiraConnectOauth;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['addSubscription']),
|
||||
async onClick() {
|
||||
if (this.oauthEnabled) {
|
||||
this.isLoading = true;
|
||||
await this.addSubscription({
|
||||
namespacePath: this.group.full_path,
|
||||
subscriptionsPath: this.subscriptionsPath,
|
||||
});
|
||||
this.isLoading = false;
|
||||
} else {
|
||||
this.deprecatedAddSubscription();
|
||||
}
|
||||
this.isLoading = true;
|
||||
await this.addSubscription({
|
||||
namespacePath: this.group.full_path,
|
||||
subscriptionsPath: this.subscriptionsPath,
|
||||
});
|
||||
this.isLoading = false;
|
||||
},
|
||||
deprecatedAddSubscription() {
|
||||
this.isLoading = true;
|
||||
|
|
|
@ -45,21 +45,14 @@ export default {
|
|||
return !isEmpty(this.subscriptions);
|
||||
},
|
||||
userSignedIn() {
|
||||
if (this.isOauthEnabled) {
|
||||
return Boolean(this.currentUser);
|
||||
}
|
||||
|
||||
return Boolean(!this.usersPath);
|
||||
},
|
||||
isOauthEnabled() {
|
||||
return this.glFeatures.jiraConnectOauth;
|
||||
return Boolean(this.currentUser);
|
||||
},
|
||||
/**
|
||||
* 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();
|
||||
return AccessorUtilities.canUseCrypto();
|
||||
},
|
||||
gitlabUrl() {
|
||||
return gon.gitlab_url;
|
||||
|
@ -80,11 +73,10 @@ export default {
|
|||
}),
|
||||
...mapActions(['fetchSubscriptions']),
|
||||
/**
|
||||
* Fetch subscriptions from the REST API,
|
||||
* if the jiraConnectOauth flag is enabled.
|
||||
* Fetch subscriptions from the REST API.
|
||||
*/
|
||||
fetchSubscriptionsOauth() {
|
||||
if (!this.isOauthEnabled || !this.userSignedIn) return;
|
||||
if (!this.userSignedIn) return;
|
||||
|
||||
this.fetchSubscriptions(this.subscriptionsPath);
|
||||
},
|
||||
|
|
|
@ -54,9 +54,6 @@ export default {
|
|||
? this.$options.i18n.signedInAsUserText
|
||||
: this.$options.i18n.signedInText;
|
||||
},
|
||||
isOauthEnabled() {
|
||||
return this.glFeatures.jiraConnectOauth;
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
this.signInURL = await getGitlabSignInURL(this.usersPath);
|
||||
|
@ -79,13 +76,9 @@ export default {
|
|||
</gl-sprintf>
|
||||
|
||||
<template v-else-if="hasSubscriptions">
|
||||
<sign-in-oauth-button v-if="isOauthEnabled" category="tertiary">
|
||||
<sign-in-oauth-button category="tertiary">
|
||||
{{ $options.i18n.signInText }}
|
||||
</sign-in-oauth-button>
|
||||
|
||||
<gl-link v-else data-testid="sign-in-link" :href="signInURL" target="_blank">
|
||||
{{ $options.i18n.signInText }}
|
||||
</gl-link>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -9,7 +9,6 @@ export default {
|
|||
name: 'SignInGitlabCom',
|
||||
components: {
|
||||
SubscriptionsList,
|
||||
SignInLegacyButton: () => import('../../components/sign_in_legacy_button.vue'),
|
||||
SignInOauthButton: () => import('../../components/sign_in_oauth_button.vue'),
|
||||
},
|
||||
mixins: [glFeatureFlagMixin()],
|
||||
|
@ -20,11 +19,6 @@ export default {
|
|||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
useSignInOauthButton() {
|
||||
return this.glFeatures.jiraConnectOauth;
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
signInButtonTextWithSubscriptions: s__('Integrations|Sign in to add namespaces'),
|
||||
signInText: s__('JiraService|Sign in to GitLab to get started.'),
|
||||
|
@ -44,16 +38,12 @@ export default {
|
|||
<div v-if="hasSubscriptions">
|
||||
<div class="gl-display-flex gl-justify-content-end gl-mb-3">
|
||||
<sign-in-oauth-button
|
||||
v-if="useSignInOauthButton"
|
||||
:gitlab-base-path="$options.GITLAB_COM_BASE_PATH"
|
||||
@sign-in="$emit('sign-in-oauth', $event)"
|
||||
@error="onSignInError"
|
||||
>
|
||||
{{ $options.i18n.signInButtonTextWithSubscriptions }}
|
||||
</sign-in-oauth-button>
|
||||
<sign-in-legacy-button v-else :users-path="usersPath">
|
||||
{{ $options.i18n.signInButtonTextWithSubscriptions }}
|
||||
</sign-in-legacy-button>
|
||||
</div>
|
||||
|
||||
<subscriptions-list />
|
||||
|
@ -61,12 +51,10 @@ export default {
|
|||
<div v-else class="gl-text-center">
|
||||
<p class="gl-mb-7">{{ $options.i18n.signInText }}</p>
|
||||
<sign-in-oauth-button
|
||||
v-if="useSignInOauthButton"
|
||||
:gitlab-base-path="$options.GITLAB_COM_BASE_PATH"
|
||||
@sign-in="$emit('sign-in-oauth', $event)"
|
||||
@error="onSignInError"
|
||||
/>
|
||||
<sign-in-legacy-button v-else class="gl-mb-7" :users-path="usersPath" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -19,7 +19,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
isOauthSelfManagedEnabled() {
|
||||
return this.glFeatures.jiraConnectOauth && this.publicKeyStorageEnabled;
|
||||
return this.publicKeyStorageEnabled;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -59,7 +59,7 @@ export default ({ editorAiActions = [] } = {}) => {
|
|||
showTimelineViewToggle,
|
||||
reportAbusePath: notesDataset.reportAbusePath,
|
||||
newCommentTemplatePath: notesDataset.newCommentTemplatePath,
|
||||
editorAiActions: editorAiActions.map((factory) => factory(notesDataset)),
|
||||
editorAiActions: editorAiActions.map((factory) => factory(noteableData)),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -5,6 +5,10 @@ module Gitlab
|
|||
# Module that provides methods shared by the various workers used for
|
||||
# importing GitHub projects.
|
||||
module ReschedulingMethods
|
||||
include JobDelayCalculator
|
||||
|
||||
ENQUEUED_JOB_COUNT = 'github-importer/enqueued_job_count/%{project}/%{collection}'
|
||||
|
||||
# project_id - The ID of the GitLab project to import the note into.
|
||||
# hash - A Hash containing the details of the GitHub object to import.
|
||||
# notify_key - The Redis key to notify upon completion, if any.
|
||||
|
@ -18,10 +22,7 @@ module Gitlab
|
|||
if try_import(project, client, hash)
|
||||
notify_waiter(notify_key)
|
||||
else
|
||||
# In the event of hitting the rate limit we want to reschedule the job
|
||||
# so its retried after our rate limit has been reset.
|
||||
self.class
|
||||
.perform_in(client.rate_limit_resets_in, project.id, hash, notify_key)
|
||||
reschedule_job(project, client, hash, notify_key)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -35,6 +36,20 @@ module Gitlab
|
|||
def notify_waiter(key = nil)
|
||||
JobWaiter.notify(key, jid) if key
|
||||
end
|
||||
|
||||
def reschedule_job(project, client, hash, notify_key)
|
||||
# In the event of hitting the rate limit we want to reschedule the job
|
||||
# so its retried after our rate limit has been reset with additional delay
|
||||
# to spread the load.
|
||||
enqueued_job_count_key = format(ENQUEUED_JOB_COUNT, project: project.id, collection: object_type)
|
||||
enqueued_job_counter =
|
||||
Gitlab::Cache::Import::Caching.increment(enqueued_job_count_key, timeout: client.rate_limit_resets_in)
|
||||
|
||||
job_delay = client.rate_limit_resets_in + calculate_job_delay(enqueued_job_counter)
|
||||
|
||||
self.class
|
||||
.perform_in(job_delay, project.id, hash, notify_key)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,6 +16,10 @@ module Gitlab
|
|||
def object_type
|
||||
:pull_request
|
||||
end
|
||||
|
||||
def parallel_import_batch
|
||||
{ size: 200, delay: 1.minute }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
- title: "Auto DevOps no longer provisions a database by default"
|
||||
announcement_milestone: "15.8"
|
||||
removal_milestone: "16.0"
|
||||
breaking_change: true
|
||||
reporter: tigerwnz
|
||||
stage: Environments
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343988
|
||||
body: |
|
||||
Currently, Auto DevOps provisions an in-cluster PostgreSQL database by default.
|
||||
In GitLab 16.0, databases will be provisioned only for users who opt in. This
|
||||
change supports production deployments that require more robust database management.
|
||||
|
||||
If you want Auto DevOps to provision an in-cluster database,
|
||||
set the `POSTGRES_ENABLED` CI/CD variable to `true`.
|
||||
tiers: [Core, Premium, Ultimate]
|
||||
documentation_url: https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-deploy
|
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemovePhabricatorFromApplicationSettings < Gitlab::Database::Migration[2.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
class ApplicationSetting < MigrationRecord
|
||||
end
|
||||
|
||||
def up
|
||||
# rubocop: disable Style/GuardClause
|
||||
unless import_sources.empty?
|
||||
ApplicationSetting.update_all(import_sources: import_sources.reject { |x| x == "phabricator" })
|
||||
end
|
||||
# rubocop: enable Style/GuardClause
|
||||
end
|
||||
|
||||
def down
|
||||
## a reversion is not needed as Phabricator is no longer a supported import source
|
||||
# and attempting to save it as one will result in a ActiveRecord error.
|
||||
end
|
||||
|
||||
def import_sources
|
||||
## the last ApplicationSetting record is used to determine application settings
|
||||
import_sources = ApplicationSetting.last&.import_sources
|
||||
import_sources.nil? ? [] : YAML.safe_load(import_sources)
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
c8e606b6e85bee317017cb15bd9d4249378b4d2b9225fb493e85086063f0f23d
|
|
@ -5439,7 +5439,7 @@ Input type: `ScanExecutionPolicyCommitInput`
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationscanexecutionpolicycommitclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationscanexecutionpolicycommitfullpath"></a>`fullPath` | [`String`](#string) | Full path of the project. |
|
||||
| <a id="mutationscanexecutionpolicycommitname"></a>`name` | [`String`](#string) | Name of the policy. If the name is null, the `name` field from `policy_yaml` is used. |
|
||||
| <a id="mutationscanexecutionpolicycommitname"></a>`name` | [`String!`](#string) | Name of the policy. If the name is null, the `name` field from `policy_yaml` is used. |
|
||||
| <a id="mutationscanexecutionpolicycommitoperationmode"></a>`operationMode` | [`MutationOperationMode!`](#mutationoperationmode) | Changes the operation mode. |
|
||||
| <a id="mutationscanexecutionpolicycommitpolicyyaml"></a>`policyYaml` | [`String!`](#string) | YAML snippet of the policy. |
|
||||
| <a id="mutationscanexecutionpolicycommitprojectpath"></a>`projectPath` **{warning-solid}** | [`ID`](#id) | **Deprecated:** Use `fullPath`. Deprecated in 14.10. |
|
||||
|
|
|
@ -270,6 +270,12 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
|
|||
every Sidekiq process also listens to those queues to ensure all jobs are processed across
|
||||
all queues. This behavior does not apply if you have configured the [routing rules](../administration/sidekiq/processing_specific_job_classes.md#routing-rules).
|
||||
|
||||
### 15.11.0
|
||||
|
||||
- Upgrades to GitLab 15.11 directly from GitLab versions 15.5.0 and earlier on self-managed installs will fail due to a missing migration until the fix for [issue 408304](https://gitlab.com/gitlab-org/gitlab/-/issues/408304) is released in 15.11.1. Affected users wanting to upgrade to 15.11.x can either:
|
||||
- Perform an intermediate upgrade to any version between 15.5 and 15.10 before upgrading to 15.11, or
|
||||
- Target the forthcoming 15.11.1 patch.
|
||||
|
||||
### 15.10.0
|
||||
|
||||
- Gitaly configuration changes significantly in Omnibus GitLab 16.0. You can begin migrating to the new structure in Omnibus GitLab 15.10 while backwards compatibility is
|
||||
|
|
|
@ -36,6 +36,19 @@ For removal reviewers (Technical Writers only):
|
|||
|
||||
## Removed in 16.0
|
||||
|
||||
### Auto DevOps no longer provisions a database by default
|
||||
|
||||
WARNING:
|
||||
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
|
||||
Review the details carefully before upgrading.
|
||||
|
||||
Currently, Auto DevOps provisions an in-cluster PostgreSQL database by default.
|
||||
In GitLab 16.0, databases will be provisioned only for users who opt in. This
|
||||
change supports production deployments that require more robust database management.
|
||||
|
||||
If you want Auto DevOps to provision an in-cluster database,
|
||||
set the `POSTGRES_ENABLED` CI/CD variable to `true`.
|
||||
|
||||
### Project REST API field `operations_access_level` removed
|
||||
|
||||
WARNING:
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module GithubImport
|
||||
# Used to calculate delay to spread sidekiq jobs on fetching records during import
|
||||
# and upon job reschedule when the rate limit is reached
|
||||
module JobDelayCalculator
|
||||
# Default batch settings for parallel import (can be redefined in Importer/Worker classes)
|
||||
def parallel_import_batch
|
||||
{ size: 1000, delay: 1.minute }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def calculate_job_delay(job_index)
|
||||
multiplier = (job_index / parallel_import_batch[:size])
|
||||
|
||||
(multiplier * parallel_import_batch[:delay]) + 1.second
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -3,6 +3,8 @@
|
|||
module Gitlab
|
||||
module GithubImport
|
||||
module ParallelScheduling
|
||||
include JobDelayCalculator
|
||||
|
||||
attr_reader :project, :client, :page_counter, :already_imported_cache_key,
|
||||
:job_waiter_cache_key, :job_waiter_remaining_cache_key
|
||||
|
||||
|
@ -197,11 +199,6 @@ module Gitlab
|
|||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Default batch settings for parallel import (can be redefined in Importer classes)
|
||||
def parallel_import_batch
|
||||
{ size: 1000, delay: 1.minute }
|
||||
end
|
||||
|
||||
def abort_on_failure
|
||||
false
|
||||
end
|
||||
|
@ -243,12 +240,6 @@ module Gitlab
|
|||
JobWaiter.new(jobs_remaining, key)
|
||||
end
|
||||
end
|
||||
|
||||
def calculate_job_delay(job_index)
|
||||
multiplier = (job_index / parallel_import_batch[:size])
|
||||
|
||||
(multiplier * parallel_import_batch[:delay]) + 1.second
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10949,6 +10949,9 @@ msgstr ""
|
|||
msgid "ComplianceFrameworks|Description is required"
|
||||
msgstr ""
|
||||
|
||||
msgid "ComplianceFrameworks|Edit compliance framework"
|
||||
msgstr ""
|
||||
|
||||
msgid "ComplianceFrameworks|Edit framework"
|
||||
msgstr ""
|
||||
|
||||
|
@ -10991,6 +10994,9 @@ msgstr ""
|
|||
msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}See some examples%{linkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "ComplianceFrameworks|Saved changes to compliance framework"
|
||||
msgstr ""
|
||||
|
||||
msgid "ComplianceFrameworks|Set default"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -1,22 +1,11 @@
|
|||
import { GlButton } from '@gitlab/ui';
|
||||
import { mount, shallowMount } from '@vue/test-utils';
|
||||
import { nextTick } from 'vue';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
|
||||
import * as JiraConnectApi from '~/jira_connect/subscriptions/api';
|
||||
import GroupItemName from '~/jira_connect/subscriptions/components/group_item_name.vue';
|
||||
import GroupsListItem from '~/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue';
|
||||
import { persistAlert, reloadPage } from '~/jira_connect/subscriptions/utils';
|
||||
import {
|
||||
I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE,
|
||||
I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE,
|
||||
INTEGRATIONS_DOC_LINK,
|
||||
} from '~/jira_connect/subscriptions/constants';
|
||||
import createStore from '~/jira_connect/subscriptions/store';
|
||||
import { mockGroup1 } from '../../mock_data';
|
||||
|
||||
jest.mock('~/jira_connect/subscriptions/utils');
|
||||
|
||||
describe('GroupsListItem', () => {
|
||||
let wrapper;
|
||||
let store;
|
||||
|
@ -61,88 +50,24 @@ describe('GroupsListItem', () => {
|
|||
});
|
||||
|
||||
describe('on Link button click', () => {
|
||||
describe('when jiraConnectOauth feature flag is disabled', () => {
|
||||
let addSubscriptionSpy;
|
||||
const mockSubscriptionsPath = '/subscriptions';
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent({ mountFn: mount });
|
||||
|
||||
addSubscriptionSpy = jest.spyOn(JiraConnectApi, 'addSubscription').mockResolvedValue();
|
||||
});
|
||||
|
||||
it('sets button to loading and sends request', async () => {
|
||||
expect(findLinkButton().props('loading')).toBe(false);
|
||||
|
||||
clickLinkButton();
|
||||
await nextTick();
|
||||
|
||||
expect(findLinkButton().props('loading')).toBe(true);
|
||||
await waitForPromises();
|
||||
|
||||
expect(addSubscriptionSpy).toHaveBeenCalledWith(
|
||||
mockAddSubscriptionsPath,
|
||||
mockGroup1.full_path,
|
||||
);
|
||||
expect(persistAlert).toHaveBeenCalledWith({
|
||||
linkUrl: INTEGRATIONS_DOC_LINK,
|
||||
message: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE,
|
||||
title: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE,
|
||||
variant: 'success',
|
||||
});
|
||||
});
|
||||
|
||||
describe('when request is successful', () => {
|
||||
it('reloads the page', async () => {
|
||||
clickLinkButton();
|
||||
|
||||
await waitForPromises();
|
||||
|
||||
expect(reloadPage).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when request has errors', () => {
|
||||
const mockErrorMessage = 'error message';
|
||||
const mockError = { response: { data: { error: mockErrorMessage } } };
|
||||
|
||||
beforeEach(() => {
|
||||
addSubscriptionSpy = jest
|
||||
.spyOn(JiraConnectApi, 'addSubscription')
|
||||
.mockRejectedValue(mockError);
|
||||
});
|
||||
|
||||
it('emits `error` event', async () => {
|
||||
clickLinkButton();
|
||||
|
||||
await waitForPromises();
|
||||
|
||||
expect(reloadPage).not.toHaveBeenCalled();
|
||||
expect(wrapper.emitted('error')[0][0]).toBe(mockErrorMessage);
|
||||
});
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
mountFn: mount,
|
||||
provide: {
|
||||
subscriptionsPath: mockSubscriptionsPath,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('when jiraConnectOauth feature flag is enabled', () => {
|
||||
const mockSubscriptionsPath = '/subscriptions';
|
||||
it('dispatches `addSubscription` action', () => {
|
||||
clickLinkButton();
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
mountFn: mount,
|
||||
provide: {
|
||||
subscriptionsPath: mockSubscriptionsPath,
|
||||
glFeatures: { jiraConnectOauth: true },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('dispatches `addSubscription` action', async () => {
|
||||
clickLinkButton();
|
||||
await nextTick();
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith('addSubscription', {
|
||||
namespacePath: mockGroup1.full_path,
|
||||
subscriptionsPath: mockSubscriptionsPath,
|
||||
});
|
||||
expect(store.dispatch).toHaveBeenCalledTimes(1);
|
||||
expect(store.dispatch).toHaveBeenCalledWith('addSubscription', {
|
||||
namespacePath: mockGroup1.full_path,
|
||||
subscriptionsPath: mockSubscriptionsPath,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { GlLink } from '@gitlab/ui';
|
||||
import { GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { nextTick } from 'vue';
|
||||
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
|
||||
import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue';
|
||||
import SignInPage from '~/jira_connect/subscriptions/pages/sign_in/sign_in_page.vue';
|
||||
|
@ -10,74 +10,48 @@ import BrowserSupportAlert from '~/jira_connect/subscriptions/components/browser
|
|||
import createStore from '~/jira_connect/subscriptions/store';
|
||||
import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types';
|
||||
import { I18N_DEFAULT_SIGN_IN_ERROR_MESSAGE } from '~/jira_connect/subscriptions/constants';
|
||||
import { retrieveAlert } from '~/jira_connect/subscriptions/utils';
|
||||
import { __ } from '~/locale';
|
||||
import AccessorUtilities from '~/lib/utils/accessor';
|
||||
import * as api from '~/jira_connect/subscriptions/api';
|
||||
import { mockSubscription } from '../mock_data';
|
||||
|
||||
jest.mock('~/jira_connect/subscriptions/utils', () => ({
|
||||
retrieveAlert: jest.fn().mockReturnValue({ message: 'error message' }),
|
||||
getGitlabSignInURL: jest.fn(),
|
||||
}));
|
||||
jest.mock('~/jira_connect/subscriptions/utils');
|
||||
|
||||
describe('JiraConnectApp', () => {
|
||||
let wrapper;
|
||||
let store;
|
||||
|
||||
const mockCurrentUser = { name: 'root' };
|
||||
|
||||
const findAlert = () => wrapper.findByTestId('jira-connect-persisted-alert');
|
||||
const findJiraConnectApp = () => wrapper.findByTestId('jira-connect-app');
|
||||
const findAlertLink = () => findAlert().findComponent(GlLink);
|
||||
const findSignInPage = () => wrapper.findComponent(SignInPage);
|
||||
const findSubscriptionsPage = () => wrapper.findComponent(SubscriptionsPage);
|
||||
const findUserLink = () => wrapper.findComponent(UserLink);
|
||||
const findBrowserSupportAlert = () => wrapper.findComponent(BrowserSupportAlert);
|
||||
|
||||
const createComponent = ({ provide, mountFn = shallowMountExtended, initialState = {} } = {}) => {
|
||||
const createComponent = ({ provide, initialState = {} } = {}) => {
|
||||
store = createStore({ ...initialState, subscriptions: [mockSubscription] });
|
||||
jest.spyOn(store, 'dispatch').mockImplementation();
|
||||
|
||||
wrapper = mountFn(JiraConnectApp, {
|
||||
wrapper = shallowMountExtended(JiraConnectApp, {
|
||||
store,
|
||||
provide,
|
||||
stubs: {
|
||||
GlSprintf,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
describe('template', () => {
|
||||
describe.each`
|
||||
scenario | usersPath | shouldRenderSignInPage | shouldRenderSubscriptionsPage
|
||||
${'user is not signed in'} | ${'/users'} | ${true} | ${false}
|
||||
${'user is signed in'} | ${undefined} | ${false} | ${true}
|
||||
`('when $scenario', ({ usersPath, shouldRenderSignInPage, shouldRenderSubscriptionsPage }) => {
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
provide: {
|
||||
usersPath,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it(`${shouldRenderSignInPage ? 'renders' : 'does not render'} sign in page`, () => {
|
||||
expect(findSignInPage().isVisible()).toBe(shouldRenderSignInPage);
|
||||
if (shouldRenderSignInPage) {
|
||||
expect(findSignInPage().props('hasSubscriptions')).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it(`${
|
||||
shouldRenderSubscriptionsPage ? 'renders' : 'does not render'
|
||||
} subscriptions page`, () => {
|
||||
expect(findSubscriptionsPage().exists()).toBe(shouldRenderSubscriptionsPage);
|
||||
if (shouldRenderSubscriptionsPage) {
|
||||
expect(findSubscriptionsPage().props('hasSubscriptions')).toBe(true);
|
||||
}
|
||||
});
|
||||
beforeEach(() => {
|
||||
jest.spyOn(AccessorUtilities, 'canUseCrypto').mockReturnValue(true);
|
||||
});
|
||||
|
||||
it('renders UserLink component', () => {
|
||||
createComponent({
|
||||
provide: {
|
||||
usersPath: '/user',
|
||||
},
|
||||
});
|
||||
createComponent();
|
||||
|
||||
const userLink = findUserLink();
|
||||
expect(userLink.exists()).toBe(true);
|
||||
|
@ -87,148 +61,171 @@ describe('JiraConnectApp', () => {
|
|||
userSignedIn: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('alert', () => {
|
||||
it.each`
|
||||
message | variant | alertShouldRender
|
||||
${'Test error'} | ${'danger'} | ${true}
|
||||
${'Test notice'} | ${'info'} | ${true}
|
||||
${''} | ${undefined} | ${false}
|
||||
${undefined} | ${undefined} | ${false}
|
||||
it('renders only Jira Connect app', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findBrowserSupportAlert().exists()).toBe(false);
|
||||
expect(findJiraConnectApp().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders only BrowserSupportAlert when canUseCrypto is false', () => {
|
||||
jest.spyOn(AccessorUtilities, 'canUseCrypto').mockReturnValue(false);
|
||||
|
||||
createComponent();
|
||||
|
||||
expect(findBrowserSupportAlert().exists()).toBe(true);
|
||||
expect(findJiraConnectApp().exists()).toBe(false);
|
||||
});
|
||||
|
||||
describe.each`
|
||||
scenario | currentUser | shouldRenderSignInPage | shouldRenderSubscriptionsPage
|
||||
${'user is not signed in'} | ${undefined} | ${true} | ${false}
|
||||
${'user is signed in'} | ${mockCurrentUser} | ${false} | ${true}
|
||||
`(
|
||||
'renders correct alert when message is `$message` and variant is `$variant`',
|
||||
async ({ message, alertShouldRender, variant }) => {
|
||||
createComponent();
|
||||
'when $scenario',
|
||||
({ currentUser, shouldRenderSignInPage, shouldRenderSubscriptionsPage }) => {
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
initialState: {
|
||||
currentUser,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
store.commit(SET_ALERT, { message, variant });
|
||||
await nextTick();
|
||||
it(`${shouldRenderSignInPage ? 'renders' : 'does not render'} sign in page`, () => {
|
||||
expect(findSignInPage().isVisible()).toBe(shouldRenderSignInPage);
|
||||
if (shouldRenderSignInPage) {
|
||||
expect(findSignInPage().props('hasSubscriptions')).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
const alert = findAlert();
|
||||
|
||||
expect(alert.exists()).toBe(alertShouldRender);
|
||||
if (alertShouldRender) {
|
||||
expect(alert.isVisible()).toBe(alertShouldRender);
|
||||
expect(alert.html()).toContain(message);
|
||||
expect(alert.props('variant')).toBe(variant);
|
||||
expect(findAlertLink().exists()).toBe(false);
|
||||
}
|
||||
it(`${
|
||||
shouldRenderSubscriptionsPage ? 'renders' : 'does not render'
|
||||
} subscriptions page`, () => {
|
||||
expect(findSubscriptionsPage().exists()).toBe(shouldRenderSubscriptionsPage);
|
||||
if (shouldRenderSubscriptionsPage) {
|
||||
expect(findSubscriptionsPage().props('hasSubscriptions')).toBe(true);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it('hides alert on @dismiss event', async () => {
|
||||
createComponent();
|
||||
|
||||
store.commit(SET_ALERT, { message: 'test message' });
|
||||
await nextTick();
|
||||
|
||||
findAlert().vm.$emit('dismiss');
|
||||
await nextTick();
|
||||
|
||||
expect(findAlert().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders link when `linkUrl` is set', async () => {
|
||||
createComponent({ provide: { usersPath: '' }, mountFn: mountExtended });
|
||||
|
||||
store.commit(SET_ALERT, {
|
||||
message: __('test message %{linkStart}test link%{linkEnd}'),
|
||||
linkUrl: 'https://gitlab.com',
|
||||
});
|
||||
await nextTick();
|
||||
|
||||
const alertLink = findAlertLink();
|
||||
|
||||
expect(alertLink.exists()).toBe(true);
|
||||
expect(alertLink.text()).toContain('test link');
|
||||
expect(alertLink.attributes('href')).toBe('https://gitlab.com');
|
||||
});
|
||||
|
||||
describe('when alert is set in localStoage', () => {
|
||||
it('renders alert on mount', () => {
|
||||
createComponent();
|
||||
|
||||
const alert = findAlert();
|
||||
|
||||
expect(alert.exists()).toBe(true);
|
||||
expect(alert.html()).toContain('error message');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user signed out', () => {
|
||||
describe('when sign in page emits `error` event', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent({
|
||||
provide: {
|
||||
usersPath: '/mock',
|
||||
},
|
||||
});
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
findSignInPage().vm.$emit('error');
|
||||
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('displays alert', () => {
|
||||
const alert = findAlert();
|
||||
|
||||
expect(alert.exists()).toBe(true);
|
||||
expect(alert.html()).toContain(I18N_DEFAULT_SIGN_IN_ERROR_MESSAGE);
|
||||
expect(alert.text()).toContain(I18N_DEFAULT_SIGN_IN_ERROR_MESSAGE);
|
||||
expect(alert.props('variant')).toBe('danger');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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 }) => {
|
||||
describe('when sign in page emits `sign-in-oauth` event', () => {
|
||||
const mockSubscriptionsPath = '/mockSubscriptionsPath';
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(AccessorUtilities, 'canUseCrypto').mockReturnValue(canUseCrypto);
|
||||
jest.spyOn(api, 'fetchSubscriptions').mockResolvedValue({ data: { subscriptions: [] } });
|
||||
|
||||
createComponent({ provide: { glFeatures: { jiraConnectOauth: jiraConnectOauthEnabled } } });
|
||||
createComponent({
|
||||
initialState: {
|
||||
currentUser: mockCurrentUser,
|
||||
},
|
||||
provide: {
|
||||
subscriptionsPath: mockSubscriptionsPath,
|
||||
},
|
||||
});
|
||||
|
||||
findSignInPage().vm.$emit('sign-in-oauth');
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
describe('when `jiraConnectOauth` feature flag is enabled', () => {
|
||||
const mockSubscriptionsPath = '/mockSubscriptionsPath';
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.spyOn(api, 'fetchSubscriptions').mockResolvedValue({ data: { subscriptions: [] } });
|
||||
jest.spyOn(AccessorUtilities, 'canUseCrypto').mockReturnValue(true);
|
||||
|
||||
createComponent({
|
||||
initialState: {
|
||||
currentUser: { name: 'root' },
|
||||
},
|
||||
provide: {
|
||||
glFeatures: { jiraConnectOauth: true },
|
||||
subscriptionsPath: mockSubscriptionsPath,
|
||||
},
|
||||
});
|
||||
|
||||
findSignInPage().vm.$emit('sign-in-oauth');
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
describe('when oauth button emits `sign-in-oauth` event', () => {
|
||||
it('dispatches `fetchSubscriptions` action', () => {
|
||||
expect(store.dispatch).toHaveBeenCalledWith('fetchSubscriptions', mockSubscriptionsPath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('alert', () => {
|
||||
const mockAlertData = { message: 'error message' };
|
||||
|
||||
describe.each`
|
||||
alertData | expectAlert
|
||||
${undefined} | ${false}
|
||||
${mockAlertData} | ${true}
|
||||
`('when retrieveAlert returns $alertData', ({ alertData, expectAlert }) => {
|
||||
beforeEach(() => {
|
||||
retrieveAlert.mockReturnValue(alertData);
|
||||
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it(`${expectAlert ? 'renders' : 'does not render'} alert on mount`, () => {
|
||||
const alert = findAlert();
|
||||
|
||||
expect(alert.exists()).toBe(expectAlert);
|
||||
if (expectAlert) {
|
||||
expect(alert.text()).toContain(mockAlertData.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it.each`
|
||||
message | variant | alertShouldRender
|
||||
${'Test error'} | ${'danger'} | ${true}
|
||||
${'Test notice'} | ${'info'} | ${true}
|
||||
${''} | ${undefined} | ${false}
|
||||
${undefined} | ${undefined} | ${false}
|
||||
`(
|
||||
'renders correct alert when message is `$message` and variant is `$variant`',
|
||||
async ({ message, alertShouldRender, variant }) => {
|
||||
createComponent();
|
||||
|
||||
store.commit(SET_ALERT, { message, variant });
|
||||
await nextTick();
|
||||
|
||||
const alert = findAlert();
|
||||
|
||||
expect(alert.exists()).toBe(alertShouldRender);
|
||||
if (alertShouldRender) {
|
||||
expect(alert.isVisible()).toBe(alertShouldRender);
|
||||
expect(alert.text()).toContain(message);
|
||||
expect(alert.props('variant')).toBe(variant);
|
||||
expect(findAlertLink().exists()).toBe(false);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
it('hides alert on @dismiss event', async () => {
|
||||
createComponent();
|
||||
|
||||
store.commit(SET_ALERT, { message: 'test message' });
|
||||
await nextTick();
|
||||
|
||||
findAlert().vm.$emit('dismiss');
|
||||
await nextTick();
|
||||
|
||||
expect(findAlert().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders link when `linkUrl` is set', async () => {
|
||||
createComponent();
|
||||
|
||||
store.commit(SET_ALERT, {
|
||||
message: __('test message %{linkStart}test link%{linkEnd}'),
|
||||
linkUrl: 'https://gitlab.com',
|
||||
});
|
||||
await nextTick();
|
||||
|
||||
const alertLink = findAlertLink();
|
||||
|
||||
expect(alertLink.exists()).toBe(true);
|
||||
expect(alertLink.text()).toContain('test link');
|
||||
expect(alertLink.attributes('href')).toBe('https://gitlab.com');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,7 +3,6 @@ import UserLink from '~/jira_connect/subscriptions/components/user_link.vue';
|
|||
import SignInOauthButton from '~/jira_connect/subscriptions/components/sign_in_oauth_button.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)),
|
||||
|
@ -23,28 +22,19 @@ describe('UserLink', () => {
|
|||
});
|
||||
};
|
||||
|
||||
const findSignInLink = () => wrapper.findByTestId('sign-in-link');
|
||||
const findGitlabUserLink = () => wrapper.findByTestId('gitlab-user-link');
|
||||
const findSprintf = () => wrapper.findComponent(GlSprintf);
|
||||
const findOauthButton = () => wrapper.findComponent(SignInOauthButton);
|
||||
|
||||
describe.each`
|
||||
userSignedIn | hasSubscriptions | expectGlSprintf | expectGlLink | expectOauthButton | jiraConnectOauthEnabled
|
||||
${true} | ${false} | ${true} | ${false} | ${false} | ${false}
|
||||
${false} | ${true} | ${false} | ${true} | ${false} | ${false}
|
||||
${true} | ${true} | ${true} | ${false} | ${false} | ${false}
|
||||
${false} | ${false} | ${false} | ${false} | ${false} | ${false}
|
||||
${false} | ${true} | ${false} | ${false} | ${true} | ${true}
|
||||
userSignedIn | hasSubscriptions | expectGlSprintf | expectOauthButton
|
||||
${false} | ${false} | ${false} | ${false}
|
||||
${false} | ${true} | ${false} | ${true}
|
||||
${true} | ${false} | ${true} | ${false}
|
||||
${true} | ${true} | ${true} | ${false}
|
||||
`(
|
||||
'when `userSignedIn` is $userSignedIn, `hasSubscriptions` is $hasSubscriptions, `jiraConnectOauthEnabled` is $jiraConnectOauthEnabled',
|
||||
({
|
||||
userSignedIn,
|
||||
hasSubscriptions,
|
||||
expectGlSprintf,
|
||||
expectGlLink,
|
||||
expectOauthButton,
|
||||
jiraConnectOauthEnabled,
|
||||
}) => {
|
||||
'when `userSignedIn` is $userSignedIn, `hasSubscriptions` is $hasSubscriptions',
|
||||
({ userSignedIn, hasSubscriptions, expectGlSprintf, expectOauthButton }) => {
|
||||
it('renders template correctly', () => {
|
||||
createComponent(
|
||||
{
|
||||
|
@ -53,39 +43,17 @@ describe('UserLink', () => {
|
|||
},
|
||||
{
|
||||
provide: {
|
||||
glFeatures: {
|
||||
jiraConnectOauth: jiraConnectOauthEnabled,
|
||||
},
|
||||
oauthMetadata: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(findSprintf().exists()).toBe(expectGlSprintf);
|
||||
expect(findSignInLink().exists()).toBe(expectGlLink);
|
||||
expect(findOauthButton().exists()).toBe(expectOauthButton);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
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', () => {
|
||||
describe.each`
|
||||
current_username | gitlabUserPath | user | expectedUserHandle | expectedUserLink
|
||||
|
|
|
@ -19,20 +19,16 @@ describe('SignInGitlabCom', () => {
|
|||
let wrapper;
|
||||
let store;
|
||||
|
||||
const findSignInLegacyButton = () => wrapper.findComponent(SignInLegacyButton);
|
||||
const findSignInOauthButton = () => wrapper.findComponent(SignInOauthButton);
|
||||
const findSubscriptionsList = () => wrapper.findComponent(SubscriptionsList);
|
||||
|
||||
const createComponent = ({ props, jiraConnectOauthEnabled } = {}) => {
|
||||
const createComponent = ({ props } = {}) => {
|
||||
store = createStore();
|
||||
|
||||
wrapper = shallowMount(SignInGitlabCom, {
|
||||
store,
|
||||
provide: {
|
||||
...defaultProvide,
|
||||
glFeatures: {
|
||||
jiraConnectOauth: jiraConnectOauthEnabled,
|
||||
},
|
||||
},
|
||||
propsData: props,
|
||||
stubs: {
|
||||
|
@ -48,57 +44,37 @@ describe('SignInGitlabCom', () => {
|
|||
${'with subscriptions'} | ${true} | ${SignInGitlabCom.i18n.signInButtonTextWithSubscriptions}
|
||||
${'without subscriptions'} | ${false} | ${I18N_DEFAULT_SIGN_IN_BUTTON_TEXT}
|
||||
`('$scenario', ({ hasSubscriptions, signInButtonText }) => {
|
||||
describe('when `jiraConnectOauthEnabled` feature flag is disabled', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
jiraConnectOauthEnabled: false,
|
||||
props: {
|
||||
hasSubscriptions,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('renders legacy sign in button', () => {
|
||||
const button = findSignInLegacyButton();
|
||||
expect(button.props('usersPath')).toBe(mockUsersPath);
|
||||
expect(button.text()).toMatchInterpolatedText(signInButtonText);
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
props: {
|
||||
hasSubscriptions,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('when `jiraConnectOauthEnabled` feature flag is enabled', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
jiraConnectOauthEnabled: true,
|
||||
props: {
|
||||
hasSubscriptions,
|
||||
},
|
||||
describe('oauth sign in button', () => {
|
||||
it('renders oauth sign in button', () => {
|
||||
const button = findSignInOauthButton();
|
||||
expect(button.text()).toMatchInterpolatedText(signInButtonText);
|
||||
});
|
||||
|
||||
describe('when button emits `sign-in` event', () => {
|
||||
it('emits `sign-in-oauth` event', () => {
|
||||
const button = findSignInOauthButton();
|
||||
|
||||
const mockUser = { name: 'test' };
|
||||
button.vm.$emit('sign-in', mockUser);
|
||||
|
||||
expect(wrapper.emitted('sign-in-oauth')[0]).toEqual([mockUser]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('oauth sign in button', () => {
|
||||
it('renders oauth sign in button', () => {
|
||||
describe('when button emits `error` event', () => {
|
||||
it('emits `error` event', () => {
|
||||
const button = findSignInOauthButton();
|
||||
expect(button.text()).toMatchInterpolatedText(signInButtonText);
|
||||
});
|
||||
button.vm.$emit('error');
|
||||
|
||||
describe('when button emits `sign-in` event', () => {
|
||||
it('emits `sign-in-oauth` event', () => {
|
||||
const button = findSignInOauthButton();
|
||||
|
||||
const mockUser = { name: 'test' };
|
||||
button.vm.$emit('sign-in', mockUser);
|
||||
|
||||
expect(wrapper.emitted('sign-in-oauth')[0]).toEqual([mockUser]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when button emits `error` event', () => {
|
||||
it('emits `error` event', () => {
|
||||
const button = findSignInOauthButton();
|
||||
button.vm.$emit('error');
|
||||
|
||||
expect(wrapper.emitted('error')).toHaveLength(1);
|
||||
});
|
||||
expect(wrapper.emitted('error')).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,20 +12,11 @@ describe('SignInPage', () => {
|
|||
const findSignInGitlabCom = () => wrapper.findComponent(SignInGitlabCom);
|
||||
const findSignInGitabMultiversion = () => wrapper.findComponent(SignInGitlabMultiversion);
|
||||
|
||||
const createComponent = ({
|
||||
props = {},
|
||||
jiraConnectOauthEnabled,
|
||||
publicKeyStorageEnabled,
|
||||
} = {}) => {
|
||||
const createComponent = ({ props = {}, publicKeyStorageEnabled } = {}) => {
|
||||
store = createStore();
|
||||
|
||||
wrapper = shallowMount(SignInPage, {
|
||||
store,
|
||||
provide: {
|
||||
glFeatures: {
|
||||
jiraConnectOauth: jiraConnectOauthEnabled,
|
||||
},
|
||||
},
|
||||
propsData: {
|
||||
hasSubscriptions: false,
|
||||
publicKeyStorageEnabled,
|
||||
|
@ -35,20 +26,13 @@ describe('SignInPage', () => {
|
|||
};
|
||||
|
||||
it.each`
|
||||
jiraConnectOauthEnabled | publicKeyStorageEnabled | shouldRenderDotCom | shouldRenderMultiversion
|
||||
${false} | ${true} | ${true} | ${false}
|
||||
${false} | ${false} | ${true} | ${false}
|
||||
${true} | ${true} | ${false} | ${true}
|
||||
${true} | ${false} | ${true} | ${false}
|
||||
publicKeyStorageEnabled | shouldRenderDotCom | shouldRenderMultiversion
|
||||
${true} | ${false} | ${true}
|
||||
${false} | ${true} | ${false}
|
||||
`(
|
||||
'renders correct component when jiraConnectOauth is $jiraConnectOauthEnabled',
|
||||
({
|
||||
jiraConnectOauthEnabled,
|
||||
publicKeyStorageEnabled,
|
||||
shouldRenderDotCom,
|
||||
shouldRenderMultiversion,
|
||||
}) => {
|
||||
createComponent({ jiraConnectOauthEnabled, publicKeyStorageEnabled });
|
||||
'renders correct component when publicKeyStorageEnabled is $publicKeyStorageEnabled',
|
||||
({ publicKeyStorageEnabled, shouldRenderDotCom, shouldRenderMultiversion }) => {
|
||||
createComponent({ publicKeyStorageEnabled });
|
||||
|
||||
expect(findSignInGitlabCom().exists()).toBe(shouldRenderDotCom);
|
||||
expect(findSignInGitabMultiversion().exists()).toBe(shouldRenderMultiversion);
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe RemovePhabricatorFromApplicationSettings, feature_category: :importers do
|
||||
let(:settings) { table(:application_settings) }
|
||||
let(:import_sources_with_phabricator) { %w[phabricator github git bitbucket bitbucket_server] }
|
||||
let(:import_sources_without_phabricator) { %w[github git bitbucket bitbucket_server] }
|
||||
|
||||
describe "#up" do
|
||||
it 'removes phabricator and preserves existing valid import sources' do
|
||||
settings.create!(import_sources: import_sources_with_phabricator)
|
||||
|
||||
migrate!
|
||||
|
||||
expect(YAML.safe_load(ApplicationSetting.last.import_sources)).to eq(import_sources_without_phabricator)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -25,9 +25,15 @@ RSpec.describe Gitlab::GithubImport::ReschedulingMethods, feature_category: :imp
|
|||
end
|
||||
end
|
||||
|
||||
context 'with an existing project' do
|
||||
context 'with an existing project', :clean_gitlab_redis_cache do
|
||||
let(:project) { create(:project, import_url: 'https://t0ken@github.com/repo/repo.git') }
|
||||
|
||||
before do
|
||||
allow_next_instance_of(Gitlab::GithubImport::Client) do |instance|
|
||||
allow(instance).to receive(:rate_limit_resets_in).and_return(14)
|
||||
end
|
||||
end
|
||||
|
||||
it 'notifies any waiters upon successfully importing the data' do
|
||||
expect(worker)
|
||||
.to receive(:try_import)
|
||||
|
@ -57,13 +63,13 @@ RSpec.describe Gitlab::GithubImport::ReschedulingMethods, feature_category: :imp
|
|||
expect(worker)
|
||||
.not_to receive(:notify_waiter)
|
||||
|
||||
expect_next_instance_of(Gitlab::GithubImport::Client) do |instance|
|
||||
expect(instance).to receive(:rate_limit_resets_in).and_return(14)
|
||||
end
|
||||
expect(worker)
|
||||
.to receive(:object_type)
|
||||
.and_return(:pull_request)
|
||||
|
||||
expect(worker.class)
|
||||
.to receive(:perform_in)
|
||||
.with(14, project.id, { 'number' => 2 }, '123')
|
||||
.with(15, project.id, { 'number' => 2 }, '123')
|
||||
|
||||
worker.perform(project.id, { 'number' => 2 }, '123')
|
||||
end
|
||||
|
|
|
@ -50,5 +50,21 @@ RSpec.describe Gitlab::GithubImport::ImportPullRequestWorker, feature_category:
|
|||
|
||||
worker.import(project, client, hash)
|
||||
end
|
||||
|
||||
describe '#importer_class' do
|
||||
it { expect(worker.importer_class).to eq Gitlab::GithubImport::Importer::PullRequestImporter }
|
||||
end
|
||||
|
||||
describe '#representation_class' do
|
||||
it { expect(worker.representation_class).to eq Gitlab::GithubImport::Representation::PullRequest }
|
||||
end
|
||||
|
||||
describe '#object_type' do
|
||||
it { expect(worker.object_type).to eq(:pull_request) }
|
||||
end
|
||||
|
||||
describe '#parallel_import_batch' do
|
||||
it { expect(worker.parallel_import_batch).to eq({ size: 200, delay: 1.minute }) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue