Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
83a9f472b8
commit
9b984f55ee
37 changed files with 226 additions and 166 deletions
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { flatten, isNumber } from 'underscore';
|
||||
import { flattenDeep, isNumber } from 'lodash';
|
||||
import { GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
|
||||
import { roundOffFloat } from '~/lib/utils/common_utils';
|
||||
import { hexToRgb } from '~/lib/utils/color_utils';
|
||||
|
@ -77,7 +77,7 @@ export default {
|
|||
* This offset is the lowest value.
|
||||
*/
|
||||
yOffset() {
|
||||
const values = flatten(this.series.map(ser => ser.data.map(([, y]) => y)));
|
||||
const values = flattenDeep(this.series.map(ser => ser.data.map(([, y]) => y)));
|
||||
const min = values.length ? Math.floor(Math.min(...values)) : 0;
|
||||
return min < 0 ? -min : 0;
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import { omit } from 'lodash';
|
||||
import { GlLink, GlButton, GlTooltip, GlResizeObserverDirective } from '@gitlab/ui';
|
||||
import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
|
||||
import dateFormat from 'dateformat';
|
||||
|
@ -140,7 +140,7 @@ export default {
|
|||
return (this.option.series || []).concat(this.scatterSeries ? [this.scatterSeries] : []);
|
||||
},
|
||||
chartOptions() {
|
||||
const option = _.omit(this.option, 'series');
|
||||
const option = omit(this.option, 'series');
|
||||
return {
|
||||
series: this.chartOptionSeries,
|
||||
xAxis: {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import { debounce, pickBy } from 'lodash';
|
||||
import { mapActions, mapState, mapGetters } from 'vuex';
|
||||
import VueDraggable from 'vuedraggable';
|
||||
import {
|
||||
|
@ -15,12 +15,13 @@ import {
|
|||
import PanelType from 'ee_else_ce/monitoring/components/panel_type.vue';
|
||||
import { s__ } from '~/locale';
|
||||
import createFlash from '~/flash';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import { getParameterValues, mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
|
||||
import invalidUrl from '~/lib/utils/invalid_url';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import { getTimeRange } from '~/vue_shared/components/date_time_picker/date_time_picker_lib';
|
||||
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
|
||||
|
||||
import DateTimePicker from './date_time_picker/date_time_picker.vue';
|
||||
import GraphGroup from './graph_group.vue';
|
||||
import EmptyState from './empty_state.vue';
|
||||
import GroupEmptyState from './group_empty_state.vue';
|
||||
|
@ -28,11 +29,10 @@ import DashboardsDropdown from './dashboards_dropdown.vue';
|
|||
|
||||
import TrackEventDirective from '~/vue_shared/directives/track_event';
|
||||
import { getAddMetricTrackingOptions } from '../utils';
|
||||
import { getTimeRange } from './date_time_picker/date_time_picker_lib';
|
||||
|
||||
import { datePickerTimeWindows, metricStates } from '../constants';
|
||||
|
||||
const defaultTimeDiff = getTimeRange();
|
||||
const defaultTimeRange = getTimeRange();
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -190,8 +190,8 @@ export default {
|
|||
return {
|
||||
state: 'gettingStarted',
|
||||
formIsValid: null,
|
||||
startDate: getParameterValues('start')[0] || defaultTimeDiff.start,
|
||||
endDate: getParameterValues('end')[0] || defaultTimeDiff.end,
|
||||
startDate: getParameterValues('start')[0] || defaultTimeRange.start,
|
||||
endDate: getParameterValues('end')[0] || defaultTimeRange.end,
|
||||
hasValidDates: true,
|
||||
datePickerTimeWindows,
|
||||
isRearrangingPanels: false,
|
||||
|
@ -288,13 +288,13 @@ export default {
|
|||
'Metrics|Link contains an invalid time window, please verify the link to see the requested time range.',
|
||||
),
|
||||
);
|
||||
this.startDate = defaultTimeDiff.start;
|
||||
this.endDate = defaultTimeDiff.end;
|
||||
this.startDate = defaultTimeRange.start;
|
||||
this.endDate = defaultTimeRange.end;
|
||||
},
|
||||
|
||||
generateLink(group, title, yLabel) {
|
||||
const dashboard = this.currentDashboard || this.firstDashboard.path;
|
||||
const params = _.pick({ dashboard, group, title, y_label: yLabel }, value => value != null);
|
||||
const params = pickBy({ dashboard, group, title, y_label: yLabel }, value => value != null);
|
||||
return mergeUrlParams(params, window.location.href);
|
||||
},
|
||||
hideAddMetricModal() {
|
||||
|
@ -306,7 +306,7 @@ export default {
|
|||
setFormValidity(isValid) {
|
||||
this.formIsValid = isValid;
|
||||
},
|
||||
debouncedEnvironmentsSearch: _.debounce(function environmentsSearchOnInput(searchTerm) {
|
||||
debouncedEnvironmentsSearch: debounce(function environmentsSearchOnInput(searchTerm) {
|
||||
this.setEnvironmentsSearchTerm(searchTerm);
|
||||
}, 500),
|
||||
submitCustomMetricsForm() {
|
||||
|
@ -427,6 +427,7 @@ export default {
|
|||
class="col-sm-6 col-md-6 col-lg-4"
|
||||
>
|
||||
<date-time-picker
|
||||
ref="dateTimePicker"
|
||||
:start="startDate"
|
||||
:end="endDate"
|
||||
:time-windows="datePickerTimeWindows"
|
||||
|
|
|
@ -3,7 +3,7 @@ import { mapActions, mapState, mapGetters } from 'vuex';
|
|||
import PanelType from 'ee_else_ce/monitoring/components/panel_type.vue';
|
||||
import { getParameterValues, removeParams } from '~/lib/utils/url_utility';
|
||||
import { sidebarAnimationDuration } from '../constants';
|
||||
import { getTimeRange } from './date_time_picker/date_time_picker_lib';
|
||||
import { getTimeRange } from '~/vue_shared/components/date_time_picker/date_time_picker_lib';
|
||||
|
||||
let sidebarMutationObserver;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import _ from 'underscore';
|
||||
import { pickBy } from 'lodash';
|
||||
import {
|
||||
GlDropdown,
|
||||
GlDropdownItem,
|
||||
|
@ -90,7 +90,7 @@ export default {
|
|||
getGraphAlerts(queries) {
|
||||
if (!this.allAlerts) return {};
|
||||
const metricIdsForChart = queries.map(q => q.metricId);
|
||||
return _.pick(this.allAlerts, alert => metricIdsForChart.includes(alert.metricId));
|
||||
return pickBy(this.allAlerts, alert => metricIdsForChart.includes(alert.metricId));
|
||||
},
|
||||
getGraphAlertValues(queries) {
|
||||
return Object.values(this.getGraphAlerts(queries));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'underscore';
|
||||
import { omit } from 'lodash';
|
||||
|
||||
export const uniqMetricsId = metric => `${metric.metric_id}_${metric.id}`;
|
||||
|
||||
|
@ -11,7 +11,7 @@ export const uniqMetricsId = metric => `${metric.metric_id}_${metric.id}`;
|
|||
*/
|
||||
|
||||
export const normalizeMetric = (metric = {}) =>
|
||||
_.omit(
|
||||
omit(
|
||||
{
|
||||
...metric,
|
||||
metric_id: uniqMetricsId(metric),
|
||||
|
|
|
@ -122,30 +122,28 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<gl-dropdown
|
||||
ref="dropdown"
|
||||
:text="timeWindowText"
|
||||
menu-class="time-window-dropdown-menu"
|
||||
class="js-time-window-dropdown"
|
||||
>
|
||||
<div class="d-flex justify-content-between time-window-dropdown-menu-container">
|
||||
<gl-dropdown :text="timeWindowText" class="date-time-picker" menu-class="date-time-picker-menu">
|
||||
<div class="d-flex justify-content-between gl-p-2">
|
||||
<gl-form-group
|
||||
:label="__('Custom range')"
|
||||
label-for="custom-from-time"
|
||||
class="custom-time-range-form-group col-md-7 p-0 m-0"
|
||||
label-class="gl-pb-1"
|
||||
class="custom-time-range-form-group col-md-7 gl-pl-1 gl-pr-0 m-0"
|
||||
>
|
||||
<date-time-picker-input
|
||||
id="custom-time-from"
|
||||
v-model="startInput"
|
||||
:label="__('From')"
|
||||
:state="startInputValid"
|
||||
/>
|
||||
<date-time-picker-input
|
||||
id="custom-time-to"
|
||||
v-model="endInput"
|
||||
:label="__('To')"
|
||||
:state="endInputValid"
|
||||
/>
|
||||
<div class="gl-pt-2">
|
||||
<date-time-picker-input
|
||||
id="custom-time-from"
|
||||
v-model="startInput"
|
||||
:label="__('From')"
|
||||
:state="startInputValid"
|
||||
/>
|
||||
<date-time-picker-input
|
||||
id="custom-time-to"
|
||||
v-model="endInput"
|
||||
:label="__('To')"
|
||||
:state="endInputValid"
|
||||
/>
|
||||
</div>
|
||||
<gl-form-group>
|
||||
<gl-button @click="closeDropdown">{{ __('Cancel') }}</gl-button>
|
||||
<gl-button variant="success" :disabled="!isValid" @click="apply()">
|
||||
|
@ -153,12 +151,10 @@ export default {
|
|||
</gl-button>
|
||||
</gl-form-group>
|
||||
</gl-form-group>
|
||||
<gl-form-group
|
||||
:label="__('Quick range')"
|
||||
label-for="group-id-dropdown"
|
||||
label-align="center"
|
||||
class="col-md-4 p-0 m-0"
|
||||
>
|
||||
<gl-form-group label-for="group-id-dropdown" class="col-md-5 gl-pl-1 gl-pr-1 m-0">
|
||||
<template #label>
|
||||
<span class="gl-pl-5">{{ __('Quick range') }}</span>
|
||||
</template>
|
||||
<gl-dropdown-item
|
||||
v-for="(timeWindow, key) in timeWindows"
|
||||
:key="key"
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import { uniqueId } from 'lodash';
|
||||
import { GlFormGroup, GlFormInput } from '@gitlab/ui';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import { dateFormats } from './date_time_picker_lib';
|
||||
|
@ -35,7 +35,7 @@ export default {
|
|||
id: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: () => _.uniqueId('dateTimePicker_'),
|
||||
default: () => uniqueId('dateTimePicker_'),
|
||||
},
|
||||
},
|
||||
data() {
|
|
@ -8,6 +8,15 @@ import { secondsToMilliseconds } from '~/lib/utils/datetime_utility';
|
|||
*/
|
||||
const dateTimePickerRegex = /^(\d{4})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])(?: (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]))?$/;
|
||||
|
||||
/**
|
||||
* A key-value pair of "time windows".
|
||||
*
|
||||
* A time window is a representation of period of time that starts
|
||||
* some time in past until now. Keys are only used for easy reference.
|
||||
*
|
||||
* It is represented as user friendly `label` and number of `seconds`
|
||||
* to be substracted from now.
|
||||
*/
|
||||
export const defaultTimeWindows = {
|
||||
thirtyMinutes: {
|
||||
label: __('30 minutes'),
|
||||
|
@ -58,6 +67,17 @@ export const isValidDate = dateString => {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* For a given time window key (e.g. `threeHours`) and key-value pair
|
||||
* object of time windows.
|
||||
*
|
||||
* Returns a date time range with start and end.
|
||||
*
|
||||
* @param {String} timeWindowKey - A key in the object of time windows.
|
||||
* @param {Object} timeWindows - A key-value pair of time windows,
|
||||
* with a second duration and a label.
|
||||
* @returns An object with time range, start and end dates, in ISO format.
|
||||
*/
|
||||
export const getTimeRange = (timeWindowKey, timeWindows = defaultTimeWindows) => {
|
||||
let difference;
|
||||
if (timeWindows[timeWindowKey]) {
|
5
app/assets/stylesheets/components/date_time_picker.scss
Normal file
5
app/assets/stylesheets/components/date_time_picker.scss
Normal file
|
@ -0,0 +1,5 @@
|
|||
.date-time-picker {
|
||||
.date-time-picker-menu {
|
||||
width: 400px;
|
||||
}
|
||||
}
|
|
@ -46,32 +46,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.prometheus-graphs-header {
|
||||
.time-window-dropdown-menu {
|
||||
padding: $gl-padding $gl-padding 0 $gl-padding-12;
|
||||
}
|
||||
|
||||
.time-window-dropdown-menu-container {
|
||||
width: 360px;
|
||||
}
|
||||
|
||||
.custom-time-range-form-group > label {
|
||||
padding-bottom: $gl-padding;
|
||||
}
|
||||
|
||||
.monitor-environment-dropdown-menu {
|
||||
&.show {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.no-matches-message {
|
||||
padding: $gl-padding-8 $gl-padding-12;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.prometheus-panel {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ The initial configuration of LDAP in GitLab requires changes to the `gitlab.rb`
|
|||
|
||||
The two Active Directory specific values are `active_directory: true` and `uid: 'sAMAccountName'`. `sAMAccountName` is an attribute returned by Active Directory used for GitLab usernames. See the example output from `ldapsearch` for a full list of attributes a "person" object (user) has in **AD** - [`ldapsearch` example](#using-ldapsearch-unix)
|
||||
|
||||
> Both group_base and admin_group configuration options are only available in GitLab Enterprise Edition. See [GitLab EE - LDAP Features](../how_to_configure_ldap_gitlab_ee/index.html#gitlab-enterprise-edition---ldap-features) **(STARTER ONLY)**
|
||||
> Both group_base and admin_group configuration options are only available in GitLab Enterprise Edition. See [GitLab EE - LDAP Features](../how_to_configure_ldap_gitlab_ee/index.md#gitlab-enterprise-edition---ldap-features) **(STARTER ONLY)**
|
||||
|
||||
### Example `gitlab.rb` LDAP
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ sudo gitlab-ctl reconfigure
|
|||
```
|
||||
|
||||
If you do not perform this step, you may find that two-factor authentication
|
||||
[is broken following DR](../disaster_recovery/index.html#i-followed-the-disaster-recovery-instructions-and-now-two-factor-auth-is-broken).
|
||||
[is broken following DR](../disaster_recovery/index.md#i-followed-the-disaster-recovery-instructions-and-now-two-factor-auth-is-broken).
|
||||
|
||||
To prevent SSH requests to the newly promoted **primary** node from failing
|
||||
due to SSH host key mismatch when updating the **primary** node domain's DNS record
|
||||
|
|
|
@ -369,7 +369,7 @@ If you need to manually remove job artifacts associated with multiple jobs while
|
|||
|
||||
NOTE: **NOTE:**
|
||||
This step will also erase artifacts that users have chosen to
|
||||
["keep"](../user/project/pipelines/job_artifacts.html#browsing-artifacts).
|
||||
["keep"](../user/project/pipelines/job_artifacts.md#browsing-artifacts).
|
||||
|
||||
```ruby
|
||||
builds_to_clear = builds_with_artifacts.where("finished_at < ?", 1.week.ago)
|
||||
|
|
|
@ -133,7 +133,7 @@ To use an external Prometheus server:
|
|||
```
|
||||
|
||||
1. Install and set up a dedicated Prometheus instance, if necessary, using the [official installation instructions](https://prometheus.io/docs/prometheus/latest/installation/).
|
||||
1. Add the Prometheus server IP address to the [monitoring IP whitelist](../ip_whitelist.html). For example:
|
||||
1. Add the Prometheus server IP address to the [monitoring IP whitelist](../ip_whitelist.md). For example:
|
||||
|
||||
```ruby
|
||||
gitlab_rails['monitoring_whitelist'] = ['127.0.0.0/8', '192.168.0.1']
|
||||
|
|
|
@ -744,7 +744,7 @@ project or branch name. Special characters can include:
|
|||
|
||||
To get around this, you can [change the group path](../../user/group/index.md#changing-a-groups-path),
|
||||
[change the project path](../../user/project/settings/index.md#renaming-a-repository) or change the
|
||||
branch name. Another option is to create a [push rule](../../push_rules/push_rules.html) to prevent
|
||||
branch name. Another option is to create a [push rule](../../push_rules/push_rules.md) to prevent
|
||||
this at the instance level.
|
||||
|
||||
### Image push errors
|
||||
|
|
|
@ -120,7 +120,7 @@ Example response:
|
|||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/34078) in GitLab 12.5.
|
||||
|
||||
The Group Audit Events API allows you to retrieve [group audit events](../administration/audit_events.html#group-events-starter).
|
||||
The Group Audit Events API allows you to retrieve [group audit events](../administration/audit_events.md#group-events-starter).
|
||||
|
||||
To retrieve group audit events using the API, you must [authenticate yourself](README.html#authentication) as an Administrator or an owner of the group.
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ Emoji can be awarded on the following (known as "awardables"):
|
|||
- [Merge requests](../user/project/merge_requests/index.md) ([API](merge_requests.md)).
|
||||
- [Snippets](../user/snippets.md) ([API](snippets.md)).
|
||||
|
||||
Emoji can also [be awarded](../user/award_emojis.html#award-emoji-for-comments) on comments (also known as notes). See also [Notes API](notes.md).
|
||||
Emoji can also [be awarded](../user/award_emojis.md#award-emoji-for-comments) on comments (also known as notes). See also [Notes API](notes.md).
|
||||
|
||||
## Issues, merge requests, and snippets
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.com/api/v4/pro
|
|||
## Compare branches, tags or commits
|
||||
|
||||
This endpoint can be accessed without authentication if the repository is
|
||||
publicly accessible. Note that diffs could have an empty diff string if [diff limits](../development/diffs.html#diff-limits) are reached.
|
||||
publicly accessible. Note that diffs could have an empty diff string if [diff limits](../development/diffs.md#diff-limits) are reached.
|
||||
|
||||
```
|
||||
GET /projects/:id/repository/compare
|
||||
|
|
|
@ -341,7 +341,7 @@ This also applies when using links in between translated sentences, otherwise th
|
|||
```js
|
||||
{{
|
||||
sprintf(s__("ClusterIntegration|Learn more about %{linkStart}zones%{linkEnd}"), {
|
||||
linkStart: '<a href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" target="_blank" rel="noopener noreferrer">'
|
||||
linkStart: '<a href="https://cloud.google.com/compute/docs/regions-zones/regions-zones" target="_blank" rel="noopener noreferrer">',
|
||||
linkEnd: '</a>',
|
||||
})
|
||||
}}
|
||||
|
|
|
@ -93,7 +93,7 @@ This creates a `.git` directory that contains the Git configuration files.
|
|||
|
||||
Once the directory has been initialized, you can [add a remote repository](#add-a-remote-repository)
|
||||
and [send changes to GitLab.com](#send-changes-to-gitlabcom). You will also need to
|
||||
[create a new project in GitLab](../gitlab-basics/create-project.html#push-to-create-a-new-project)
|
||||
[create a new project in GitLab](../gitlab-basics/create-project.md#push-to-create-a-new-project)
|
||||
for your Git repository.
|
||||
|
||||
### Clone a repository
|
||||
|
|
|
@ -119,7 +119,7 @@ The following table depicts the various user permission levels in a project.
|
|||
| Configure project hooks | | | | ✓ | ✓ |
|
||||
| Manage Runners | | | | ✓ | ✓ |
|
||||
| Manage job triggers | | | | ✓ | ✓ |
|
||||
| Manage variables | | | | ✓ | ✓ |
|
||||
| Manage CI/CD variables | | | | ✓ | ✓ |
|
||||
| Manage GitLab Pages | | | | ✓ | ✓ |
|
||||
| Manage GitLab Pages domains and certificates | | | | ✓ | ✓ |
|
||||
| Remove GitLab Pages | | | | ✓ | ✓ |
|
||||
|
@ -223,6 +223,7 @@ group.
|
|||
| Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
|
||||
| Create subgroup | | | | ✓ (1) | ✓ |
|
||||
| Edit group | | | | | ✓ |
|
||||
| Manage group level CI/CD variables | | | | | ✓ |
|
||||
| Manage group members | | | | | ✓ |
|
||||
| Remove group | | | | | ✓ |
|
||||
| Delete group epic **(ULTIMATE)** | | | | | ✓ |
|
||||
|
|
|
@ -134,7 +134,7 @@ Multiple metrics can be displayed on the same chart if the fields **Name**, **Ty
|
|||
|
||||
#### Query Variables
|
||||
|
||||
GitLab supports a limited set of [CI variables](../../../ci/variables/README.html) in the Prometheus query. This is particularly useful for identifying a specific environment, for example with `CI_ENVIRONMENT_SLUG`. The supported variables are:
|
||||
GitLab supports a limited set of [CI variables](../../../ci/variables/README.md) in the Prometheus query. This is particularly useful for identifying a specific environment, for example with `CI_ENVIRONMENT_SLUG`. The supported variables are:
|
||||
|
||||
- CI_ENVIRONMENT_SLUG
|
||||
- KUBE_NAMESPACE
|
||||
|
|
|
@ -34,7 +34,7 @@ to be enabled:
|
|||
and enable **Git Large File Storage**.
|
||||
|
||||
Design Management requires that projects are using
|
||||
[hashed storage](../../../administration/repository_storage_types.html#hashed-storage)
|
||||
[hashed storage](../../../administration/repository_storage_types.md#hashed-storage)
|
||||
(the default storage type since v10.0).
|
||||
|
||||
### Feature Flags
|
||||
|
|
|
@ -54,4 +54,4 @@ It is possible to prevent projects in a group from [sharing
|
|||
a project with another group](../members/share_project_with_groups.md).
|
||||
This allows for tighter control over project access.
|
||||
|
||||
Learn more about [Share with group lock](../../group/index.html#share-with-group-lock).
|
||||
Learn more about [Share with group lock](../../group/index.md#share-with-group-lock).
|
||||
|
|
|
@ -58,7 +58,7 @@ if the job surpasses the threshold, it is marked as failed.
|
|||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/17221) in GitLab 10.7.
|
||||
|
||||
Project defined timeout (either specific timeout set by user or the default
|
||||
60 minutes timeout) may be [overridden on Runner level](../../../ci/runners/README.html#setting-maximum-job-timeout-for-a-runner).
|
||||
60 minutes timeout) may be [overridden on Runner level](../../../ci/runners/README.md#setting-maximum-job-timeout-for-a-runner).
|
||||
|
||||
## Maximum artifacts size **(CORE ONLY)**
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ related to the project by selecting the **Disable email notifications** checkbox
|
|||
|
||||
Set up your project's merge request settings:
|
||||
|
||||
- Set up the merge request method (merge commit, [fast-forward merge](../merge_requests/fast_forward_merge.html)).
|
||||
- Set up the merge request method (merge commit, [fast-forward merge](../merge_requests/fast_forward_merge.md)).
|
||||
- Add merge request [description templates](../description_templates.md#description-templates).
|
||||
- Enable [merge request approvals](../merge_requests/merge_request_approvals.md). **(STARTER)**
|
||||
- Enable [merge only if pipeline succeeds](../merge_requests/merge_when_pipeline_succeeds.md).
|
||||
|
|
|
@ -7,8 +7,8 @@ import statusCodes from '~/lib/utils/http_status';
|
|||
import { metricStates } from '~/monitoring/constants';
|
||||
import Dashboard from '~/monitoring/components/dashboard.vue';
|
||||
|
||||
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
|
||||
import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue';
|
||||
import DateTimePicker from '~/monitoring/components/date_time_picker/date_time_picker.vue';
|
||||
import GroupEmptyState from '~/monitoring/components/group_empty_state.vue';
|
||||
import { createStore } from '~/monitoring/stores';
|
||||
import * as types from '~/monitoring/stores/mutation_types';
|
||||
|
|
|
@ -53,7 +53,7 @@ describe('dashboard time window', () => {
|
|||
.$nextTick()
|
||||
.then(() => {
|
||||
const timeWindowDropdownItems = wrapper
|
||||
.find('.js-time-window-dropdown')
|
||||
.find({ ref: 'dateTimePicker' })
|
||||
.findAll(GlDropdownItem);
|
||||
|
||||
const activeItem = timeWindowDropdownItems.wrappers.filter(itemWrapper =>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import DateTimePickerInput from '~/monitoring/components/date_time_picker/date_time_picker_input.vue';
|
||||
import DateTimePickerInput from '~/vue_shared/components/date_time_picker/date_time_picker_input.vue';
|
||||
|
||||
const inputLabel = 'This is a label';
|
||||
const inputValue = 'something';
|
|
@ -1,4 +1,4 @@
|
|||
import * as dateTimePickerLib from '~/monitoring/components/date_time_picker/date_time_picker_lib';
|
||||
import * as dateTimePickerLib from '~/vue_shared/components/date_time_picker/date_time_picker_lib';
|
||||
|
||||
describe('date time picker lib', () => {
|
||||
describe('isValidDate', () => {
|
|
@ -1,6 +1,6 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import DateTimePicker from '~/monitoring/components/date_time_picker/date_time_picker.vue';
|
||||
import { defaultTimeWindows } from '~/monitoring/components/date_time_picker/date_time_picker_lib';
|
||||
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
|
||||
import { defaultTimeWindows } from '~/vue_shared/components/date_time_picker/date_time_picker_lib';
|
||||
|
||||
const timeWindowsCount = Object.entries(defaultTimeWindows).length;
|
||||
const start = '2019-10-10T07:00:00.000Z';
|
|
@ -482,6 +482,18 @@ describe Repository do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#root_ref_sha" do
|
||||
let(:commit) { double("commit", sha: "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3") }
|
||||
|
||||
subject { repository.root_ref_sha }
|
||||
|
||||
before do
|
||||
allow(repository).to receive(:commit).with(repository.root_ref) { commit }
|
||||
end
|
||||
|
||||
it { is_expected.to eq(commit.sha) }
|
||||
end
|
||||
|
||||
describe '#can_be_merged?' do
|
||||
context 'mergeable branches' do
|
||||
subject { repository.can_be_merged?('0b4bc9a49b562e85de7cc9e834518ea6828729b9', 'master') }
|
||||
|
|
|
@ -10,10 +10,12 @@ describe NotificationService, :mailer do
|
|||
let(:notification) { described_class.new }
|
||||
let(:assignee) { create(:user) }
|
||||
|
||||
around do |example|
|
||||
perform_enqueued_jobs do
|
||||
example.run
|
||||
end
|
||||
around(:example, :deliver_mails_inline) do |example|
|
||||
# This is a temporary `around` hook until all the examples check the
|
||||
# background jobs queue instead of the delivered emails array.
|
||||
# `perform_enqueued_jobs` makes the ActiveJob jobs (e.g. mailer jobs) run inline
|
||||
# compared to `Sidekiq::Testing.inline!` which makes the Sidekiq jobs run inline.
|
||||
perform_enqueued_jobs { example.run }
|
||||
end
|
||||
|
||||
shared_examples 'altered milestone notification on issue' do
|
||||
|
@ -187,26 +189,41 @@ describe NotificationService, :mailer do
|
|||
describe 'Keys' do
|
||||
describe '#new_key' do
|
||||
let(:key_options) { {} }
|
||||
let!(:key) { create(:personal_key, key_options) }
|
||||
let!(:key) { build_stubbed(:personal_key, key_options) }
|
||||
|
||||
it { expect(notification.new_key(key)).to be_truthy }
|
||||
subject { notification.new_key(key) }
|
||||
|
||||
describe 'never emails the ghost user' do
|
||||
it "sends email to key owner" do
|
||||
expect { subject }.to have_enqueued_email(key.id, mail: "new_ssh_key_email")
|
||||
end
|
||||
|
||||
describe "never emails the ghost user" do
|
||||
let(:key_options) { { user: User.ghost } }
|
||||
|
||||
it { should_not_email_anyone }
|
||||
it "does not send email to key owner" do
|
||||
expect { subject }.not_to have_enqueued_email(key.id, mail: "new_ssh_key_email")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GpgKeys' do
|
||||
describe '#new_gpg_key' do
|
||||
let!(:key) { create(:gpg_key) }
|
||||
let(:key_options) { {} }
|
||||
let(:key) { create(:gpg_key, key_options) }
|
||||
|
||||
it { expect(notification.new_gpg_key(key)).to be_truthy }
|
||||
subject { notification.new_gpg_key(key) }
|
||||
|
||||
it 'sends email to key owner' do
|
||||
expect { notification.new_gpg_key(key) }.to change { ActionMailer::Base.deliveries.size }.by(1)
|
||||
it "sends email to key owner" do
|
||||
expect { subject }.to have_enqueued_email(key.id, mail: "new_gpg_key_email")
|
||||
end
|
||||
|
||||
describe "never emails the ghost user" do
|
||||
let(:key_options) { { user: User.ghost } }
|
||||
|
||||
it "does not send email to key owner" do
|
||||
expect { subject }.not_to have_enqueued_email(key.id, mail: "new_gpg_key_email")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -215,10 +232,10 @@ describe NotificationService, :mailer do
|
|||
describe '#access_token_about_to_expire' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
it 'sends email to the token owner' do
|
||||
expect(notification.access_token_about_to_expire(user)).to be_truthy
|
||||
subject { notification.access_token_about_to_expire(user) }
|
||||
|
||||
should_email user
|
||||
it 'sends email to the token owner' do
|
||||
expect { subject }.to have_enqueued_email(user, mail: "access_token_about_to_expire_email")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -231,6 +248,8 @@ describe NotificationService, :mailer do
|
|||
let(:author) { create(:user) }
|
||||
let(:note) { create(:note_on_issue, author: author, noteable: issue, project_id: issue.project_id, note: '@mention referenced, @unsubscribed_mentioned and @outsider also') }
|
||||
|
||||
subject { notification.new_note(note) }
|
||||
|
||||
before do
|
||||
build_team(project)
|
||||
project.add_maintainer(issue.author)
|
||||
|
@ -260,32 +279,23 @@ describe NotificationService, :mailer do
|
|||
reset_delivered_emails!
|
||||
end
|
||||
|
||||
it do
|
||||
expect(SentNotification).to receive(:record).with(issue, any_args).exactly(10).times
|
||||
it 'sends emails to recipients' do
|
||||
subject
|
||||
|
||||
notification.new_note(note)
|
||||
|
||||
should_email(@u_watcher)
|
||||
should_email(note.noteable.author)
|
||||
should_email(note.noteable.assignees.first)
|
||||
should_email(@u_custom_global)
|
||||
should_email(@u_mentioned)
|
||||
should_email(@subscriber)
|
||||
should_email(@watcher_and_subscriber)
|
||||
should_email(@subscribed_participant)
|
||||
should_email(@u_custom_off)
|
||||
should_email(@unsubscribed_mentioned)
|
||||
should_not_email(@u_guest_custom)
|
||||
should_not_email(@u_guest_watcher)
|
||||
should_not_email(note.author)
|
||||
should_not_email(@u_participating)
|
||||
should_not_email(@u_disabled)
|
||||
should_not_email(@unsubscriber)
|
||||
should_not_email(@u_outsider_mentioned)
|
||||
should_not_email(@u_lazy_participant)
|
||||
expect_delivery_jobs_count(10)
|
||||
expect_enqueud_email(@u_watcher.id, note.id, nil, mail: "note_issue_email")
|
||||
expect_enqueud_email(note.noteable.author.id, note.id, nil, mail: "note_issue_email")
|
||||
expect_enqueud_email(note.noteable.assignees.first.id, note.id, nil, mail: "note_issue_email")
|
||||
expect_enqueud_email(@u_custom_global.id, note.id, nil, mail: "note_issue_email")
|
||||
expect_enqueud_email(@u_mentioned.id, note.id, "mentioned", mail: "note_issue_email")
|
||||
expect_enqueud_email(@subscriber.id, note.id, "subscribed", mail: "note_issue_email")
|
||||
expect_enqueud_email(@watcher_and_subscriber.id, note.id, "subscribed", mail: "note_issue_email")
|
||||
expect_enqueud_email(@subscribed_participant.id, note.id, "subscribed", mail: "note_issue_email")
|
||||
expect_enqueud_email(@u_custom_off.id, note.id, nil, mail: "note_issue_email")
|
||||
expect_enqueud_email(@unsubscribed_mentioned.id, note.id, "mentioned", mail: "note_issue_email")
|
||||
end
|
||||
|
||||
it "emails the note author if they've opted into notifications about their activity" do
|
||||
it "emails the note author if they've opted into notifications about their activity", :deliver_mails_inline do
|
||||
note.author.notified_of_own_activity = true
|
||||
|
||||
notification.new_note(note)
|
||||
|
@ -294,7 +304,7 @@ describe NotificationService, :mailer do
|
|||
expect(find_email_for(note.author)).to have_header('X-GitLab-NotificationReason', 'own_activity')
|
||||
end
|
||||
|
||||
it_behaves_like 'project emails are disabled' do
|
||||
it_behaves_like 'project emails are disabled', check_delivery_jobs_queue: true do
|
||||
let(:notification_target) { note }
|
||||
let(:notification_trigger) { notification.new_note(note) }
|
||||
end
|
||||
|
@ -302,21 +312,21 @@ describe NotificationService, :mailer do
|
|||
|
||||
it 'filters out "mentioned in" notes' do
|
||||
mentioned_note = SystemNoteService.cross_reference(mentioned_issue, issue, issue.author)
|
||||
reset_delivered_emails!
|
||||
|
||||
expect(Notify).not_to receive(:note_issue_email)
|
||||
notification.new_note(mentioned_note)
|
||||
|
||||
expect_no_delivery_jobs
|
||||
end
|
||||
|
||||
context 'participating' do
|
||||
context 'by note' do
|
||||
before do
|
||||
reset_delivered_emails!
|
||||
note.author = @u_lazy_participant
|
||||
note.save
|
||||
notification.new_note(note)
|
||||
end
|
||||
|
||||
it { should_not_email(@u_lazy_participant) }
|
||||
it { expect { subject }.not_to have_enqueued_email(@u_lazy_participant.id, note.id, mail: "note_issue_email") }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -335,7 +345,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
|
||||
shared_examples 'new note notifications' do
|
||||
it do
|
||||
it 'sends notifications', :deliver_mails_inline do
|
||||
notification.new_note(note)
|
||||
|
||||
should_email(note.noteable.author)
|
||||
|
@ -359,7 +369,7 @@ describe NotificationService, :mailer do
|
|||
|
||||
it_behaves_like 'new note notifications'
|
||||
|
||||
it_behaves_like 'project emails are disabled' do
|
||||
it_behaves_like 'project emails are disabled', check_delivery_jobs_queue: true do
|
||||
let(:notification_target) { note }
|
||||
let(:notification_trigger) { notification.new_note(note) }
|
||||
end
|
||||
|
@ -378,13 +388,13 @@ describe NotificationService, :mailer do
|
|||
|
||||
notification.new_note(note)
|
||||
|
||||
should_email(user)
|
||||
expect_enqueud_email(user.id, note.id, nil, mail: "note_issue_email")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'confidential issue note' do
|
||||
context 'confidential issue note', :deliver_mails_inline do
|
||||
let(:project) { create(:project, :public) }
|
||||
let(:author) { create(:user) }
|
||||
let(:assignee) { create(:user) }
|
||||
|
@ -441,7 +451,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
context 'issue note mention' do
|
||||
context 'issue note mention', :deliver_mails_inline do
|
||||
let(:project) { create(:project, :public) }
|
||||
let(:issue) { create(:issue, project: project, assignees: [assignee]) }
|
||||
let(:mentioned_issue) { create(:issue, assignees: issue.assignees) }
|
||||
|
@ -507,7 +517,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
context 'project snippet note' do
|
||||
context 'project snippet note', :deliver_mails_inline do
|
||||
let!(:project) { create(:project, :public) }
|
||||
let(:snippet) { create(:project_snippet, project: project, author: create(:user)) }
|
||||
let(:author) { create(:user) }
|
||||
|
@ -551,7 +561,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
context 'personal snippet note' do
|
||||
context 'personal snippet note', :deliver_mails_inline do
|
||||
let(:snippet) { create(:personal_snippet, :public, author: @u_snippet_author) }
|
||||
let(:note) { create(:note_on_personal_snippet, noteable: snippet, note: '@mentioned note', author: @u_note_author) }
|
||||
|
||||
|
@ -600,7 +610,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
context 'commit note' do
|
||||
context 'commit note', :deliver_mails_inline do
|
||||
let(:project) { create(:project, :public, :repository) }
|
||||
let(:note) { create(:note_on_commit, project: project) }
|
||||
|
||||
|
@ -659,7 +669,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
context "merge request diff note" do
|
||||
context "merge request diff note", :deliver_mails_inline do
|
||||
let(:project) { create(:project, :repository) }
|
||||
let(:user) { create(:user) }
|
||||
let(:merge_request) { create(:merge_request, source_project: project, assignees: [user], author: create(:user)) }
|
||||
|
@ -691,11 +701,11 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#send_new_release_notifications' do
|
||||
describe '#send_new_release_notifications', :deliver_mails_inline, :sidekiq_inline do
|
||||
context 'when recipients for a new release exist' do
|
||||
let(:release) { create(:release) }
|
||||
|
||||
it 'calls new_release_email for each relevant recipient', :sidekiq_might_not_need_inline do
|
||||
it 'calls new_release_email for each relevant recipient' do
|
||||
user_1 = create(:user)
|
||||
user_2 = create(:user)
|
||||
user_3 = create(:user)
|
||||
|
@ -712,7 +722,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Participating project notification settings have priority over group and global settings if available' do
|
||||
describe 'Participating project notification settings have priority over group and global settings if available', :deliver_mails_inline do
|
||||
let!(:group) { create(:group) }
|
||||
let!(:maintainer) { group.add_owner(create(:user, username: 'maintainer')).user }
|
||||
let!(:user1) { group.add_developer(create(:user, username: 'user_with_project_and_custom_setting')).user }
|
||||
|
@ -770,7 +780,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Issues' do
|
||||
describe 'Issues', :deliver_mails_inline do
|
||||
let(:group) { create(:group) }
|
||||
let(:project) { create(:project, :public, namespace: group) }
|
||||
let(:another_project) { create(:project, :public, namespace: group) }
|
||||
|
@ -1423,7 +1433,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Merge Requests' do
|
||||
describe 'Merge Requests', :deliver_mails_inline do
|
||||
let(:group) { create(:group) }
|
||||
let(:project) { create(:project, :public, :repository, namespace: group) }
|
||||
let(:another_project) { create(:project, :public, namespace: group) }
|
||||
|
@ -1898,7 +1908,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Projects' do
|
||||
describe 'Projects', :deliver_mails_inline do
|
||||
let(:project) { create(:project) }
|
||||
|
||||
before do
|
||||
|
@ -1989,7 +1999,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'GroupMember' do
|
||||
describe 'GroupMember', :deliver_mails_inline do
|
||||
let(:added_user) { create(:user) }
|
||||
|
||||
describe '#new_access_request' do
|
||||
|
@ -2075,7 +2085,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'ProjectMember' do
|
||||
describe 'ProjectMember', :deliver_mails_inline do
|
||||
let(:project) { create(:project) }
|
||||
let(:added_user) { create(:user) }
|
||||
|
||||
|
@ -2236,7 +2246,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
context 'guest user in private project' do
|
||||
context 'guest user in private project', :deliver_mails_inline do
|
||||
let(:private_project) { create(:project, :private) }
|
||||
let(:guest) { create(:user) }
|
||||
let(:developer) { create(:user) }
|
||||
|
@ -2291,7 +2301,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Pipelines' do
|
||||
describe 'Pipelines', :deliver_mails_inline do
|
||||
describe '#pipeline_finished' do
|
||||
let(:project) { create(:project, :public, :repository) }
|
||||
let(:u_member) { create(:user) }
|
||||
|
@ -2507,7 +2517,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Pages domains' do
|
||||
describe 'Pages domains', :deliver_mails_inline do
|
||||
let_it_be(:project, reload: true) { create(:project) }
|
||||
let_it_be(:domain, reload: true) { create(:pages_domain, project: project) }
|
||||
let_it_be(:u_blocked) { create(:user, :blocked) }
|
||||
|
@ -2560,7 +2570,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
context 'Auto DevOps notifications' do
|
||||
context 'Auto DevOps notifications', :deliver_mails_inline do
|
||||
describe '#autodevops_disabled' do
|
||||
let(:owner) { create(:user) }
|
||||
let(:namespace) { create(:namespace, owner: owner) }
|
||||
|
@ -2584,7 +2594,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Repository cleanup' do
|
||||
describe 'Repository cleanup', :deliver_mails_inline do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project) }
|
||||
|
||||
|
@ -2615,7 +2625,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
context 'Remote mirror notifications' do
|
||||
context 'Remote mirror notifications', :deliver_mails_inline do
|
||||
describe '#remote_mirror_update_failed' do
|
||||
let(:project) { create(:project) }
|
||||
let(:remote_mirror) { create(:remote_mirror, project: project) }
|
||||
|
@ -2653,7 +2663,7 @@ describe NotificationService, :mailer do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with external authorization service' do
|
||||
context 'with external authorization service', :deliver_mails_inline do
|
||||
let(:issue) { create(:issue) }
|
||||
let(:project) { issue.project }
|
||||
let(:note) { create(:note, noteable: issue, project: project) }
|
||||
|
|
|
@ -6,7 +6,12 @@ module EmailHelpers
|
|||
end
|
||||
|
||||
def reset_delivered_emails!
|
||||
# We shouldn't actually send the emails, but we keep the following line for
|
||||
# back-compatibility until we only check the mailer jobs enqueued in Sidekiq
|
||||
ActionMailer::Base.deliveries.clear
|
||||
# We should only check that the mailer jobs are enqueued in Sidekiq, hence
|
||||
# clearing the background jobs queue
|
||||
ActiveJob::Base.queue_adapter.enqueued_jobs.clear
|
||||
end
|
||||
|
||||
def should_only_email(*users, kind: :to)
|
||||
|
|
|
@ -36,4 +36,28 @@ module NotificationHelpers
|
|||
setting = user.notification_settings_for(resource)
|
||||
setting.update!(event => value)
|
||||
end
|
||||
|
||||
def expect_delivery_jobs_count(count)
|
||||
expect(ActionMailer::DeliveryJob).to have_been_enqueued.exactly(count).times
|
||||
end
|
||||
|
||||
def expect_no_delivery_jobs
|
||||
expect(ActionMailer::DeliveryJob).not_to have_been_enqueued
|
||||
end
|
||||
|
||||
def expect_any_delivery_jobs
|
||||
expect(ActionMailer::DeliveryJob).to have_been_enqueued.at_least(:once)
|
||||
end
|
||||
|
||||
def have_enqueued_email(*args, mailer: "Notify", mail: "", delivery: "deliver_now")
|
||||
have_enqueued_job(ActionMailer::DeliveryJob).with(mailer, mail, delivery, *args)
|
||||
end
|
||||
|
||||
def expect_enqueud_email(*args, mailer: "Notify", mail: "", delivery: "deliver_now")
|
||||
expect(ActionMailer::DeliveryJob).to have_been_enqueued.with(mailer, mail, delivery, *args)
|
||||
end
|
||||
|
||||
def expect_not_enqueud_email(*args, mailer: "Notify", mail: "", delivery: "deliver_now")
|
||||
expect(ActionMailer::DeliveryJob).not_to have_been_enqueued.with(mailer, mail, *args, any_args)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# Note that we actually update the attribute on the target_project/group, rather than
|
||||
# using `allow`. This is because there are some specs where, based on how the notification
|
||||
# is done, using an `allow` doesn't change the correct object.
|
||||
RSpec.shared_examples 'project emails are disabled' do
|
||||
RSpec.shared_examples 'project emails are disabled' do |check_delivery_jobs_queue: false|
|
||||
let(:target_project) { notification_target.is_a?(Project) ? notification_target : notification_target.project }
|
||||
|
||||
before do
|
||||
|
@ -16,7 +16,13 @@ RSpec.shared_examples 'project emails are disabled' do
|
|||
|
||||
notification_trigger
|
||||
|
||||
should_not_email_anyone
|
||||
if check_delivery_jobs_queue
|
||||
# Only check enqueud jobs, not delivered emails
|
||||
expect_no_delivery_jobs
|
||||
else
|
||||
# Deprecated: Check actual delivered emails
|
||||
should_not_email_anyone
|
||||
end
|
||||
end
|
||||
|
||||
it 'sends emails to someone' do
|
||||
|
@ -24,7 +30,13 @@ RSpec.shared_examples 'project emails are disabled' do
|
|||
|
||||
notification_trigger
|
||||
|
||||
should_email_anyone
|
||||
if check_delivery_jobs_queue
|
||||
# Only check enqueud jobs, not delivered emails
|
||||
expect_any_delivery_jobs
|
||||
else
|
||||
# Deprecated: Check actual delivered emails
|
||||
should_email_anyone
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue