summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/factories/ci/pending_builds.rb2
-rw-r--r--spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb8
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb8
-rw-r--r--spec/frontend/__helpers__/mock_dom_observer.js22
-rw-r--r--spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js2
-rw-r--r--spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap2
-rw-r--r--spec/frontend/environment.js23
-rw-r--r--spec/frontend/issue_show/components/app_spec.js3
-rw-r--r--spec/frontend/issue_show/issue_spec.js3
-rw-r--r--spec/frontend/popovers/components/popovers_spec.js9
-rw-r--r--spec/frontend/tooltips/components/tooltips_spec.js9
-rw-r--r--spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap136
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js42
-rw-r--r--spec/frontend/vue_shared/directives/autofocusonshow_spec.js3
-rw-r--r--spec/lib/gitlab/ci/parsers/security/common_spec.rb34
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/trial_short_spec.rb45
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb20
-rw-r--r--spec/lib/gitlab/usage_data_metrics_spec.rb25
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb4
-rw-r--r--spec/models/ci/pending_build_spec.rb6
-rw-r--r--spec/models/namespace_spec.rb1
-rw-r--r--spec/models/postgresql/replication_slot_spec.rb67
-rw-r--r--spec/services/namespaces/in_product_marketing_emails_service_spec.rb29
23 files changed, 314 insertions, 189 deletions
diff --git a/spec/factories/ci/pending_builds.rb b/spec/factories/ci/pending_builds.rb
index 90779ae8ab9..fbd76e07d8e 100644
--- a/spec/factories/ci/pending_builds.rb
+++ b/spec/factories/ci/pending_builds.rb
@@ -6,5 +6,7 @@ FactoryBot.define do
project
protected { build.protected }
instance_runners_enabled { true }
+ namespace { project.namespace }
+ minutes_exceeded { false }
end
end
diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
index 9e1b0135932..af5ba14e310 100644
--- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
+++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb
@@ -64,7 +64,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do
context 'when enabled after it was previously canceled' do
before do
click_button "Merge when pipeline succeeds"
- click_link "Cancel"
+ click_button "Cancel auto-merge"
wait_for_requests
@@ -87,7 +87,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do
before do
merge_request.merge_params['force_remove_source_branch'] = '0'
merge_request.save!
- click_link "Cancel"
+ click_button "Cancel auto-merge"
end
it_behaves_like 'Merge when pipeline succeeds activator'
@@ -114,7 +114,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do
end
it 'allows to cancel the automatic merge' do
- click_link "Cancel"
+ click_button "Cancel auto-merge"
expect(page).to have_button "Merge when pipeline succeeds"
@@ -124,7 +124,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do
end
it 'allows to delete source branch' do
- click_link "Delete source branch"
+ click_button "Delete source branch"
expect(page).to have_content "The source branch will be deleted"
end
diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
index 906eef775ab..2a49109d360 100644
--- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
@@ -151,7 +151,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when detached merge request pipeline is pending' do
it 'waits the head pipeline' do
expect(page).to have_content('to be merged automatically when the pipeline succeeds')
- expect(page).to have_link('Cancel')
+ expect(page).to have_button('Cancel auto-merge')
end
end
@@ -178,7 +178,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'waits the head pipeline' do
expect(page).to have_content('to be merged automatically when the pipeline succeeds')
- expect(page).to have_link('Cancel')
+ expect(page).to have_button('Cancel auto-merge')
end
end
end
@@ -377,7 +377,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
context 'when detached merge request pipeline is pending' do
it 'waits the head pipeline' do
expect(page).to have_content('to be merged automatically when the pipeline succeeds')
- expect(page).to have_link('Cancel')
+ expect(page).to have_button('Cancel auto-merge')
end
end
@@ -403,7 +403,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
it 'waits the head pipeline' do
expect(page).to have_content('to be merged automatically when the pipeline succeeds')
- expect(page).to have_link('Cancel')
+ expect(page).to have_button('Cancel auto-merge')
end
end
end
diff --git a/spec/frontend/__helpers__/mock_dom_observer.js b/spec/frontend/__helpers__/mock_dom_observer.js
index 1b93b81535d..dd26b594ad9 100644
--- a/spec/frontend/__helpers__/mock_dom_observer.js
+++ b/spec/frontend/__helpers__/mock_dom_observer.js
@@ -52,7 +52,7 @@ class MockIntersectionObserver extends MockObserver {
* const { trigger: triggerMutate } = useMockMutationObserver();
*
* it('test', () => {
- * trigger(el, { options: { childList: true }, entry: { } });
+ * triggerMutate(el, { options: { childList: true }, entry: { } });
* });
* })
* ```
@@ -60,33 +60,31 @@ class MockIntersectionObserver extends MockObserver {
* @param {String} key
*/
const useMockObserver = (key, createMock) => {
- let mockObserver;
+ let mockObservers = [];
let origObserver;
beforeEach(() => {
origObserver = global[key];
global[key] = jest.fn().mockImplementation((...args) => {
- mockObserver = createMock(...args);
+ const mockObserver = createMock(...args);
+ mockObservers.push(mockObserver);
return mockObserver;
});
});
afterEach(() => {
- mockObserver = null;
+ mockObservers.forEach((x) => x.disconnect());
+ mockObservers = [];
global[key] = origObserver;
});
const trigger = (...args) => {
- if (!mockObserver) {
- return;
- }
-
- mockObserver.$_triggerObserve(...args);
+ mockObservers.forEach((observer) => {
+ observer.$_triggerObserve(...args);
+ });
};
- const observersCount = () => mockObserver.$_observers.length;
-
- return { trigger, observersCount };
+ return { trigger };
};
export const useMockIntersectionObserver = () =>
diff --git a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
index 1c4dde39585..e6a6e01c41c 100644
--- a/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
+++ b/spec/frontend/alerts_settings/components/alerts_settings_wrapper_spec.js
@@ -6,7 +6,6 @@ import VueApollo from 'vue-apollo';
import createHttpIntegrationMutation from 'ee_else_ce/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql';
import updateHttpIntegrationMutation from 'ee_else_ce/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
-import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
@@ -57,7 +56,6 @@ describe('AlertsSettingsWrapper', () => {
let wrapper;
let fakeApollo;
let destroyIntegrationHandler;
- useMockIntersectionObserver();
const httpMappingData = {
payloadExample: '{"test: : "field"}',
diff --git a/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap b/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap
index 03ae77d4977..57023c55878 100644
--- a/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap
+++ b/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap
@@ -61,6 +61,7 @@ exports[`Design management design index page renders design index 1`] = `
<participants-stub
class="gl-mb-4"
+ lazy="true"
numberoflessparticipants="7"
participants="[object Object]"
/>
@@ -221,6 +222,7 @@ exports[`Design management design index page with error GlAlert is rendered in c
<participants-stub
class="gl-mb-4"
+ lazy="true"
numberoflessparticipants="7"
participants="[object Object]"
/>
diff --git a/spec/frontend/environment.js b/spec/frontend/environment.js
index 29aa416149c..cf47a1cd7bb 100644
--- a/spec/frontend/environment.js
+++ b/spec/frontend/environment.js
@@ -88,13 +88,32 @@ class CustomEnvironment extends JSDOMEnvironment {
}),
});
- this.global.PerformanceObserver = class {
+ /**
+ * JSDom doesn't have an own observer implementation, so this a Noop Observer.
+ * If you are testing functionality, related to observers, have a look at __helpers__/mock_dom_observer.js
+ *
+ * JSDom actually implements a _proper_ MutationObserver, so no need to mock it!
+ */
+ class NoopObserver {
/* eslint-disable no-useless-constructor, no-unused-vars, no-empty-function, class-methods-use-this */
constructor(callback) {}
disconnect() {}
observe(element, initObject) {}
+ unobserve(element) {}
+ takeRecords() {
+ return [];
+ }
/* eslint-enable no-useless-constructor, no-unused-vars, no-empty-function, class-methods-use-this */
- };
+ }
+
+ ['IntersectionObserver', 'PerformanceObserver', 'ResizeObserver'].forEach((observer) => {
+ if (this.global[observer]) {
+ throw new Error(
+ `We overwrite an existing Observer in jsdom (${observer}), are you sure you want to do that?`,
+ );
+ }
+ this.global[observer] = NoopObserver;
+ });
}
async teardown() {
diff --git a/spec/frontend/issue_show/components/app_spec.js b/spec/frontend/issue_show/components/app_spec.js
index 4c06f2dca1b..babe3a66578 100644
--- a/spec/frontend/issue_show/components/app_spec.js
+++ b/spec/frontend/issue_show/components/app_spec.js
@@ -2,7 +2,6 @@ import { GlIntersectionObserver } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
-import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
import '~/behaviors/markdown/render_gfm';
import IssuableApp from '~/issue_show/components/app.vue';
import DescriptionComponent from '~/issue_show/components/description.vue';
@@ -30,8 +29,6 @@ jest.mock('~/issue_show/event_hub');
const REALTIME_REQUEST_STACK = [initialRequest, secondRequest];
describe('Issuable output', () => {
- useMockIntersectionObserver();
-
let mock;
let realtimeRequestCount = 0;
let wrapper;
diff --git a/spec/frontend/issue_show/issue_spec.js b/spec/frontend/issue_show/issue_spec.js
index d043693b863..76989413edb 100644
--- a/spec/frontend/issue_show/issue_spec.js
+++ b/spec/frontend/issue_show/issue_spec.js
@@ -1,5 +1,4 @@
import MockAdapter from 'axios-mock-adapter';
-import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
import waitForPromises from 'helpers/wait_for_promises';
import { initIssuableApp } from '~/issue_show/issue';
import * as parseData from '~/issue_show/utils/parse_data';
@@ -10,8 +9,6 @@ import { appProps } from './mock_data/mock_data';
const mock = new MockAdapter(axios);
mock.onGet().reply(200);
-useMockIntersectionObserver();
-
jest.mock('~/lib/utils/poll');
const setupHTML = (initialData) => {
diff --git a/spec/frontend/popovers/components/popovers_spec.js b/spec/frontend/popovers/components/popovers_spec.js
index 0c164d97564..25c509346d1 100644
--- a/spec/frontend/popovers/components/popovers_spec.js
+++ b/spec/frontend/popovers/components/popovers_spec.js
@@ -4,7 +4,7 @@ import { useMockMutationObserver } from 'helpers/mock_dom_observer';
import Popovers from '~/popovers/components/popovers.vue';
describe('popovers/components/popovers.vue', () => {
- const { trigger: triggerMutate, observersCount } = useMockMutationObserver();
+ const { trigger: triggerMutate } = useMockMutationObserver();
let wrapper;
const buildWrapper = (...targets) => {
@@ -120,10 +120,13 @@ describe('popovers/components/popovers.vue', () => {
it('disconnects mutation observer on beforeDestroy', async () => {
await buildWrapper(createPopoverTarget());
+ const { observer } = wrapper.vm;
+ jest.spyOn(observer, 'disconnect');
- expect(observersCount()).toBe(1);
+ expect(observer.disconnect).toHaveBeenCalledTimes(0);
wrapper.destroy();
- expect(observersCount()).toBe(0);
+
+ expect(observer.disconnect).toHaveBeenCalledTimes(1);
});
});
diff --git a/spec/frontend/tooltips/components/tooltips_spec.js b/spec/frontend/tooltips/components/tooltips_spec.js
index c44918ceaf3..9b703b74a1a 100644
--- a/spec/frontend/tooltips/components/tooltips_spec.js
+++ b/spec/frontend/tooltips/components/tooltips_spec.js
@@ -4,7 +4,7 @@ import { useMockMutationObserver } from 'helpers/mock_dom_observer';
import Tooltips from '~/tooltips/components/tooltips.vue';
describe('tooltips/components/tooltips.vue', () => {
- const { trigger: triggerMutate, observersCount } = useMockMutationObserver();
+ const { trigger: triggerMutate } = useMockMutationObserver();
let wrapper;
const buildWrapper = () => {
@@ -211,11 +211,14 @@ describe('tooltips/components/tooltips.vue', () => {
it('disconnects mutation observer on beforeDestroy', () => {
buildWrapper();
wrapper.vm.addTooltips([createTooltipTarget()]);
+ const { observer } = wrapper.vm;
+ jest.spyOn(observer, 'disconnect');
- expect(observersCount()).toBe(1);
+ expect(observer.disconnect).toHaveBeenCalledTimes(0);
wrapper.destroy();
- expect(observersCount()).toBe(0);
+
+ expect(observer.disconnect).toHaveBeenCalledTimes(1);
});
it('exposes hidden event', async () => {
diff --git a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
index ac20487c55f..5981d2d7849 100644
--- a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
+++ b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
@@ -4,8 +4,10 @@ exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have
<div
class="mr-widget-body media"
>
- <status-icon-stub
- status="success"
+ <gl-icon-stub
+ class="gl-text-blue-500 gl-mr-3 gl-mt-1"
+ name="status_scheduled"
+ size="24"
/>
<div
@@ -17,55 +19,31 @@ exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have
<span
class="gl-mr-3"
>
- <span
- class="js-status-text-before-author"
- data-testid="beforeStatusText"
- >
- Set by
- </span>
-
- <mr-widget-author-stub
- author="[object Object]"
- showauthorname="true"
+ <gl-sprintf-stub
+ data-testid="statusText"
+ message="Set by %{merge_author} to be merged automatically when the pipeline succeeds"
/>
-
- <span
- class="js-status-text-after-author"
- data-testid="afterStatusText"
- >
- to be merged automatically when the pipeline succeeds
- </span>
</span>
- <a
- class="btn btn-sm btn-default js-cancel-auto-merge"
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
+ class="js-cancel-auto-merge"
data-qa-selector="cancel_auto_merge_button"
data-testid="cancelAutomaticMergeButton"
- href="#"
- role="button"
+ icon=""
+ size="small"
+ variant="default"
>
- <!---->
- Cancel
+ Cancel auto-merge
- </a>
+ </gl-button-stub>
</h4>
<section
class="mr-info-list"
>
- <p>
-
- The changes will be merged into
-
- <a
- class="label-branch"
- href="/foo/bar"
- >
- foo
- </a>
- </p>
-
<p
class="gl-display-flex"
>
@@ -75,17 +53,19 @@ exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have
The source branch will not be deleted
</span>
- <a
- class="btn btn-sm btn-default js-remove-source-branch"
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
+ class="js-remove-source-branch"
data-testid="removeSourceBranchButton"
- href="#"
- role="button"
+ icon=""
+ size="small"
+ variant="default"
>
- <!---->
Delete source branch
- </a>
+ </gl-button-stub>
</p>
</section>
</div>
@@ -96,8 +76,10 @@ exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have c
<div
class="mr-widget-body media"
>
- <status-icon-stub
- status="success"
+ <gl-icon-stub
+ class="gl-text-blue-500 gl-mr-3 gl-mt-1"
+ name="status_scheduled"
+ size="24"
/>
<div
@@ -109,55 +91,31 @@ exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have c
<span
class="gl-mr-3"
>
- <span
- class="js-status-text-before-author"
- data-testid="beforeStatusText"
- >
- Set by
- </span>
-
- <mr-widget-author-stub
- author="[object Object]"
- showauthorname="true"
+ <gl-sprintf-stub
+ data-testid="statusText"
+ message="Set by %{merge_author} to be merged automatically when the pipeline succeeds"
/>
-
- <span
- class="js-status-text-after-author"
- data-testid="afterStatusText"
- >
- to be merged automatically when the pipeline succeeds
- </span>
</span>
- <a
- class="btn btn-sm btn-default js-cancel-auto-merge"
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
+ class="js-cancel-auto-merge"
data-qa-selector="cancel_auto_merge_button"
data-testid="cancelAutomaticMergeButton"
- href="#"
- role="button"
+ icon=""
+ size="small"
+ variant="default"
>
- <!---->
- Cancel
+ Cancel auto-merge
- </a>
+ </gl-button-stub>
</h4>
<section
class="mr-info-list"
>
- <p>
-
- The changes will be merged into
-
- <a
- class="label-branch"
- href="/foo/bar"
- >
- foo
- </a>
- </p>
-
<p
class="gl-display-flex"
>
@@ -167,17 +125,19 @@ exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have c
The source branch will not be deleted
</span>
- <a
- class="btn btn-sm btn-default js-remove-source-branch"
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
+ class="js-remove-source-branch"
data-testid="removeSourceBranchButton"
- href="#"
- role="button"
+ icon=""
+ size="small"
+ variant="default"
>
- <!---->
Delete source branch
- </a>
+ </gl-button-stub>
</p>
</section>
</div>
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
index 0110a76e722..4c1534574f5 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
@@ -72,6 +72,8 @@ const defaultMrProps = () => ({
autoMergeStrategy: MWPS_MERGE_STRATEGY,
});
+const getStatusText = () => wrapper.findByTestId('statusText').attributes('message');
+
describe('MRWidgetAutoMergeEnabled', () => {
let oldWindowGl;
@@ -167,30 +169,6 @@ describe('MRWidgetAutoMergeEnabled', () => {
});
});
- describe('statusTextBeforeAuthor', () => {
- it('should return "Set by" if the MWPS is selected', () => {
- factory({
- ...defaultMrProps(),
- autoMergeStrategy: MWPS_MERGE_STRATEGY,
- });
-
- expect(wrapper.findByTestId('beforeStatusText').text()).toBe('Set by');
- });
- });
-
- describe('statusTextAfterAuthor', () => {
- it('should return "to be merged automatically..." if MWPS is selected', () => {
- factory({
- ...defaultMrProps(),
- autoMergeStrategy: MWPS_MERGE_STRATEGY,
- });
-
- expect(wrapper.findByTestId('afterStatusText').text()).toBe(
- 'to be merged automatically when the pipeline succeeds',
- );
- });
- });
-
describe('cancelButtonText', () => {
it('should return "Cancel" if MWPS is selected', () => {
factory({
@@ -198,7 +176,9 @@ describe('MRWidgetAutoMergeEnabled', () => {
autoMergeStrategy: MWPS_MERGE_STRATEGY,
});
- expect(wrapper.findByTestId('cancelAutomaticMergeButton').text()).toBe('Cancel');
+ expect(wrapper.findByTestId('cancelAutomaticMergeButton').text()).toBe(
+ 'Cancel auto-merge',
+ );
});
});
});
@@ -279,7 +259,7 @@ describe('MRWidgetAutoMergeEnabled', () => {
await nextTick();
- expect(wrapper.find('.js-cancel-auto-merge').attributes('disabled')).toBe('disabled');
+ expect(wrapper.find('.js-cancel-auto-merge').props('loading')).toBe(true);
});
it('should show source branch will be deleted text when it source branch set to remove', () => {
@@ -313,7 +293,7 @@ describe('MRWidgetAutoMergeEnabled', () => {
await nextTick();
- expect(wrapper.find('.js-remove-source-branch').attributes('disabled')).toBe('disabled');
+ expect(wrapper.find('.js-remove-source-branch').props('loading')).toBe(true);
});
it('should render the status text as "...to merged automatically" if MWPS is selected', () => {
@@ -322,9 +302,9 @@ describe('MRWidgetAutoMergeEnabled', () => {
autoMergeStrategy: MWPS_MERGE_STRATEGY,
});
- const statusText = trimText(wrapper.find('.js-status-text-after-author').text());
-
- expect(statusText).toBe('to be merged automatically when the pipeline succeeds');
+ expect(getStatusText()).toBe(
+ 'Set by %{merge_author} to be merged automatically when the pipeline succeeds',
+ );
});
it('should render the cancel button as "Cancel" if MWPS is selected', () => {
@@ -335,7 +315,7 @@ describe('MRWidgetAutoMergeEnabled', () => {
const cancelButtonText = trimText(wrapper.find('.js-cancel-auto-merge').text());
- expect(cancelButtonText).toBe('Cancel');
+ expect(cancelButtonText).toBe('Cancel auto-merge');
});
});
});
diff --git a/spec/frontend/vue_shared/directives/autofocusonshow_spec.js b/spec/frontend/vue_shared/directives/autofocusonshow_spec.js
index 1c9e89f99e9..59ce9f086c3 100644
--- a/spec/frontend/vue_shared/directives/autofocusonshow_spec.js
+++ b/spec/frontend/vue_shared/directives/autofocusonshow_spec.js
@@ -1,4 +1,3 @@
-import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
/**
@@ -7,8 +6,6 @@ import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
* on underlying DOM methods.
*/
describe('AutofocusOnShow directive', () => {
- useMockIntersectionObserver();
-
describe('with input invisible on component render', () => {
let el;
diff --git a/spec/lib/gitlab/ci/parsers/security/common_spec.rb b/spec/lib/gitlab/ci/parsers/security/common_spec.rb
index 35eba4cacf4..c6387bf615b 100644
--- a/spec/lib/gitlab/ci/parsers/security/common_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/security/common_spec.rb
@@ -99,42 +99,42 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
context 'when message is provided' do
it 'sets message from the report as a finding name' do
- vulnerability = report.findings.find { |x| x.compare_key == 'CVE-1020' }
- expected_name = Gitlab::Json.parse(vulnerability.raw_metadata)['message']
+ finding = report.findings.find { |x| x.compare_key == 'CVE-1020' }
+ expected_name = Gitlab::Json.parse(finding.raw_metadata)['message']
- expect(vulnerability.name).to eq(expected_name)
+ expect(finding.name).to eq(expected_name)
end
end
context 'when message is not provided' do
context 'and name is provided' do
it 'sets name from the report as a name' do
- vulnerability = report.findings.find { |x| x.compare_key == 'CVE-1030' }
- expected_name = Gitlab::Json.parse(vulnerability.raw_metadata)['name']
+ finding = report.findings.find { |x| x.compare_key == 'CVE-1030' }
+ expected_name = Gitlab::Json.parse(finding.raw_metadata)['name']
- expect(vulnerability.name).to eq(expected_name)
+ expect(finding.name).to eq(expected_name)
end
end
context 'and name is not provided' do
context 'when CVE identifier exists' do
it 'combines identifier with location to create name' do
- vulnerability = report.findings.find { |x| x.compare_key == 'CVE-2017-11429' }
- expect(vulnerability.name).to eq("CVE-2017-11429 in yarn.lock")
+ finding = report.findings.find { |x| x.compare_key == 'CVE-2017-11429' }
+ expect(finding.name).to eq("CVE-2017-11429 in yarn.lock")
end
end
context 'when CWE identifier exists' do
it 'combines identifier with location to create name' do
- vulnerability = report.findings.find { |x| x.compare_key == 'CWE-2017-11429' }
- expect(vulnerability.name).to eq("CWE-2017-11429 in yarn.lock")
+ finding = report.findings.find { |x| x.compare_key == 'CWE-2017-11429' }
+ expect(finding.name).to eq("CWE-2017-11429 in yarn.lock")
end
end
context 'when neither CVE nor CWE identifier exist' do
it 'combines identifier with location to create name' do
- vulnerability = report.findings.find { |x| x.compare_key == 'OTHER-2017-11429' }
- expect(vulnerability.name).to eq("other-2017-11429 in yarn.lock")
+ finding = report.findings.find { |x| x.compare_key == 'OTHER-2017-11429' }
+ expect(finding.name).to eq("other-2017-11429 in yarn.lock")
end
end
end
@@ -144,17 +144,17 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
describe 'parsing finding.details' do
context 'when details are provided' do
it 'sets details from the report' do
- vulnerability = report.findings.find { |x| x.compare_key == 'CVE-1020' }
- expected_details = Gitlab::Json.parse(vulnerability.raw_metadata)['details']
+ finding = report.findings.find { |x| x.compare_key == 'CVE-1020' }
+ expected_details = Gitlab::Json.parse(finding.raw_metadata)['details']
- expect(vulnerability.details).to eq(expected_details)
+ expect(finding.details).to eq(expected_details)
end
end
context 'when details are not provided' do
it 'sets empty hash' do
- vulnerability = report.findings.find { |x| x.compare_key == 'CVE-1030' }
- expect(vulnerability.details).to eq({})
+ finding = report.findings.find { |x| x.compare_key == 'CVE-1030' }
+ expect(finding.details).to eq({})
end
end
end
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/trial_short_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/trial_short_spec.rb
new file mode 100644
index 00000000000..ebad4672eb3
--- /dev/null
+++ b/spec/lib/gitlab/email/message/in_product_marketing/trial_short_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Email::Message::InProductMarketing::TrialShort do
+ let_it_be(:group) { build(:group) }
+ let_it_be(:user) { build(:user) }
+
+ let(:series) { 0 }
+
+ subject(:message) { described_class.new(group: group, user: user, series: series)}
+
+ describe 'public methods' do
+ it 'returns value for series', :aggregate_failures do
+ expect(message.subject_line).to eq 'Be a DevOps hero'
+ expect(message.tagline).to be_nil
+ expect(message.title).to eq 'Expand your DevOps journey with a free GitLab trial'
+ expect(message.subtitle).to eq 'Start your trial today to experience single application success and discover all the features of GitLab Ultimate for free!'
+ expect(message.body_line1).to be_empty
+ expect(message.body_line2).to be_empty
+ expect(message.cta_text).to eq 'Start a trial'
+ expect(message.logo_path).to eq 'mailers/in_product_marketing/trial-0.png'
+ end
+
+ describe '#progress' do
+ subject { message.progress }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(is_gitlab_com)
+ end
+
+ context 'on gitlab.com' do
+ let(:is_gitlab_com) { true }
+
+ it { is_expected.to eq('This is email 1 of 4 in the Trial series.') }
+ end
+
+ context 'not on gitlab.com' do
+ let(:is_gitlab_com) { false }
+
+ it { is_expected.to include('This is email 1 of 4 in the Trial series', Gitlab::Routing.url_helpers.profile_notifications_url) }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb
index 5f7639a9ed6..3e18b8e35b6 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb
@@ -23,6 +23,26 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Trial do
expect(message.body_line2).to be_present
expect(message.cta_text).to be_present
end
+
+ describe '#progress' do
+ subject { message.progress }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(is_gitlab_com)
+ end
+
+ context 'on gitlab.com' do
+ let(:is_gitlab_com) { true }
+
+ it { is_expected.to eq("This is email #{series + 2} of 4 in the Trial series.") }
+ end
+
+ context 'not on gitlab.com' do
+ let(:is_gitlab_com) { false }
+
+ it { is_expected.to include("This is email #{series + 2} of 4 in the Trial series", Gitlab::Routing.url_helpers.profile_notifications_url) }
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/usage_data_metrics_spec.rb b/spec/lib/gitlab/usage_data_metrics_spec.rb
index bcf14d8ea4d..59ceaeaf6de 100644
--- a/spec/lib/gitlab/usage_data_metrics_spec.rb
+++ b/spec/lib/gitlab/usage_data_metrics_spec.rb
@@ -41,6 +41,31 @@ RSpec.describe Gitlab::UsageDataMetrics do
])
end
+ it 'includes incident_management_alerts monthly and weekly keys' do
+ expect(subject[:redis_hll_counters][:incident_management_alerts].keys).to contain_exactly(*[
+ :incident_management_alert_create_incident_monthly, :incident_management_alert_create_incident_weekly
+ ])
+ end
+
+ it 'includes incident_management monthly and weekly keys' do
+ expect(subject[:redis_hll_counters][:incident_management]).to include(
+ :incident_management_incident_created_monthly, :incident_management_incident_created_weekly,
+ :incident_management_incident_reopened_monthly, :incident_management_incident_reopened_weekly,
+ :incident_management_incident_closed_monthly, :incident_management_incident_closed_weekly,
+ :incident_management_incident_assigned_monthly, :incident_management_incident_assigned_weekly,
+ :incident_management_incident_todo_monthly, :incident_management_incident_todo_weekly,
+ :incident_management_incident_comment_monthly, :incident_management_incident_comment_weekly,
+ :incident_management_incident_zoom_meeting_monthly, :incident_management_incident_zoom_meeting_weekly,
+ :incident_management_incident_relate_monthly, :incident_management_incident_relate_weekly,
+ :incident_management_incident_unrelate_monthly, :incident_management_incident_unrelate_weekly,
+ :incident_management_incident_change_confidential_monthly, :incident_management_incident_change_confidential_weekly,
+ :incident_management_alert_status_changed_monthly, :incident_management_alert_status_changed_weekly,
+ :incident_management_alert_assigned_monthly, :incident_management_alert_assigned_weekly,
+ :incident_management_alert_todo_monthly, :incident_management_alert_todo_weekly,
+ :incident_management_total_unique_counts_monthly, :incident_management_total_unique_counts_weekly
+ )
+ end
+
it 'includes source_code monthly and weekly keys' do
expect(subject[:redis_hll_counters][:source_code].keys).to contain_exactly(*[
:wiki_action_monthly, :wiki_action_weekly,
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 556b65679bb..6fd25571c6e 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -1361,6 +1361,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
"in_product_marketing_email_create_2_cta_clicked" => -1,
"in_product_marketing_email_team_short_0_sent" => -1,
"in_product_marketing_email_team_short_0_cta_clicked" => -1,
+ "in_product_marketing_email_trial_short_0_sent" => -1,
+ "in_product_marketing_email_trial_short_0_cta_clicked" => -1,
"in_product_marketing_email_verify_0_sent" => -1,
"in_product_marketing_email_verify_0_cta_clicked" => -1,
"in_product_marketing_email_verify_1_sent" => -1,
@@ -1402,6 +1404,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
"in_product_marketing_email_create_2_cta_clicked" => 0,
"in_product_marketing_email_team_short_0_sent" => 0,
"in_product_marketing_email_team_short_0_cta_clicked" => 0,
+ "in_product_marketing_email_trial_short_0_sent" => 0,
+ "in_product_marketing_email_trial_short_0_cta_clicked" => 0,
"in_product_marketing_email_verify_0_sent" => 1,
"in_product_marketing_email_verify_0_cta_clicked" => 0,
"in_product_marketing_email_verify_1_sent" => 0,
diff --git a/spec/models/ci/pending_build_spec.rb b/spec/models/ci/pending_build_spec.rb
index b64f3999232..211caebdf70 100644
--- a/spec/models/ci/pending_build_spec.rb
+++ b/spec/models/ci/pending_build_spec.rb
@@ -8,6 +8,12 @@ RSpec.describe Ci::PendingBuild do
let(:build) { create(:ci_build, :created, pipeline: pipeline) }
+ describe 'associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to belong_to :build }
+ it { is_expected.to belong_to :namespace }
+ end
+
describe '.upsert_from_build!' do
context 'another pending entry does not exist' do
it 'creates a new pending entry' do
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 3f626fb3fce..e2700378f5f 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -23,6 +23,7 @@ RSpec.describe Namespace do
it { is_expected.to have_one :package_setting_relation }
it { is_expected.to have_one :onboarding_progress }
it { is_expected.to have_one :admin_note }
+ it { is_expected.to have_many :pending_builds }
end
describe 'validations' do
diff --git a/spec/models/postgresql/replication_slot_spec.rb b/spec/models/postgresql/replication_slot_spec.rb
index 4bad8a3f0c0..c3b67a2e7b8 100644
--- a/spec/models/postgresql/replication_slot_spec.rb
+++ b/spec/models/postgresql/replication_slot_spec.rb
@@ -60,4 +60,71 @@ RSpec.describe Postgresql::ReplicationSlot do
expect(described_class.lag_too_great?).to eq(false)
end
end
+
+ describe '#max_replication_slots' do
+ it 'returns the maximum number of replication slots' do
+ expect(described_class.max_replication_slots).to be >= 0
+ end
+ end
+
+ context 'with enough slots available' do
+ skip_examples = described_class.max_replication_slots <= described_class.count
+
+ before(:all) do
+ skip('max_replication_slots too small') if skip_examples
+
+ @current_slot_count = ApplicationRecord
+ .connection
+ .execute("SELECT COUNT(*) FROM pg_replication_slots;")
+ .first
+ .fetch('count')
+ .to_i
+
+ @current_unused_count = ApplicationRecord
+ .connection
+ .execute("SELECT COUNT(*) FROM pg_replication_slots WHERE active = 'f';")
+ .first
+ .fetch('count')
+ .to_i
+
+ ApplicationRecord
+ .connection
+ .execute("SELECT * FROM pg_create_physical_replication_slot('test_slot');")
+ end
+
+ after(:all) do
+ unless skip_examples
+ ApplicationRecord
+ .connection
+ .execute("SELECT pg_drop_replication_slot('test_slot');")
+ end
+ end
+
+ describe '#slots_count' do
+ it 'returns the number of replication slots' do
+ expect(described_class.count).to eq(@current_slot_count + 1)
+ end
+ end
+
+ describe '#unused_slots_count' do
+ it 'returns the number of unused replication slots' do
+ expect(described_class.unused_slots_count).to eq(@current_unused_count + 1)
+ end
+ end
+
+ describe '#max_retained_wal' do
+ it 'returns the retained WAL size' do
+ expect(described_class.max_retained_wal).not_to be_nil
+ end
+ end
+
+ describe '#slots_retained_bytes' do
+ it 'returns the number of retained bytes' do
+ slot = described_class.slots_retained_bytes.find {|x| x['slot_name'] == 'test_slot' }
+
+ expect(slot).not_to be_nil
+ expect(slot['retained_bytes']).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/services/namespaces/in_product_marketing_emails_service_spec.rb b/spec/services/namespaces/in_product_marketing_emails_service_spec.rb
index 3f2611d90ee..6857b842d5a 100644
--- a/spec/services/namespaces/in_product_marketing_emails_service_spec.rb
+++ b/spec/services/namespaces/in_product_marketing_emails_service_spec.rb
@@ -39,20 +39,21 @@ RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
using RSpec::Parameterized::TableSyntax
where(:track, :interval, :actions_completed) do
- :create | 1 | { created_at: frozen_time - 2.days }
- :create | 5 | { created_at: frozen_time - 6.days }
- :create | 10 | { created_at: frozen_time - 11.days }
- :team_short | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days }
- :verify | 2 | { created_at: frozen_time - 3.days, git_write_at: frozen_time - 3.days }
- :verify | 6 | { created_at: frozen_time - 7.days, git_write_at: frozen_time - 7.days }
- :verify | 11 | { created_at: frozen_time - 12.days, git_write_at: frozen_time - 12.days }
- :trial | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days, pipeline_created_at: frozen_time - 2.days }
- :trial | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days, pipeline_created_at: frozen_time - 6.days }
- :trial | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days, pipeline_created_at: frozen_time - 11.days }
- :team | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days, pipeline_created_at: frozen_time - 2.days, trial_started_at: frozen_time - 2.days }
- :team | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days, pipeline_created_at: frozen_time - 6.days, trial_started_at: frozen_time - 6.days }
- :team | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days, pipeline_created_at: frozen_time - 11.days, trial_started_at: frozen_time - 11.days }
- :experience | 30 | { created_at: frozen_time - 31.days, git_write_at: frozen_time - 31.days }
+ :create | 1 | { created_at: frozen_time - 2.days }
+ :create | 5 | { created_at: frozen_time - 6.days }
+ :create | 10 | { created_at: frozen_time - 11.days }
+ :team_short | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days }
+ :trial_short | 2 | { created_at: frozen_time - 3.days, git_write_at: frozen_time - 3.days }
+ :verify | 3 | { created_at: frozen_time - 4.days, git_write_at: frozen_time - 4.days }
+ :verify | 7 | { created_at: frozen_time - 8.days, git_write_at: frozen_time - 8.days }
+ :verify | 12 | { created_at: frozen_time - 13.days, git_write_at: frozen_time - 13.days }
+ :trial | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days, pipeline_created_at: frozen_time - 2.days }
+ :trial | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days, pipeline_created_at: frozen_time - 6.days }
+ :trial | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days, pipeline_created_at: frozen_time - 11.days }
+ :team | 1 | { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days, pipeline_created_at: frozen_time - 2.days, trial_started_at: frozen_time - 2.days }
+ :team | 5 | { created_at: frozen_time - 6.days, git_write_at: frozen_time - 6.days, pipeline_created_at: frozen_time - 6.days, trial_started_at: frozen_time - 6.days }
+ :team | 10 | { created_at: frozen_time - 11.days, git_write_at: frozen_time - 11.days, pipeline_created_at: frozen_time - 11.days, trial_started_at: frozen_time - 11.days }
+ :experience | 30 | { created_at: frozen_time - 31.days, git_write_at: frozen_time - 31.days }
end
with_them do