Commit 23997246 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 6755df10
......@@ -1328,7 +1328,7 @@ DEPENDENCIES
request_store (~> 1.3)
responders (~> 3.0)
retriable (~> 3.1.2)
rouge (~> 3.11.0)
rouge (~> 3.15.0)
rqrcode-rails3 (~> 0.1.7)
rspec-parameterized
rspec-rails (~> 4.0.0.beta3)
......
---
title: Document CI job activity limit for pipeline creation
merge_request: 23246
author:
type: added
......@@ -42,3 +42,35 @@ Activity history for projects and individuals' profiles was limited to one year
A maximum number of project webhooks applies to each GitLab.com tier. Check the
[Maximum number of webhooks (per tier)](../user/project/integrations/webhooks.md#maximum-number-of-webhooks-per-tier)
section in the Webhooks page.
## CI/CD limits
### Number of jobs in active pipelines
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/32823) in GitLab 12.6.
The total number of jobs in active pipelines can be limited per project. This limit is checked
each time a new pipeline is created. An active pipeline is any pipeline in one of the following states:
- `created`
- `pending`
- `running`
If a new pipeline would cause the total number of jobs to exceed the limit, the pipeline
will fail with a `job_activity_limit_exceeded` error.
- On GitLab.com different [limits are defined per plan](../user/gitlab_com/index.md#gitlab-cicd) and they affect all projects under that plan.
- On [GitLab Starter](https://about.gitlab.com/pricing/#self-managed) tier or higher self-hosted installations, this limit is defined for the `default` plan that affects all projects.
This limit is disabled by default.
To set this limit on a self-hosted installation, run the following in the
[GitLab Rails console](https://docs.gitlab.com/omnibus/maintenance/#starting-a-rails-console-session):
```ruby
# If limits don't exist for the default plan, you can create one with:
# Plan.default.create_limits!
Plan.default.limits.update!(ci_active_jobs: 500)
```
Set the limit to `0` to disable it.
......@@ -121,7 +121,9 @@ In this example we can see that server processed an HTTP request with URL
## `api_json.log`
Introduced in GitLab 10.0, this file lives in
> Introduced in GitLab 10.0.
This file lives in
`/var/log/gitlab/gitlab-rails/api_json.log` for Omnibus GitLab packages or in
`/home/git/gitlab/log/api_json.log` for installations from source.
......@@ -159,6 +161,21 @@ October 07, 2014 11:25: User "Claudie Hodkiewicz" (nasir_stehr@olson.co.uk) was
October 07, 2014 11:25: Project "project133" was removed
```
## `application_json.log`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/22812) in GitLab 12.7.
This file lives in `/var/log/gitlab/gitlab-rails/application_json.log` for
Omnibus GitLab packages or in `/home/git/gitlab/log/application_json.log` for
installations from source.
It contains the JSON version of the logs in `application.log` like the example below:
``` json
{"severity":"INFO","time":"2020-01-14T13:35:15.466Z","correlation_id":"3823a1550b64417f9c9ed8ee0f48087e","message":"User \"Administrator\" (admin@example.com) was created"}
{"severity":"INFO","time":"2020-01-14T13:35:15.466Z","correlation_id":"78e3df10c9a18745243d524540bd5be4","message":"Project \"project133\" was removed"}
```
## `integrations_json.log`
This file lives in `/var/log/gitlab/gitlab-rails/integrations_json.log` for
......@@ -174,7 +191,9 @@ It contains information about [integrations](../user/project/integrations/projec
## `kubernetes.log`
Introduced in GitLab 11.6. This file lives in
> Introduced in GitLab 11.6.
This file lives in
`/var/log/gitlab/gitlab-rails/kubernetes.log` for Omnibus GitLab
packages or in `/home/git/gitlab/log/kubernetes.log` for
installations from source.
......@@ -320,13 +339,17 @@ It logs information whenever a [repository check is run][repocheck] on a project
## `importer.log`
Introduced in GitLab 11.3. This file lives in `/var/log/gitlab/gitlab-rails/importer.log` for
> Introduced in GitLab 11.3.
This file lives in `/var/log/gitlab/gitlab-rails/importer.log` for
Omnibus GitLab packages or in `/home/git/gitlab/log/importer.log` for
installations from source.
## `auth.log`
Introduced in GitLab 12.0. This file lives in `/var/log/gitlab/gitlab-rails/auth.log` for
> Introduced in GitLab 12.0.
This file lives in `/var/log/gitlab/gitlab-rails/auth.log` for
Omnibus GitLab packages or in `/home/git/gitlab/log/auth.log` for
installations from source.
......@@ -356,7 +379,9 @@ GraphQL queries are recorded in that file. For example:
## `migrations.log`
Introduced in GitLab 12.3. This file lives in `/var/log/gitlab/gitlab-rails/migrations.log` for
> Introduced in GitLab 12.3.
This file lives in `/var/log/gitlab/gitlab-rails/migrations.log` for
Omnibus GitLab packages or in `/home/git/gitlab/log/migrations.log` for
installations from source.
......@@ -406,7 +431,9 @@ It is stored at:
## `elasticsearch.log`
Introduced in GitLab 12.6. This file lives in
> Introduced in GitLab 12.6.
This file lives in
`/var/log/gitlab/gitlab-rails/elasticsearch.log` for Omnibus GitLab
packages or in `/home/git/gitlab/log/elasticsearch.log` for installations
from source.
......
......@@ -75,6 +75,7 @@ Below are the current settings regarding [GitLab CI/CD](../../ci/README.md).
| Artifacts maximum size (uncompressed) | 1G | 100M |
| Artifacts [expiry time](../../ci/yaml/README.md#artifactsexpire_in) | kept forever | deleted after 30 days unless otherwise specified |
| Scheduled Pipeline Cron | `*/5 * * * *` | `*/19 * * * *` |
| [Max jobs in active pipelines](../../administration/instance_limits.md#number-of-jobs-in-active-pipelines) | `500` for Free tier, unlimited otherwise | Unlimited
## Repository size limit
......@@ -95,7 +96,11 @@ IP based firewall can be configured by looking up all
## Shared Runners
Shared Runners on GitLab.com run in [autoscale mode] and powered by Google Cloud Platform.
GitLab offers Linux and Windows shared runners hosted on GitLab.com for executing your pipelines.
### Linux Shared Runners
Linux Shared Runners on GitLab.com run in [autoscale mode] and are powered by Google Cloud Platform.
Autoscaling means reduced waiting times to spin up CI/CD jobs, and isolated VMs for each project,
thus maximizing security. They're free to use for public open source projects and limited
to 2000 CI minutes per month per group for private projects. More minutes
......@@ -122,7 +127,7 @@ Below are the shared Runners settings.
| Default Docker image | `ruby:2.5` | - |
| `privileged` (run [Docker in Docker]) | `true` | `false` |
### `config.toml`
#### `config.toml`
The full contents of our `config.toml` are:
......@@ -184,6 +189,158 @@ sentry_dsn = "X"
BucketName = "bucket-name"
```
### Windows Shared Runners (beta)
The Windows Shared Runners are currently in
[beta](https://about.gitlab.com/handbook/product/#beta) and should not be used
for production workloads.
During the beta period for groups and private projects the use of
Windows Shared Runners will count towards the [shared runner pipeline
quota](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html#shared-runners-pipeline-minutes-quota-starter-only)
as if they are Linux Runners, we do have plans to change this in
[#30835](https://gitlab.com/gitlab-org/gitlab/issues/30834).
Windows Shared Runners on GitLab.com automatically autoscale by
launching virtual machines on the Google Cloud Platform. This solution uses
a new [autoscaling driver](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md)
developed by GitLab for the [custom executor](https://docs.gitlab.com/runner/executors/custom.html).
Windows Shared Runners execute your CI/CD jobs on `n1-standard-2` instances with 2
vCPUs and 7.5GB RAM. You can find a full list of available Windows packages in the
[package documentation](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/master/cookbooks/preinstalled-software/README.md).
We want to keep iterating to get Windows Shared Runners in a stable state and
[generally available](https://about.gitlab.com/handbook/product/#generally-available-ga).
You can follow our work towards this goal in the
[related epic](https://gitlab.com/groups/gitlab-org/-/epics/2162).
#### Configuration
The full contents of our `config.toml` are:
```toml
concurrent = 10
check_interval = 3
[[runners]]
name = "windows-runner"
url = "https://gitlab.com/"
token = "TOKEN"
executor = "custom"
builds_dir = "C:\\GitLab-Runner\\builds"
cache_dir = "C:\\GitLab-Runner\\cache"
shell = "powershell"
[runners.custom]
config_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
config_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "config"]
prepare_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
prepare_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "prepare"]
run_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
run_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "run"]
cleanup_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
cleanup_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "cleanup"]
```
The full contents of our `autoscaler/config.toml` are:
```toml
Provider = "gcp"
Executor = "winrm"
OS = "windows"
LogLevel = "info"
LogFormat = "text"
LogFile = "C:\\GitLab-Runner\\autoscaler\\autoscaler.log"
VMTag = "windows"
[GCP]
ServiceAccountFile = "PATH"
Project = "some-project-df9323"
Zone = "us-east1-c"
MachineType = "n1-standard-2"
Image = "IMAGE"
DiskSize = 50
DiskType = "pd-standard"
Subnetwork = "default"
Network = "default"
Tags = ["TAGS"]
Username = "gitlab_runner"
[WinRM]
MaximumTimeout = 3600
ExecutionMaxRetries = 0
[ProviderCache]
Enabled = true
Directory = "C:\\GitLab-Runner\\autoscaler\\machines"
```
#### Example
Below is a simple `.gitlab-ci.yml` file to show how to start using the
Windows Shared Runners:
```yaml
.shared_windows_runners:
tags:
- shared
- windows
- windows-1809
stages:
- build
- test
before_script:
- date +"%H"
- echo ${HOUR}
- echo "started by ${GITLAB_USER_NAME}"
build:
extends:
- .shared_windows_runners
stage: build
script:
- echo "running scripts in the build job"
test:
extends:
- .shared_windows_runners
stage: test
script:
- echo "running scripts in the test job"
```
#### Limitations and known issues
- All the limitations mentioned in our [beta
definition](https://about.gitlab.com/handbook/product/#beta).
- The average provisioning time for a new Windows VM is 5 minutes.
This means that for the beta you will notice slower build start times
on the Windows Shared Runner fleet compared to Linux. In a future
release we will add the ability to the autoscaler which will enable
the pre-warming of virtual machines. This will significantly reduce
the time it takes to provision a VM on the Windows fleet. You can
follow along in this
[issue](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/issues/32).
- The Windows Shared Runner fleet may be unavailable occasionally
for maintenance or updates.
- The Windows Shared Runner virtual machine instances do not use the
GitLab Docker executor. This means that unlike the Linux Shared
Runners, you will not be able to specify `image` and `services` in
your pipeline configuration.
- For the beta release, we have included a set of software packages in
the base VM image. If your CI job requires additional software that's
not included in this list, then you will need to add installation
commands to [`before_script`](../../ci/yaml/README.md#before_script-and-after_script) or [`script`](../../ci/yaml/README.md#script) to install the required
software. Note that each job runs on a new VM instance, so the
installation of additional software packages needs to be repeated for
each job in your pipeline.
- The job may stay in a pending state for longer than the
Linux shared Runners.
- There is the possibility that we introduce breaking changes which will
require updates to pipelines that are using the Windows Shared Runner
fleet.
## Sidekiq
GitLab.com runs [Sidekiq](https://sidekiq.org) with arguments `--timeout=4 --concurrency=4`
......
......@@ -54,8 +54,8 @@ Design Management requires that projects are using
- Design Management data [won't be moved](https://gitlab.com/gitlab-org/gitlab/issues/13426)
when an issue is moved, nor [deleted](https://gitlab.com/gitlab-org/gitlab/issues/13427)
when an issue is deleted.
- Design Management
[isn't supported by Geo](https://gitlab.com/groups/gitlab-org/-/epics/1633) yet.
- From GitLab 12.7, Design Management data [can be replicated](../../../administration/geo/replication/datatypes.md#limitations-on-replicationverification)
by Geo but [not verified](https://gitlab.com/gitlab-org/gitlab/issues/32467).
- Only the latest version of the designs can be deleted.
- Deleted designs cannot be recovered but you can see them on previous designs versions.
......
......@@ -8,7 +8,7 @@ import TimeSeries from '~/monitoring/components/charts/time_series.vue';
import * as types from '~/monitoring/stores/mutation_types';
import {
deploymentData,
metricsGroupsAPIResponse,
metricsDashboardPayload,
mockedQueryResultPayload,
mockProjectDir,
mockHost,
......@@ -34,7 +34,7 @@ describe('Time series component', () => {
store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
metricsGroupsAPIResponse,
metricsDashboardPayload,
);
store.commit(`monitoringDashboard/${types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS}`, deploymentData);
......
......@@ -14,9 +14,8 @@ import { createStore } from '~/monitoring/stores';
import * as types from '~/monitoring/stores/mutation_types';
import { setupComponentStore, propsData } from '../init_utils';
import {
metricsGroupsAPIResponse,
metricsDashboardPayload,
mockedQueryResultPayload,
mockApiEndpoint,
environmentData,
dashboardGitResponse,
} from '../mock_data';
......@@ -33,6 +32,9 @@ describe('Dashboard', () => {
wrapper = shallowMount(Dashboard, {
localVue,
propsData: { ...propsData, ...props },
methods: {
fetchData: jest.fn(),
},
store,
...options,
});
......@@ -42,6 +44,9 @@ describe('Dashboard', () => {
wrapper = mount(Dashboard, {
localVue,
propsData: { ...propsData, ...props },
methods: {
fetchData: jest.fn(),
},
store,
...options,
});
......@@ -55,21 +60,16 @@ describe('Dashboard', () => {
afterEach(() => {
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
mock.restore();
});
describe('no metrics are available yet', () => {
beforeEach(() => {
mock.onGet(mockApiEndpoint).reply(statusCodes.OK, metricsGroupsAPIResponse);
createShallowWrapper();
});
afterEach(() => {
wrapper.destroy();
});
it('shows the environment selector', () => {
expect(wrapper.vm.$el.querySelector('.js-environments-dropdown')).toBeTruthy();
});
......@@ -77,29 +77,19 @@ describe('Dashboard', () => {
describe('no data found', () => {
beforeEach(done => {
mock.onGet(mockApiEndpoint).reply(statusCodes.OK, metricsGroupsAPIResponse);
createShallowWrapper();
wrapper.vm.$nextTick(done);
});
afterEach(() => {
wrapper.destroy();
});
it('shows the environment selector dropdown', () => {
expect(wrapper.vm.$el.querySelector('.js-environments-dropdown')).toBeTruthy();
});
});
describe('request information to the server', () => {
beforeEach(() => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
});
it('shows up a loading state', done => {
createShallowWrapper({ hasMetrics: true });
createShallowWrapper({ hasMetrics: true }, { methods: {} });
wrapper.vm
.$nextTick()
......@@ -153,17 +143,11 @@ describe('Dashboard', () => {
describe('when all requests have been commited by the store', () => {
beforeEach(() => {
mock.onGet(mockApiEndpoint).reply(statusCodes.OK, metricsGroupsAPIResponse);
createMountedWrapper({ hasMetrics: true }, { stubs: ['graph-group', 'panel-type'] });
setupComponentStore(wrapper);
});
afterEach(() => {
wrapper.destroy();
});
it('renders the environments dropdown with a number of environments', done => {
wrapper.vm
.$nextTick()
......@@ -211,7 +195,7 @@ describe('Dashboard', () => {
wrapper.vm.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
metricsGroupsAPIResponse,
metricsDashboardPayload,
);
wrapper.vm.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`,
......@@ -247,8 +231,6 @@ describe('Dashboard', () => {
describe('when one of the metrics is missing', () => {
beforeEach(done => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
createShallowWrapper({ hasMetrics: true });
setupComponentStore(wrapper);
......@@ -278,10 +260,6 @@ describe('Dashboard', () => {
const findDraggablePanels = () => wrapper.findAll('.js-draggable-panel');
const findRearrangeButton = () => wrapper.find('.js-rearrange-button');
beforeEach(() => {
mock.onGet(mockApiEndpoint).reply(statusCodes.OK, metricsGroupsAPIResponse);
});
beforeEach(done => {
createShallowWrapper({ hasMetrics: true });
......@@ -290,10 +268,6 @@ describe('Dashboard', () => {
wrapper.vm.$nextTick(done);
});
afterEach(() => {
wrapper.destroy();
});
it('wraps vuedraggable', () => {
expect(findDraggablePanels().exists()).toBe(true);
expect(findDraggablePanels().length).toEqual(expectedPanelCount);
......@@ -332,7 +306,7 @@ describe('Dashboard', () => {
it('metrics can be swapped', done => {
const firstDraggable = findDraggables().at(0);
const mockMetrics = [...metricsGroupsAPIResponse.panel_groups[1].panels];
const mockMetrics = [...metricsDashboardPayload.panel_groups[1].panels];
const firstTitle = mockMetrics[0].title;
const secondTitle = mockMetrics[1].title;
......@@ -384,10 +358,6 @@ describe('Dashboard', () => {
wrapper.vm.$nextTick(done);
});
afterEach(() => {
wrapper.destroy();
});
it('renders correctly', () => {
expect(wrapper.isVueInstance()).toBe(true);
expect(wrapper.exists()).toBe(true);
......@@ -398,8 +368,6 @@ describe('Dashboard', () => {
const findEditLink = () => wrapper.find('.js-edit-link');
beforeEach(done => {
mock.onGet(mockApiEndpoint).reply(statusCodes.OK, metricsGroupsAPIResponse);
createShallowWrapper({ hasMetrics: true });
wrapper.vm.$store.commit(
......@@ -409,10 +377,6 @@ describe('Dashboard', () => {
wrapper.vm.$nextTick(done);
});
afterEach(() => {
wrapper.destroy();
});
it('is not present for the default dashboard', () => {
expect(findEditLink().exists()).toBe(false);
});
......@@ -435,8 +399,6 @@ describe('Dashboard', () => {
describe('Dashboard dropdown', () => {
beforeEach(() => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
createMountedWrapper({ hasMetrics: true }, { stubs: ['graph-group', 'panel-type'] });
wrapper.vm.$store.commit(
......@@ -460,8 +422,6 @@ describe('Dashboard', () => {
describe('external dashboard link', () => {
beforeEach(() => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
createMountedWrapper(
{
hasMetrics: true,
......@@ -497,17 +457,11 @@ describe('Dashboard', () => {
const clipboardText = () => link().element.dataset.clipboardText;
beforeEach(done => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
createShallowWrapper({ hasMetrics: true, currentDashboard });
setTimeout(done);
});
afterEach(() => {
wrapper.destroy();
});
it('adds a copy button to the dropdown', () => {
expect(link().text()).toContain('Generate link to chart');
});
......
......@@ -6,7 +6,7 @@ import statusCodes from '~/lib/utils/http_status';
import Dashboard from '~/monitoring/components/dashboard.vue';
import { createStore } from '~/monitoring/stores';
import { propsData, setupComponentStore } from '../init_utils';
import { metricsGroupsAPIResponse, mockApiEndpoint } from '../mock_data';
import { metricsDashboardPayload, mockApiEndpoint } from '../mock_data';
jest.mock('~/lib/utils/url_utility', () => ({
getParameterValues: jest.fn().mockImplementation(param => {
......@@ -43,7 +43,7 @@ describe('dashboard time window', () => {
});
it('shows an error message if invalid url parameters are passed', done => {
mock.onGet(mockApiEndpoint).reply(statusCodes.OK, metricsGroupsAPIResponse);
mock.onGet(mockApiEndpoint).reply(statusCodes.OK, metricsDashboardPayload);
createComponentWrapperMounted({ hasMetrics: true }, { stubs: ['graph-group', 'panel-type'] });
......
import * as types from '~/monitoring/stores/mutation_types';
import {
metricsGroupsAPIResponse,
metricsDashboardPayload,
mockedEmptyResult,
mockedQueryResultPayload,
mockedQueryResultPayloadCoresTotal,
......@@ -23,7 +23,7 @@ export const propsData = {
emptyNoDataSvgPath: '/path/to/no-data.svg',
emptyNoDataSmallSvgPath: '/path/to/no-data-small.svg',
emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
environmentsEndpoint: '/root/hello-prometheus/environments/35',
environmentsEndpoint: '/root/hello-prometheus/-/environments.json',
currentEnvironmentName: 'production',
customMetricsAvailable: false,
customMetricsPath: '',
......@@ -33,7 +33,7 @@ export const propsData = {
export const setupComponentStore = wrapper => {
wrapper.vm.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
metricsGroupsAPIResponse,
metricsDashboardPayload,
);
// Load 3 panels to the dashboard, one with an empty result
......
......@@ -331,81 +331,6 @@ export const mockedQueryResultPayloadCoresTotal = {
],
};
export const metricsGroupsAPIResponse = {
dashboard: 'Environment metrics',
panel_groups: [
{
group: 'Response metrics (NGINX Ingress VTS)',
priority: 10,
panels: [
{
metrics: [
{
id: 'response_metrics_nginx_ingress_throughput_status_code',
label: 'Status Code',
metric_id: 1,
prometheus_endpoint_path:
'/root/autodevops-deploy/environments/32/prometheus/api/v1/query_range?query=sum%28rate%28nginx_upstream_responses_total%7Bupstream%3D~%22%25%7Bkube_namespace%7D-%25%7Bci_environment_slug%7D-.%2A%22%7D%5B2m%5D%29%29+by+%28status_code%29',
query_range:
'sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) by (status_code)',
unit: 'req / sec',
},
],
title: 'Throughput',
type: 'area-chart',
weight: 1,
y_label: 'Requests / Sec',
},
],
},
{
group: 'System metrics (Kubernetes)',
priority: 5,
panels: [
{
title: 'Memory Usage (Pod average)',
type: 'area-chart',
y_label: 'Memory Used per Pod',
weight: 2,
metrics: [
{
id: 'system_metrics_kubernetes_container_memory_average',
query_range:
'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024',
label: 'Pod average',
unit: 'MB',
metric_id: 17,
prometheus_endpoint_path:
'/root/autodevops-deploy/environments/32/prometheus/api/v1/query_range?query=avg%28sum%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+by+%28job%29%29+without+%28job%29+%2F+count%28avg%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+without+%28job%29%29+%2F1024%2F1024',
appearance: {
line: {
width: 2,
},
},
},
],
},
{
title: 'Core Usage (Total)',
type: 'area-chart',
y_label: 'Total Cores',
weight: 3,
metrics: [
{
id: 'system_metrics_kubernetes_container_cores_total',
query_range:
'avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job)',
label: 'Total',
unit: 'cores',
metric_id: 13,
},
],
},
],
},
],
};
export const environmentData = [
{
id: 34,
......@@ -517,6 +442,81 @@ export const metricsDashboardResponse = {
status: 'success',
};
export const metricsDashboardPayload = {
dashboard: 'Environment metrics',
panel_groups: [
{
group: 'Response metrics (NGINX Ingress VTS)',
priority: 10,
panels: [
{
metrics: [
{
id: 'response_metrics_nginx_ingress_throughput_status_code',
label: 'Status Code',
metric_id: 1,
prometheus_endpoint_path:
'/root/autodevops-deploy/environments/32/prometheus/api/v1/query_range?query=sum%28rate%28nginx_upstream_responses_total%7Bupstream%3D~%22%25%7Bkube_namespace%7D-%25%7Bci_environment_slug%7D-.%2A%22%7D%5B2m%5D%29%29+by+%28status_code%29',
query_range:
'sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) by (status_code)',
unit: 'req / sec',
},
],
title: 'Throughput',
type: 'area-chart',
weight: 1,
y_label: 'Requests / Sec',
},
],
},
{
group: 'System metrics (Kubernetes)',
priority: 5,
panels: [
{
title: 'Memory Usage (Pod average)',
type: 'area-chart',
y_label: 'Memory Used per Pod',
weight: 2,
metrics: [
{
id: 'system_metrics_kubernetes_container_memory_average',
query_range:
'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024',
label: 'Pod average',
unit: 'MB',
metric_id: 17,
prometheus_endpoint_path:
'/root/autodevops-deploy/environments/32/prometheus/api/v1/query_range?query=avg%28sum%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+by+%28job%29%29+without+%28job%29+%2F+count%28avg%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+without+%28job%29%29+%2F1024%2F1024',
appearance: {
line: {
width: 2,
},
},
},
],
},
{
title: 'Core Usage (Total)',
type: 'area-chart',
y_label: 'Total Cores',
weight: 3,
metrics: [
{
id: 'system_metrics_kubernetes_container_cores_total',
query_range:
'avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job)',
label: 'Total',
unit: 'cores',
metric_id: 13,
},
],
},
],
},
],
};
export const dashboardGitResponse = [
{
default: true,
......
......@@ -25,7 +25,7 @@ import {
deploymentData,
environmentData,
metricsDashboardResponse,
metricsGroupsAPIResponse,
metricsDashboardPayload,
dashboardGitResponse,
} from '../mock_data';
......@@ -442,7 +442,7 @@ describe('Monitoring store actions', () => {
beforeEach(() => {
state = storeState();
[metric] = metricsDashboardResponse.dashboard.panel_groups[0].panels[0].metrics;
[data] = metricsGroupsAPIResponse.panel_groups[0].panels[0].metrics;
[data] = metricsDashboardPayload.panel_groups[0].panels[0].metrics;
});
it('commits result', done => {
......
......@@ -3,7 +3,7 @@ import mutations from '~/monitoring/stores/mutations';
import * as types from '~/monitoring/stores/mutation_types';
import { metricStates } from '~/monitoring/constants';
import {
metricsGroupsAPIResponse,
metricsDashboardPayload,
mockedEmptyResult,
mockedQueryResultPayload,
mockedQueryResultPayloadCoresTotal,
......@@ -44,7 +44,7 @@ describe('Monitoring store Getters', () => {
setupState({
dashboard: { panel_groups: [] },
});
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsGroupsAPIResponse);
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsDashboardPayload);
groups = state.dashboard.panel_groups;
});
......@@ -53,21 +53,21 @@ describe('Monitoring store Getters', () => {
});
it('on an empty metric with no result, returns NO_DATA', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsGroupsAPIResponse);
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsDashboardPayload);
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, mockedEmptyResult);
expect(getMetricStates()).toEqual([metricStates.NO_DATA]);
});
it('on a metric with a result, returns OK', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsGroupsAPIResponse);
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsDashboardPayload);
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, mockedQueryResultPayload);
expect(getMetricStates()).toEqual([metricStates.OK]);
});
it('on a metric with an error, returns an error', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsGroupsAPIResponse);
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsDashboardPayload);
mutations[types.RECEIVE_METRIC_RESULT_FAILURE](state, {
metricId: groups[0].panels[0].metrics[0].metricId,
});
......@@ -76,7 +76,7 @@ describe('Monitoring store Getters', () => {
});
it('on multiple metrics with results, returns OK', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsGroupsAPIResponse);
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsDashboardPayload);
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, mockedQueryResultPayload);
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, mockedQueryResultPayloadCoresTotal);
......@@ -87,7 +87,7 @@ describe('Monitoring store Getters', () => {
expect(getMetricStates(state.dashboard.panel_groups[1].key)).toEqual([metricStates.OK]);
});
it('on multiple metrics errors', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsGroupsAPIResponse);
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsDashboardPayload);
mutations[types.RECEIVE_METRIC_RESULT_FAILURE](state, {
metricId: groups[0].panels[0].metrics[0].metricId,
......@@ -106,7 +106,7 @@ describe('Monitoring store Getters', () => {
});
it('on multiple metrics with errors', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsGroupsAPIResponse);
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsDashboardPayload);
// An success in 1 group
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, mockedQueryResultPayload);
......@@ -168,27 +168,27 @@ describe('Monitoring store Getters', () => {
});
it('no loaded metric returns empty', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsGroupsAPIResponse);
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsDashboardPayload);
expect(metricsWithData()).toEqual([]);
});
it('an empty metric, returns empty', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsGroupsAPIResponse);
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsDashboardPayload);
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, mockedEmptyResult);
expect(metricsWithData()).toEqual([]);
});
it('a metric with results, it returns a metric', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsGroupsAPIResponse);
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsDashboardPayload);
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, mockedQueryResultPayload);
expect(metricsWithData()).toEqual([mockedQueryResultPayload.metricId]);
});
it('multiple metrics with results, it return multiple metrics', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsGroupsAPIResponse);
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsDashboardPayload);
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, mockedQueryResultPayload);
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, mockedQueryResultPayloadCoresTotal);
......@@ -199,7 +199,7 @@ describe('Monitoring store Getters', () => {
});
it('multiple metrics with results, it returns metrics filtered by group', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsGroupsAPIResponse);
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](state, metricsDashboardPayload);
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, mockedQueryResultPayload);
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, mockedQueryResultPayloadCoresTotal);
......
......@@ -5,7 +5,7 @@ import * as types from '~/monitoring/stores/mutation_types';
import state from '~/monitoring/stores/state';
import { metricStates } from '~/monitoring/constants';
import {
metricsGroupsAPIResponse,
metricsDashboardPayload,
deploymentData,
metricsDashboardResponse,
dashboardGitResponse,
......@@ -23,7 +23,7 @@ describe('Monitoring mutations', () => {
beforeEach(() => {
stateCopy.dashboard.panel_groups = [];
payload = metricsGroupsAPIResponse;
payload = metricsDashboardPayload;
});
it('adds a key to the group', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, payload);
......
......@@ -6,7 +6,7 @@ import * as types from '~/monitoring/stores/mutation_types';
import { createStore } from '~/monitoring/stores';
import axios from '~/lib/utils/axios_utils';
import {
metricsGroupsAPIResponse,
metricsDashboardPayload,
mockedEmptyResult,
mockedQueryResultPayload,
mockedQueryResultPayloadCoresTotal,
......@@ -41,7 +41,7 @@ function setupComponentStore(component) {
// Load 2 panel groups
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
metricsGroupsAPIResponse,
metricsDashboardPayload,
);
// Load 3 panels to the dashboard, one with an empty result
......@@ -98,7 +98,7 @@ describe('Dashboard', () => {
let panelToggle;
let chart;
beforeEach(() => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
mock.onGet(mockApiEndpoint).reply(200, metricsDashboardPayload);
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
......
......@@ -5,6 +5,14 @@ require 'spec_helper'
describe Gitlab::Email::Receiver do
include_context :email_shared_context
shared_examples 'correctly finds the mail key' do
specify do
expect(Gitlab::Email::Handler).to receive(:for).with(an_instance_of(Mail::Message), 'gitlabhq/gitlabhq+auth_token').and_return(handler)
receiver.execute
end
end
context 'when the email contains a valid email address in a header' do
let(:handler) { double(:handler) }
......
......@@ -16,6 +16,40 @@ describe Gitlab::MailRoom do
}
end
shared_examples_for 'only truthy if both enabled and address are truthy' do |target_proc|
context 'with both enabled and address as truthy values' do
it 'is truthy' do
stub_config(enabled: true, address: 'localhost')
expect(target_proc.call).to be_truthy
end
end
context 'with address only as truthy' do
it 'is falsey' do
stub_config(enabled: false, address: 'localhost')
expect(target_proc.call).to be_falsey
end
end
context 'with enabled only as truthy' do
it 'is falsey' do
stub_config(enabled: true, address: nil)
expect(target_proc.call).to be_falsey
end
end
context 'with neither address nor enabled as truthy' do
it 'is falsey' do
stub_config(enabled: false, address: nil)
expect(target_proc.call).to be_falsey
end
end
end
before do
described_class.reset_config!
allow(File).to receive(:exist?).and_return true
......
# frozen_string_literal: true
require 'fast_spec_helper'
require 'support/shared_examples/malicious_regexp_shared_examples'
require 'support/shared_examples/lib/gitlab/malicious_regexp_shared_examples'
require 'support/helpers/stub_feature_flags'
describe Gitlab::UntrustedRegexp::RubySyntax do
......
# frozen_string_literal: true
require 'fast_spec_helper'
require 'support/shared_examples/malicious_regexp_shared_examples'
require 'support/shared_examples/lib/gitlab/malicious_regexp_shared_examples'
describe Gitlab::UntrustedRegexp do
describe '#initialize' do
......
......@@ -27,7 +27,42 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
let(:build) { create(:ci_build, :running, :trace_live, pipeline: pipeline, project: parent) }
let(:subjects) { build.trace_chunks }
it_behaves_like 'fast destroyable'
describe 'Forbid #destroy and #destroy_all' do
it 'does not delete database rows and associted external data' do
expect(external_data_counter).to be > 0
expect(subjects.count).to be > 0
expect { subjects.first.destroy }.to raise_error('`destroy` and `destroy_all` are forbidden. Please use `fast_destroy_all`')
expect { subjects.destroy_all }.to raise_error('`destroy` and `destroy_all` are forbidden. Please use `fast_destroy_all`') # rubocop: disable DestroyAll
expect(subjects.count).to be > 0
expect(external_data_counter).to be > 0
end
end
describe '.fast_destroy_all' do
it 'deletes database rows and associted external data' do
expect(external_data_counter).to be > 0
expect(subjects.count).to be > 0
expect { subjects.fast_destroy_all }.not_to raise_error
expect(subjects.count).to eq(0)
expect(external_data_counter).to eq(0)
end
end
describe '.use_fast_destroy' do
it 'performs cascading delete with fast_destroy_all' do
expect(external_data_counter).to be > 0
expect(subjects.count).to be > 0
expect { parent.destroy }.not_to raise_error
expect(subjects.count).to eq(0)
expect(external_data_counter).to eq(0)
end
end
def external_data_counter
Gitlab::Redis::SharedState.with do |redis|
......
......@@ -176,6 +176,35 @@ describe Projects::UpdatePagesService do
describe 'maximum pages artifacts size' do
let(:metadata) { spy('metadata') }
shared_examples 'pages size limit is' do |size_limit|
context "when size is below the limit" do
before do
allow(metadata).to receive(:total_size).and_return(size_limit - 1.megabyte)
end
it 'updates pages correctly' do
subject.execute
expect(deploy_status.description).not_to be_present
expect(project.pages_metadatum).to be_deployed
end
end
context "when size is above the limit" do
before do
allow(metadata).to receive(:total_size).and_return(size_limit + 1.megabyte)
end
it 'limits the maximum size of gitlab pages' do
subject.execute
expect(deploy_status.description)
.to match(/artifacts for pages are too large/)
expect(deploy_status).to be_script_failure
end
end
end
before do
file = fixture_file_upload('spec/fixtures/pages.zip')
metafile = fixture_file_upload('spec/fixtures/pages.zip.meta')
......
......@@ -4,7 +4,7 @@
#
# Requires a reference:
# let(:reference) { '#42' }
shared_examples 'a reference containing an element node' do
RSpec.shared_examples 'a reference containing an element node' do
let(:inner_html) { 'element <code>node</code> inside' }
let(:reference_with_element) { %{<a href="#{reference}">#{inner_html}</a>} }
......@@ -18,7 +18,7 @@ end
# subject { create(:user) }
# let(:reference) { subject.to_reference }
# let(:subject_name) { 'user' }
shared_examples 'user reference or project reference' do
RSpec.shared_examples 'user reference or project reference' do
shared_examples 'it contains a data- attribute' do
it 'includes a data- attribute' do
doc = reference_filter("Hey #{reference}")
......
# frozen_string_literal: true
shared_context 'valid cluster create params' do
RSpec.shared_context 'valid cluster create params' do
let(:params) do
{
name: 'test-cluster',
......@@ -16,7 +16,7 @@ shared_context 'valid cluster create params' do
end
end
shared_context 'invalid cluster create params' do
RSpec.shared_context 'invalid cluster create params' do
let(:params) do
{
name: 'test-cluster',
......@@ -31,7 +31,7 @@ shared_context 'invalid cluster create params' do
end
end
shared_examples 'create cluster service success' do
RSpec.shared_examples 'create cluster service success' do
it 'creates a cluster object and performs a worker' do
expect(ClusterProvisionWorker).to receive(:perform_async)
......@@ -53,7 +53,7 @@ shared_examples 'create cluster service success' do
end
end
shared_examples 'create cluster service error' do
RSpec.shared_examples 'create cluster service error' do
it 'returns an error' do
expect(ClusterProvisionWorker).not_to receive(:perform_async)
expect { subject }.to change { Clusters::Cluster.count }.by(0)
......
......@@ -3,7 +3,7 @@
# Specifications for behavior common to all objects with executable attributes.
# It can take a `default_params`.
shared_examples 'new issuable record that supports quick actions' do
RSpec.shared_examples 'new issuable record that supports quick actions' do
let!(:project) { create(:project, :repository) }
let(:user) { create(:user).tap { |u| project.add_maintainer(u) } }
let(:assignee) { create(:user) }
......
# frozen_string_literal: true
shared_examples 'issuable update service' do
RSpec.shared_examples 'issuable update service' do
def update_issuable(opts)
described_class.new(project, user, opts).execute(open_issuable)
end
......
# frozen_string_literal: true
require "spec_helper"
shared_examples "migrating a deleted user's associated records to the ghost user" do |record_class, fields|
RSpec.shared_examples "migrating a deleted user's associated records to the ghost user" do |record_class, fields|
record_class_name = record_class.to_s.titleize.downcase
let(:project) do
......
# frozen_string_literal: true
shared_context 'change access checks context' do
RSpec.shared_context 'change access checks context' do
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
let(:user_access) { Gitlab::UserAccess.new(user, project: project) }
......
# frozen_string_literal: true
shared_context 'a GitHub-ish import controller' do
RSpec.shared_context 'a GitHub-ish import controller' do
let(:user) { create(:user) }
let(:token) { "asdasd12345" }
let(:access_params) { { github_access_token: token } }
......
# frozen_string_literal: true
require 'spec_helper'
shared_context 'Ldap::OmniauthCallbacksController' do
RSpec.shared_context 'Ldap::OmniauthCallbacksController' do
include LoginHelpers
include LdapHelpers
......
# frozen_string_literal: true
shared_context :email_shared_context do
RSpec.shared_context :email_shared_context do
let(:mail_key) { "59d8df8370b7e95c5a49fbf86aeb2c93" }
let(:receiver) { Gitlab::Email::Receiver.new(email_raw) }
let(:markdown) { "![image](uploads/image.png)" }
......@@ -18,7 +18,7 @@ shared_context :email_shared_context do
end
end
shared_examples :reply_processing_shared_examples do
RSpec.shared_examples :reply_processing_shared_examples do
context "when the user could not be found" do
before do
user.destroy
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.shared_context 'GroupProjectsFinder context' do
let(:group) { create(:group) }
let(:subgroup) { create(:group, parent: group) }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.shared_context 'IssuesFinder context' do
set(:user) { create(:user) }
set(:user2) { create(:user) }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.shared_context 'MergeRequestsFinder multiple projects with merge requests context' do
include ProjectForksHelper
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.shared_context 'UsersFinder#execute filter by project context' do
set(:normal_user) { create(:user, username: 'johndoe') }
set(:blocked_user) { create(:user, :blocked, username: 'notsorandom') }
......
# frozen_string_literal: true
shared_context 'JSON response' do
RSpec.shared_context 'JSON response' do
let(:json_response) { JSON.parse(response.body) }
end
# frozen_string_literal: true
RSpec.shared_context 'gitlab email notification' do
set(:group) { create(:group) }
set(:subgroup) { create(:group, parent: group) }
set(:project) { create(:project, :repository, name: 'a-known-name', group: group) }
set(:recipient) { create(:user, email: 'recipient@example.com') }
let(:gitlab_sender_display_name) { Gitlab.config.gitlab.email_display_name }
let(:gitlab_sender) { Gitlab.config.gitlab.email_from }
let(:gitlab_sender_reply_to) { Gitlab.config.gitlab.email_reply_to }
let(:new_user_address) { 'newguy@example.com' }
before do
email = recipient.emails.create(email: "notifications@example.com")
recipient.update_attribute(:notification_email, email.email)
stub_incoming_email_setting(enabled: true, address: "reply+%{key}@#{Gitlab.config.gitlab.host}")
end
end
RSpec.shared_context 'reply-by-email is enabled with incoming address without %{key}' do
before do
stub_incoming_email_setting(enabled: true, address: "reply@#{Gitlab.config.gitlab.host}")
end
end
# frozen_string_literal: true
shared_context 'merge request create context' do
RSpec.shared_context 'merge request create context' do
let(:user) { create(:user) }
let(:user2) { create(:user) }
let(:target_project) { create(:project, :public, :repository) }
......
# frozen_string_literal: true
require 'spec_helper'
shared_context 'merge request edit context' do
RSpec.shared_context 'merge request edit context' do
let(:user) { create(:user) }
let(:user2) { create(:user) }
let!(:milestone) { create(:milestone, project: target_project) }
......
# frozen_string_literal: true
shared_context 'merge request allowing collaboration' do
RSpec.shared_context 'merge request allowing collaboration' do
include ProjectForksHelper
let(:canonical) { create(:project, :public, :repository) }
......
# frozen_string_literal: true
shared_context 'rack attack cache store' do
RSpec.shared_context 'rack attack cache store' do
around do |example|
# Instead of test environment's :null_store so the throttles can increment
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
......
# frozen_string_literal: true
Service.available_services_names.each do |service|
shared_context service do
RSpec.shared_context service do
let(:dashed_service) { service.dasherize }
let(:service_method) { "#{service}_service".to_sym }
let(:service_klass) { "#{service}_service".classify.constantize }
......
......@@ -4,7 +4,7 @@
# let(:session) variable
# we do not use a parameter such as |session| because it does not play nice
# with let variables
shared_context 'custom session' do
RSpec.shared_context 'custom session' do
let!(:session) { {} }
around do |example|
......
# frozen_string_literal: true
RSpec.shared_context 'unique ips sign in limit' do
include StubENV
let(:request_context) { Gitlab::RequestContext.instance }
before do
Gitlab::Redis::Cache.with(&:flushall)
Gitlab::Redis::Queues.with(&:flushall)
Gitlab::Redis::SharedState.with(&:flushall)
end
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
Gitlab::CurrentSettings.update!(
unique_ips_limit_enabled: true,
unique_ips_limit_time_window: 10000
)
# Make sure we're working with the same reqeust context everywhere
allow(Gitlab::RequestContext).to receive(:instance).and_return(request_context)
end
def change_ip(ip)
allow(request_context).to receive(:client_ip).and_return(ip)
end
def request_from_ip(ip)
change_ip(ip)
request
response
end
def operation_from_ip(ip)
change_ip(ip)
operation
end
end
......@@ -2,7 +2,7 @@
# Construct an `uploader` variable that is configured to `check_upload_type`
# with `mime_types` and `extensions`.
shared_context 'uploader with type check' do
RSpec.shared_context 'uploader with type check' do
let(:uploader_class) do
Class.new(GitlabUploader) do
include UploadTypeCheck::Concern
......@@ -20,7 +20,7 @@ shared_context 'uploader with type check' do
end
end
shared_context 'stubbed MimeMagic mime type detection' do
RSpec.shared_context 'stubbed MimeMagic mime type detection' do
let(:mime_type) { '' }
let(:magic_mime) { mime_type }
let(:ext_mime) { mime_type }
......
# frozen_string_literal: true
shared_context 'invalid urls' do
RSpec.shared_context 'invalid urls' do
let(:urls_with_CRLF) do
["http://127.0.0.1:333/pa\rth",
"http://127.0.0.1:333/pa\nth",
......
# frozen_string_literal: true
shared_examples_for 'multiple issue boards' do
RSpec.shared_examples 'multiple issue boards' do
context 'authorized user' do
before do
parent.add_maintainer(user)
......
# frozen_string_literal: true
shared_examples 'aborted merge requests for MWPS' do
RSpec.shared_examples 'aborted merge requests for MWPS' do
let(:aborted_message) do
/aborted the automatic merge because target branch was updated/
end
......@@ -23,7 +23,7 @@ shared_examples 'aborted merge requests for MWPS' do
end
end
shared_examples 'maintained merge requests for MWPS' do
RSpec.shared_examples 'maintained merge requests for MWPS' do
it 'does not cancel auto merge' do
expect(merge_request.auto_merge_enabled?).to be_truthy
expect(merge_request.notes).to be_empty
......
# frozen_string_literal: true
shared_examples_for 'correct pipeline information for pipelines for merge requests' do
RSpec.shared_examples 'correct pipeline information for pipelines for merge requests' do
context 'when pipeline for merge request' do
let(:pipeline) { merge_request.all_pipelines.first }
......
# frozen_string_literal: true
shared_examples 'manual playable stage' do |stage_type|
RSpec.shared_examples 'manual playable stage' do |stage_type|
let(:stage) { build(stage_type, status: status) }
describe '#manual_playable?' do
......
# frozen_string_literal: true
shared_examples 'renders correct panels' do
RSpec.shared_examples 'renders correct panels' do
it 'renders correct action on error' do
expect_next_instance_of(ApplicationSettings::UpdateService) do |service|
allow(service).to receive(:execute).and_return(false)
......
# frozen_string_literal: true
require 'spec_helper'
shared_examples 'discussions provider' do
RSpec.shared_examples 'discussions provider' do
it 'returns the expected discussions' do
get :discussions, params: { namespace_id: project.namespace, project_id: project, id: requested_iid }
......
# frozen_string_literal: true
shared_examples_for 'successful response for #cancel_auto_stop' do
RSpec.shared_examples 'successful response for #cancel_auto_stop' do
include GitlabRoutingHelper
context 'when request is html' do
......@@ -42,7 +42,7 @@ shared_examples_for 'successful response for #cancel_auto_stop' do
end
end
shared_examples_for 'failed response for #cancel_auto_stop' do
RSpec.shared_examples 'failed response for #cancel_auto_stop' do
context 'when request is html' do
let(:params) { environment_params(format: :html) }
......
# frozen_string_literal: true
shared_examples 'sets the polling header' do
RSpec.shared_examples 'sets the polling header' do
subject { response.headers[Gitlab::PollingInterval::HEADER_NAME] }
it { is_expected.to eq '1000'}
......
# frozen_string_literal: true
require 'spec_helper'
shared_examples 'disabled when using an external authorization service' do
RSpec.shared_examples 'disabled when using an external authorization service' do
include ExternalAuthorizationServiceHelpers
it 'works when the feature is not enabled' do
......@@ -20,7 +18,7 @@ shared_examples 'disabled when using an external authorization service' do
end
end
shared_examples 'unauthorized when external service denies access' do
RSpec.shared_examples 'unauthorized when external service denies access' do
include ExternalAuthorizationServiceHelpers
it 'allows access when the authorization service allows it' do
......
......@@ -10,7 +10,7 @@ def assign_session_token(provider)
session[:"#{provider}_access_token"] = 'asdasd12345'
end
shared_examples 'a GitHub-ish import controller: POST personal_access_token' do
RSpec.shared_examples 'a GitHub-ish import controller: POST personal_access_token' do
let(:status_import_url) { public_send("status_import_#{provider}_url") }
it "updates access token" do
......@@ -38,7 +38,7 @@ shared_examples 'a GitHub-ish import controller: POST personal_access_token' do
end
end
shared_examples 'a GitHub-ish import controller: GET new' do
RSpec.shared_examples 'a GitHub-ish import controller: GET new' do
let(:status_import_url) { public_send("status_import_#{provider}_url") }
it "redirects to status if we already have a token" do
......@@ -57,7 +57,7 @@ shared_examples 'a GitHub-ish import controller: GET new' do
end
end
shared_examples 'a GitHub-ish import controller: GET status' do
RSpec.shared_examples 'a GitHub-ish import controller: GET status' do
let(:new_import_url) { public_send("new_import_#{provider}_url") }
let(:user) { create(:user) }
let(:repo) { OpenStruct.new(login: 'vim', full_name: 'asd/vim', name: 'vim', owner: { login: 'owner' }) }
......@@ -76,7 +76,7 @@ shared_examples 'a GitHub-ish import controller: GET status' do
get :status, format: :json
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.dig("imported_projects", 0, "id")).to eq(project.id)
expect(json_response.dig("provider_repos", 0, "id")).to eq(repo.id)
expect(json_response.dig("provider_repos", 1, "id")).to eq(org_repo.id)
......@@ -107,7 +107,7 @@ shared_examples 'a GitHub-ish import controller: GET status' do
get :status
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
it "handles an invalid access token" do
......@@ -153,7 +153,7 @@ shared_examples 'a GitHub-ish import controller: GET status' do
it 'filters list of repositories by name' do
get :status, params: { filter: 'emacs' }, format: :json
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.dig("imported_projects").count).to eq(0)
expect(json_response.dig("provider_repos").count).to eq(1)
expect(json_response.dig("provider_repos", 0, "id")).to eq(repo_2.id)
......@@ -173,7 +173,7 @@ shared_examples 'a GitHub-ish import controller: GET status' do
end
end
shared_examples 'a GitHub-ish import controller: POST create' do
RSpec.shared_examples 'a GitHub-ish import controller: POST create' do
let(:user) { create(:user) }
let(:provider_username) { user.username }
let(:provider_user) { OpenStruct.new(login: provider_username) }
......@@ -198,7 +198,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
post :create, format: :json
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
it 'returns 422 response with the base error when the project could not be imported' do
......@@ -212,7 +212,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
post :create, format: :json
expect(response).to have_gitlab_http_status(422)
expect(response).to have_gitlab_http_status(:unprocessable_entity)
expect(json_response['errors']).to eq('Name is invalid, Path is old')
end
......@@ -484,13 +484,13 @@ shared_examples 'a GitHub-ish import controller: POST create' do
post :create, params: { target_namespace: other_namespace.name }, format: :json
expect(response).to have_gitlab_http_status(422)
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
end
end
end
shared_examples 'a GitHub-ish import controller: GET realtime_changes' do
RSpec.shared_examples 'a GitHub-ish import controller: GET realtime_changes' do
let(:user) { create(:user) }
before do
......
# frozen_string_literal: true
shared_examples 'instance statistics availability' do
RSpec.shared_examples 'instance statistics availability' do
let(:user) { create(:user) }
before do
......
# frozen_string_literal: true
shared_examples 'issuable notes filter' do
RSpec.shared_examples 'issuable notes filter' do
let(:params) do
if issuable_parent.is_a?(Project)
{ namespace_id: issuable_parent.namespace, project_id: issuable_parent, id: issuable.iid }
......
# frozen_string_literal: true
shared_examples 'issuables list meta-data' do |issuable_type, action = nil|
RSpec.shared_examples 'issuables list meta-data' do |issuable_type, action = nil|
include ProjectForksHelper
def get_action(action, project, extra_params = {})
......
# frozen_string_literal: true
shared_examples 'issuables requiring filter' do |action|
RSpec.shared_examples 'issuables requiring filter' do |action|
it "doesn't load any issuables if no filter is set" do
expect_any_instance_of(described_class).not_to receive(:issuables_collection)
......
# frozen_string_literal: true
shared_examples 'milestone tabs' do
RSpec.shared_examples 'milestone tabs' do
def go(path, extra_params = {})
params =
case milestone
......
# frozen_string_literal: true
require 'spec_helper'
shared_examples 'paginated collection' do
RSpec.shared_examples 'paginated collection' do
let(:collection) { nil }
let(:last_page) { collection.page.total_pages }
let(:action) { :index }
......
......@@ -17,7 +17,7 @@
# it_behaves_like 'a controller that can serve LFS files', skip_lfs_disabled_tests: true do
# ...
# end
shared_examples 'a controller that can serve LFS files' do |options = {}|
RSpec.shared_examples 'a controller that can serve LFS files' do |options = {}|
let(:lfs_oid) { '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897' }
let(:lfs_size) { '1575078' }
let!(:lfs_object) { create(:lfs_object, oid: lfs_oid, size: lfs_size) }
......
# frozen_string_literal: true
shared_examples 'authenticates sessionless user' do |path, format, params|
RSpec.shared_examples 'authenticates sessionless user' do |path, format, params|
params ||= {}
before do
......@@ -20,14 +20,14 @@ shared_examples 'authenticates sessionless user' do |path, format, params|
get path, params: default_params.merge(private_token: personal_access_token.token)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(controller.current_user).to eq(user)
end
it 'does not log the user in if page is public', if: params[:public] do
get path, params: default_params
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(controller.current_user).to be_nil
end
end
......@@ -48,7 +48,7 @@ shared_examples 'authenticates sessionless user' do |path, format, params|
get path, params: default_params.merge(private_token: personal_access_token.token)
expect(response).not_to have_gitlab_http_status(200)
expect(response).not_to have_gitlab_http_status(:ok)
end
end
......@@ -62,7 +62,7 @@ shared_examples 'authenticates sessionless user' do |path, format, params|
@request.headers['PRIVATE-TOKEN'] = personal_access_token.token
get path, params: default_params
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
end
......@@ -75,7 +75,7 @@ shared_examples 'authenticates sessionless user' do |path, format, params|
get path, params: default_params.merge(feed_token: user.feed_token)
expect(response).to have_gitlab_http_status 200
expect(response).to have_gitlab_http_status(:ok)
end
end
......
# frozen_string_literal: true
shared_examples 'set sort order from user preference' do
RSpec.shared_examples 'set sort order from user preference' do
describe '#set_sort_order_from_user_preference' do
# There is no sorting_field defined in any CE controllers yet,
# however any other field present in user_preferences table can be used for testing.
......
# frozen_string_literal: true
shared_examples 'todos actions' do
RSpec.shared_examples 'todos actions' do
context 'when authorized' do
before do
sign_in(user)
......
# frozen_string_literal: true
shared_examples 'a Trackable Controller' do
RSpec.shared_examples 'a Trackable Controller' do
describe '#track_event' do
before do
sign_in user
......
# frozen_string_literal: true
shared_examples 'update invalid issuable' do |klass|
RSpec.shared_examples 'update invalid issuable' do |klass|
let(:params) do
{
namespace_id: project.namespace.path,
......
# frozen_string_literal: true
shared_examples 'handle uploads' do
RSpec.shared_examples 'handle uploads' do
let(:user) { create(:user) }
let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') }
let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') }
......@@ -287,7 +287,7 @@ shared_examples 'handle uploads' do
end
end
shared_examples 'handle uploads authorize' do
RSpec.shared_examples 'handle uploads authorize' do
describe "POST #authorize" do
context 'when a user is not authorized to upload a file' do
it 'returns 404 status' do
......
# frozen_string_literal: true
shared_examples 'GET #show lists all variables' do
RSpec.shared_examples 'GET #show lists all variables' do
it 'renders the variables as json' do
subject
......@@ -14,7 +14,7 @@ shared_examples 'GET #show lists all variables' do
end
end
shared_examples 'PATCH #update updates variables' do
RSpec.shared_examples 'PATCH #update updates variables' do
let(:variable_attributes) do
{ id: variable.id,
key: variable.key,
......
# frozen_string_literal: true
shared_examples_for 'correctly finds the mail key' do
specify do
expect(Gitlab::Email::Handler).to receive(:for).with(an_instance_of(Mail::Message), 'gitlabhq/gitlabhq+auth_token').and_return(handler)
receiver.execute
end
end
# frozen_string_literal: true
shared_examples 'updated exposed field' do
it 'creates another Evidence object' do
model.send("#{updated_field}=", updated_value)
expect(model.evidence_summary_keys).to include(updated_field)
expect { model.save! }.to change(Evidence, :count).by(1)
expect(updated_json_field).to eq(updated_value)
end
end
shared_examples 'updated non-exposed field' do
it 'does not create any Evidence object' do
model.send("#{updated_field}=", updated_value)
expect(model.evidence_summary_keys).not_to include(updated_field)
expect { model.save! }.not_to change(Evidence, :count)
end
end
shared_examples 'updated field on non-linked entity' do
it 'does not create any Evidence object' do
model.send("#{updated_field}=", updated_value)
expect(model.evidence_summary_keys).to be_empty
expect { model.save! }.not_to change(Evidence, :count)
end
end
# frozen_string_literal: true
shared_examples_for 'fast destroyable' do
describe 'Forbid #destroy and #destroy_all' do
it 'does not delete database rows and associted external data' do
expect(external_data_counter).to be > 0
expect(subjects.count).to be > 0
expect { subjects.first.destroy }.to raise_error('`destroy` and `destroy_all` are forbidden. Please use `fast_destroy_all`')
expect { subjects.destroy_all }.to raise_error('`destroy` and `destroy_all` are forbidden. Please use `fast_destroy_all`') # rubocop: disable DestroyAll
expect(subjects.count).to be > 0
expect(external_data_counter).to be > 0
end
end
describe '.fast_destroy_all' do
it 'deletes database rows and associted external data' do
expect(external_data_counter).to be > 0
expect(subjects.count).to be > 0
expect { subjects.fast_destroy_all }.not_to raise_error
expect(subjects.count).to eq(0)
expect(external_data_counter).to eq(0)
end
end
describe '.use_fast_destroy' do
it 'performs cascading delete with fast_destroy_all' do
expect(external_data_counter).to be > 0
expect(subjects.count).to be > 0
expect { parent.destroy }.not_to raise_error
expect(subjects.count).to eq(0)
expect(external_data_counter).to eq(0)
end
end
end
# frozen_string_literal: true
shared_examples 'archive download buttons' do
RSpec.shared_examples 'archive download buttons' do
let(:path_to_visit) { project_path(project) }
let(:ref) { project.default_branch }
......
# frozen_string_literal: true
shared_examples 'comment on merge request file' do
RSpec.shared_examples 'comment on merge request file' do
it 'adds a comment' do
click_diff_line(find("[id='#{sample_commit.line_code}']"))
......
# frozen_string_literal: true
shared_examples 'dirty submit form' do |selector_args|
RSpec.shared_examples 'dirty submit form' do |selector_args|
selectors = selector_args.is_a?(Array) ? selector_args : [selector_args]
def expect_disabled_state(form, submit_selector, is_disabled = true)
......
# frozen_string_literal: true
shared_examples 'thread comments' do |resource_name|
RSpec.shared_examples 'thread comments' do |resource_name|
let(:form_selector) { '.js-main-target-form' }
let(:dropdown_selector) { "#{form_selector} .comment-type-dropdown" }
let(:toggle_selector) { "#{dropdown_selector} .dropdown-toggle" }
......
# frozen_string_literal: true
shared_examples 'issue sidebar stays collapsed on mobile' do
RSpec.shared_examples 'issue sidebar stays collapsed on mobile' do
before do
resize_screen_xs
end
......
# frozen_string_literal: true
shared_examples 'issuable user dropdown behaviors' do
RSpec.shared_examples 'issuable user dropdown behaviors' do
include FilteredSearchHelpers
before do
......
# frozen_string_literal: true
shared_examples 'multiple assignees merge request' do |action, save_button_title|
RSpec.shared_examples 'multiple assignees merge request' do |action, save_button_title|
it "#{action} a MR with multiple assignees", :js do
find('.js-assignee-search').click
page.within '.dropdown-menu-user' do
......
# frozen_string_literal: true
shared_examples 'project features apply to issuables' do |klass|
RSpec.shared_examples 'project features apply to issuables' do |klass|
let(:described_class) { klass }
let(:group) { create(:group) }
......
# frozen_string_literal: true
shared_examples 'shows public projects' do
RSpec.shared_examples 'shows public projects' do
it 'shows projects' do
expect(page).to have_content(public_project.title)
expect(page).not_to have_content(internal_project.title)
......@@ -9,7 +9,7 @@ shared_examples 'shows public projects' do
end
end
shared_examples 'shows public and internal projects' do
RSpec.shared_examples 'shows public and internal projects' do
it 'shows projects' do
expect(page).to have_content(public_project.title)
expect(page).to have_content(internal_project.title)
......
# frozen_string_literal: true
shared_examples "protected branches > access control > CE" do
RSpec.shared_examples "protected branches > access control > CE" do
ProtectedRefAccess::HUMAN_ACCESS_LEVELS.each do |(access_type_id, access_type_name)|
it "allows creating protected branches that #{access_type_name} can push to" do
visit project_protected_branches_path(project)
......
# frozen_string_literal: true
require 'spec_helper'
shared_examples 'reportable note' do |type|
RSpec.shared_examples 'reportable note' do |type|
include MobileHelpers
include NotesHelper
......
# frozen_string_literal: true
shared_examples 'creating an issue for a thread' do
RSpec.shared_examples 'creating an issue for a thread' do
it 'shows an issue with the title filled in' do
title_field = page.find_field('issue[title]')
......
# frozen_string_literal: true
shared_examples "an autodiscoverable RSS feed with current_user's feed token" do
RSpec.shared_examples "an autodiscoverable RSS feed with current_user's feed token" do
it "has an RSS autodiscovery link tag with current_user's feed token" do
expect(page).to have_css("link[type*='atom+xml'][href*='feed_token=#{user.feed_token}']", visible: false)
end
end
shared_examples "it has an RSS button with current_user's feed token" do
RSpec.shared_examples "it has an RSS button with current_user's feed token" do
it "shows the RSS button with current_user's feed token" do
expect(page)
.to have_css("a:has(.fa-rss)[href*='feed_token=#{user.feed_token}']")
......@@ -14,13 +14,13 @@ shared_examples "it has an RSS button with current_user's feed token" do
end
end
shared_examples "an autodiscoverable RSS feed without a feed token" do
RSpec.shared_examples "an autodiscoverable RSS feed without a feed token" do
it "has an RSS autodiscovery link tag without a feed token" do
expect(page).to have_css("link[type*='atom+xml']:not([href*='feed_token'])", visible: false)
end
end
shared_examples "it has an RSS button without a feed token" do
RSpec.shared_examples "it has an RSS button without a feed token" do
it "shows the RSS button without a feed token" do
expect(page)
.to have_css("a:has(.fa-rss):not([href*='feed_token'])")
......
# frozen_string_literal: true
shared_examples 'top right search form' do
RSpec.shared_examples 'top right search form' do
it 'does not show top right search form' do
expect(page).not_to have_selector('.search')
end
......
# frozen_string_literal: true
shared_examples 'showing user status' do
RSpec.shared_examples 'showing user status' do
let!(:status) { create(:user_status, user: user_with_status, emoji: 'smirk', message: 'Authoring this object') }
it 'shows the status' do
......
# frozen_string_literal: true
shared_examples 'variable list' do
RSpec.shared_examples 'variable list' do
it 'shows list of variables' do
page.within('.js-ci-variable-list-section') do
expect(first('.js-ci-variable-input-key').value).to eq(variable.key)
......
......@@ -3,7 +3,7 @@
# Requires a context containing:
# project
shared_examples 'wiki file attachments' do
RSpec.shared_examples 'wiki file attachments' do
include DropzoneHelper
context 'uploading attachments', :js do
......
# frozen_string_literal: true
shared_examples 'assignee ID filter' do
RSpec.shared_examples 'assignee ID filter' do
it 'returns issuables assigned to that user' do
expect(issuables).to contain_exactly(*expected_issuables)
end
end
shared_examples 'assignee NOT ID filter' do
RSpec.shared_examples 'assignee NOT ID filter' do
it 'returns issuables not assigned to that user' do
expect(issuables).to contain_exactly(*expected_issuables)
end
end
shared_examples 'assignee username filter' do
RSpec.shared_examples 'assignee username filter' do
it 'returns issuables assigned to those users' do
expect(issuables).to contain_exactly(*expected_issuables)
end
end
shared_examples 'assignee NOT username filter' do
RSpec.shared_examples 'assignee NOT username filter' do
it 'returns issuables not assigned to those users' do
expect(issuables).to contain_exactly(*expected_issuables)
end
end
shared_examples 'no assignee filter' do
RSpec.shared_examples 'no assignee filter' do
let(:params) { { assignee_id: 'None' } }
it 'returns issuables not assigned to any assignee' do
......@@ -38,7 +38,7 @@ shared_examples 'no assignee filter' do
end
end
shared_examples 'any assignee filter' do
RSpec.shared_examples 'any assignee filter' do
context '' do
let(:params) { { assignee_id: 'Any' } }
......
# frozen_string_literal: true
require 'spec_helper'
shared_examples 'a finder with external authorization service' do
RSpec.shared_examples 'a finder with external authorization service' do
include ExternalAuthorizationServiceHelpers
let(:user) { create(:user) }
......
# frozen_string_literal: true
require 'spec_helper'
# Shared example for legal queries that are expected to return nil.
# Requires the following let bindings to be defined:
# - post_query: action to send the query
# - path: array of keys from query root to the result
shared_examples 'a failure to find anything' do
RSpec.shared_examples 'a failure to find anything' do
it 'finds nothing' do
post_query
......
# frozen_string_literal: true
require 'spec_helper'
shared_context 'exposing regular notes on a noteable in GraphQL' do
RSpec.shared_context 'exposing regular notes on a noteable in GraphQL' do
include GraphqlHelpers
let(:note) do
......
# frozen_string_literal: true
shared_examples 'a request using Gitlab::UrlBlocker' do
RSpec.shared_examples 'a request using Gitlab::UrlBlocker' do
# Written to test internal patches against 3rd party libraries
#
# Expects the following to be available in the example contexts:
......
# frozen_string_literal: true
shared_examples 'redirecting a legacy path' do |source, target|
include RSpec::Rails::RequestExampleGroup
it "redirects #{source} to #{target} when the resource does not exist" do
expect(get(source)).to redirect_to(target)
end
it "does not redirect #{source} to #{target} when the resource exists" do
resource
expect(get(source)).not_to redirect_to(target)
end
end
shared_examples 'redirecting a legacy project path' do |source, target|
include RSpec::Rails::RequestExampleGroup
it "redirects #{source} to #{target}" do
expect(get(source)).to redirect_to(target)
end
end
# frozen_string_literal: true
shared_examples 'backfill migration for project repositories' do |storage|
RSpec.shared_examples 'backfill migration for project repositories' do |storage|
describe '#perform' do
let(:storage_versions) { storage == :legacy ? [nil, 0] : [1, 2] }
let(:storage_version) { storage_versions.first }
......
# frozen_string_literal: true
shared_examples_for 'common trace features' do
RSpec.shared_examples 'common trace features' do
describe '#html' do
before do
trace.set("12\n34")
......@@ -284,7 +284,7 @@ shared_examples_for 'common trace features' do
end
end
shared_examples_for 'trace with disabled live trace feature' do
RSpec.shared_examples 'trace with disabled live trace feature' do
it_behaves_like 'common trace features'
describe '#read' do
......@@ -618,7 +618,7 @@ shared_examples_for 'trace with disabled live trace feature' do
end
end
shared_examples_for 'trace with enabled live trace feature' do
RSpec.shared_examples 'trace with enabled live trace feature' do
it_behaves_like 'common trace features'
describe '#read' do
......
# frozen_string_literal: true
shared_examples_for 'cycle analytics event' do
RSpec.shared_examples_for 'cycle analytics event' do
let(:params) { {} }
let(:instance) { described_class.new(params) }
......
# frozen_string_literal: true
shared_examples 'diff statistics' do |test_include_stats_flag: true|
RSpec.shared_examples 'diff statistics' do |test_include_stats_flag: true|
subject { described_class.new(diffable, collection_default_args) }
def stub_stats_find_by_path(path, stats_mock)
......@@ -42,7 +42,7 @@ shared_examples 'diff statistics' do |test_include_stats_flag: true|
end
end
shared_examples 'unfoldable diff' do
RSpec.shared_examples 'unfoldable diff' do
let(:subject) { described_class.new(diffable, diff_options: nil) }
it 'calls Gitlab::Diff::File#unfold_diff_lines with correct position' do
......@@ -58,7 +58,7 @@ shared_examples 'unfoldable diff' do
end
end
shared_examples 'cacheable diff collection' do
RSpec.shared_examples 'cacheable diff collection' do
let(:cache) { instance_double(Gitlab::Diff::HighlightCache) }
before do
......
# frozen_string_literal: true
shared_examples 'file finder' do
RSpec.shared_examples 'file finder' do
let(:query) { 'files' }
let(:search_results) { subject.find(query) }
......
# frozen_string_literal: true
shared_examples 'helm commands' do
RSpec.shared_examples 'helm commands' do
describe '#generate_script' do
let(:helm_setup) do
<<~EOS
......
# frozen_string_literal: true
shared_examples 'log import failure' do |importable_column|
RSpec.shared_examples 'log import failure' do |importable_column|
it 'tracks error' do
extra = {
relation_key: relation_key,
......
# frozen_string_literal: true
shared_examples_for 'normalizes a DN' do
RSpec.shared_examples 'normalizes a DN' do
using RSpec::Parameterized::TableSyntax
where(:test_description, :given, :expected) do
......@@ -40,7 +40,7 @@ shared_examples_for 'normalizes a DN' do
end
end
shared_examples_for 'normalizes a DN attribute value' do
RSpec.shared_examples 'normalizes a DN attribute value' do
using RSpec::Parameterized::TableSyntax
where(:test_description, :given, :expected) do
......
......@@ -2,7 +2,7 @@
require 'timeout'
shared_examples 'malicious regexp' do
RSpec.shared_examples 'malicious regexp' do
let(:malicious_text) { 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!' }
let(:malicious_regexp_re2) { '(?i)^(([a-z])+.)+[A-Z]([a-z])+$' }
let(:malicious_regexp_ruby) { '/^(([a-z])+.)+[A-Z]([a-z])+$/i' }
......
# frozen_string_literal: true
shared_examples 'skips validation' do |validation_option|
RSpec.shared_examples 'skips validation' do |validation_option|
it 'skips validation' do
expect(model).not_to receive(:disable_statement_timeout)
expect(model).to receive(:execute).with(/ADD CONSTRAINT/)
......@@ -10,7 +10,7 @@ shared_examples 'skips validation' do |validation_option|
end
end
shared_examples 'performs validation' do |validation_option|
RSpec.shared_examples 'performs validation' do |validation_option|
it 'performs validation' do
expect(model).to receive(:disable_statement_timeout).and_call_original
expect(model).to receive(:execute).with(/statement_timeout/)
......
# frozen_string_literal: true
shared_examples_for "position formatter" do
RSpec.shared_examples "position formatter" do
let(:formatter) { described_class.new(attrs) }
describe '#key' do
......
# frozen_string_literal: true
shared_examples 'a repo type' do
RSpec.shared_examples 'a repo type' do
describe "#identifier_for_repositorable" do
subject { described_class.identifier_for_repositorable(project) }
......
# frozen_string_literal: true
shared_context 'unique ips sign in limit' do
include StubENV
let(:request_context) { Gitlab::RequestContext.instance }
before do
Gitlab::Redis::Cache.with(&:flushall)
Gitlab::Redis::Queues.with(&:flushall)
Gitlab::Redis::SharedState.with(&:flushall)
end
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
Gitlab::CurrentSettings.update!(
unique_ips_limit_enabled: true,
unique_ips_limit_time_window: 10000
)
# Make sure we're working with the same reqeust context everywhere
allow(Gitlab::RequestContext).to receive(:instance).and_return(request_context)
end
def change_ip(ip)
allow(request_context).to receive(:client_ip).and_return(ip)
end
def request_from_ip(ip)
change_ip(ip)
request
response
end
def operation_from_ip(ip)
change_ip(ip)
operation
end
end
shared_examples 'user login operation with unique ip limit' do
RSpec.shared_examples 'user login operation with unique ip limit' do
include_context 'unique ips sign in limit' do
before do
Gitlab::CurrentSettings.update!(unique_ips_limit_per_user: 1)
......@@ -56,7 +18,7 @@ shared_examples 'user login operation with unique ip limit' do
end
end
shared_examples 'user login request with unique ip limit' do |success_status = 200|
RSpec.shared_examples 'user login request with unique ip limit' do |success_status = 200|
include_context 'unique ips sign in limit' do
before do
Gitlab::CurrentSettings.update!(unique_ips_limit_per_user: 1)
......
# frozen_string_literal: true
shared_examples 'a redis usage counter' do |thing, event|
RSpec.shared_examples 'a redis usage counter' do |thing, event|
describe ".count(#{event})", :clean_gitlab_redis_shared_state do
it "increments the #{thing} #{event} counter by 1" do
expect do
......@@ -22,7 +22,7 @@ shared_examples 'a redis usage counter' do |thing, event|
end
end
shared_examples 'a redis usage counter with totals' do |prefix, events|
RSpec.shared_examples 'a redis usage counter with totals' do |prefix, events|
describe 'totals', :clean_gitlab_redis_shared_state do
before do
events.each do |k, n|
......
# frozen_string_literal: true
shared_examples_for 'only truthy if both enabled and address are truthy' do |target_proc|
context 'with both enabled and address as truthy values' do
it 'is truthy' do
stub_config(enabled: true, address: 'localhost')
expect(target_proc.call).to be_truthy
end
end
context 'with address only as truthy' do
it 'is falsey' do
stub_config(enabled: false, address: 'localhost')
expect(target_proc.call).to be_falsey
end
end
context 'with enabled only as truthy' do
it 'is falsey' do
stub_config(enabled: true, address: nil)
expect(target_proc.call).to be_falsey
end
end
context 'with neither address nor enabled as truthy' do
it 'is falsey' do
stub_config(enabled: false, address: nil)
expect(target_proc.call).to be_falsey
end
end
end
# frozen_string_literal: true
shared_context 'gitlab email notification' do
set(:group) { create(:group) }
set(:subgroup) { create(:group, parent: group) }
set(:project) { create(:project, :repository, name: 'a-known-name', group: group) }
set(:recipient) { create(:user, email: 'recipient@example.com') }
let(:gitlab_sender_display_name) { Gitlab.config.gitlab.email_display_name }
let(:gitlab_sender) { Gitlab.config.gitlab.email_from }
let(:gitlab_sender_reply_to) { Gitlab.config.gitlab.email_reply_to }
let(:new_user_address) { 'newguy@example.com' }
before do
email = recipient.emails.create(email: "notifications@example.com")
recipient.update_attribute(:notification_email, email.email)
stub_incoming_email_setting(enabled: true, address: "reply+%{key}@#{Gitlab.config.gitlab.host}")
end
end
shared_context 'reply-by-email is enabled with incoming address without %{key}' do
before do
stub_incoming_email_setting(enabled: true, address: "reply@#{Gitlab.config.gitlab.host}")
end
end
shared_examples 'a multiple recipients email' do
RSpec.shared_examples 'a multiple recipients email' do
it 'is sent to the given recipient' do
is_expected.to deliver_to recipient.notification_email
end
end
shared_examples 'an email sent from GitLab' do
RSpec.shared_examples 'an email sent from GitLab' do
it 'has the characteristics of an email sent from GitLab' do
sender = subject.header[:from].addrs[0]
reply_to = subject.header[:reply_to].addresses
......@@ -43,7 +19,7 @@ shared_examples 'an email sent from GitLab' do
end
end
shared_examples 'an email sent to a user' do
RSpec.shared_examples 'an email sent to a user' do
it 'is sent to user\'s global notification email address' do
expect(subject).to deliver_to(recipient.notification_email)
end
......@@ -59,13 +35,13 @@ shared_examples 'an email sent to a user' do
end
end
shared_examples 'an email that contains a header with author username' do
RSpec.shared_examples 'an email that contains a header with author username' do
it 'has X-GitLab-Author header containing author\'s username' do
is_expected.to have_header 'X-GitLab-Author', user.username
end
end
shared_examples 'an email with X-GitLab headers containing IDs' do
RSpec.shared_examples 'an email with X-GitLab headers containing IDs' do
it 'has X-GitLab-*-ID header' do
is_expected.to have_header "X-GitLab-#{model.class.name}-ID", "#{model.id}"
end
......@@ -79,7 +55,7 @@ shared_examples 'an email with X-GitLab headers containing IDs' do
end
end
shared_examples 'an email with X-GitLab headers containing project details' do
RSpec.shared_examples 'an email with X-GitLab headers containing project details' do
it 'has X-GitLab-Project headers' do
aggregate_failures do
full_path_as_domain = "#{project.name}.#{project.namespace.path}"
......@@ -91,7 +67,7 @@ shared_examples 'an email with X-GitLab headers containing project details' do
end
end
shared_examples 'a new thread email with reply-by-email enabled' do
RSpec.shared_examples 'a new thread email with reply-by-email enabled' do
it 'has the characteristics of a threaded email' do
host = Gitlab.config.gitlab.host
route_key = "#{model.class.model_name.singular_route_key}_#{model.id}"
......@@ -103,7 +79,7 @@ shared_examples 'a new thread email with reply-by-email enabled' do
end
end
shared_examples 'a thread answer email with reply-by-email enabled' do
RSpec.shared_examples 'a thread answer email with reply-by-email enabled' do
include_examples 'an email with X-GitLab headers containing project details'
include_examples 'an email with X-GitLab headers containing IDs'
......@@ -120,7 +96,7 @@ shared_examples 'a thread answer email with reply-by-email enabled' do
end
end
shared_examples 'an email starting a new thread with reply-by-email enabled' do
RSpec.shared_examples 'an email starting a new thread with reply-by-email enabled' do
include_examples 'an email with X-GitLab headers containing project details'
include_examples 'an email with X-GitLab headers containing IDs'
include_examples 'a new thread email with reply-by-email enabled'
......@@ -145,7 +121,7 @@ shared_examples 'an email starting a new thread with reply-by-email enabled' do
end
end
shared_examples 'an answer to an existing thread with reply-by-email enabled' do
RSpec.shared_examples 'an answer to an existing thread with reply-by-email enabled' do
include_examples 'an email with X-GitLab headers containing project details'
include_examples 'an email with X-GitLab headers containing IDs'
include_examples 'a thread answer email with reply-by-email enabled'
......@@ -166,7 +142,7 @@ shared_examples 'an answer to an existing thread with reply-by-email enabled' do
end
end
shared_examples 'it should have Gmail Actions links' do
RSpec.shared_examples 'it should have Gmail Actions links' do
it do
aggregate_failures do
is_expected.to have_body_text('<script type="application/ld+json">')
......@@ -175,7 +151,7 @@ shared_examples 'it should have Gmail Actions links' do
end
end
shared_examples 'it should not have Gmail Actions links' do
RSpec.shared_examples 'it should not have Gmail Actions links' do
it do
aggregate_failures do
is_expected.not_to have_body_text('<script type="application/ld+json">')
......@@ -184,25 +160,25 @@ shared_examples 'it should not have Gmail Actions links' do
end
end
shared_examples 'it should show Gmail Actions View Issue link' do
RSpec.shared_examples 'it should show Gmail Actions View Issue link' do
it_behaves_like 'it should have Gmail Actions links'
it { is_expected.to have_body_text('View Issue') }
end
shared_examples 'it should show Gmail Actions View Merge request link' do
RSpec.shared_examples 'it should show Gmail Actions View Merge request link' do
it_behaves_like 'it should have Gmail Actions links'
it { is_expected.to have_body_text('View Merge request') }
end
shared_examples 'it should show Gmail Actions View Commit link' do
RSpec.shared_examples 'it should show Gmail Actions View Commit link' do
it_behaves_like 'it should have Gmail Actions links'
it { is_expected.to have_body_text('View Commit') }
end
shared_examples 'an unsubscribeable thread' do
RSpec.shared_examples 'an unsubscribeable thread' do
it_behaves_like 'an unsubscribeable thread with incoming address without %{key}'
it 'has a List-Unsubscribe header in the correct format, and a body link' do
......@@ -215,7 +191,7 @@ shared_examples 'an unsubscribeable thread' do
end
end
shared_examples 'an unsubscribeable thread with incoming address without %{key}' do
RSpec.shared_examples 'an unsubscribeable thread with incoming address without %{key}' do
include_context 'reply-by-email is enabled with incoming address without %{key}'
it 'has a List-Unsubscribe header in the correct format, and a body link' do
......@@ -228,7 +204,7 @@ shared_examples 'an unsubscribeable thread with incoming address without %{key}'
end
end
shared_examples 'a user cannot unsubscribe through footer link' do
RSpec.shared_examples 'a user cannot unsubscribe through footer link' do
it 'does not have a List-Unsubscribe header or a body link' do
aggregate_failures do
is_expected.not_to have_header('List-Unsubscribe', /unsubscribe/)
......@@ -237,11 +213,11 @@ shared_examples 'a user cannot unsubscribe through footer link' do
end
end
shared_examples 'an email with a labels subscriptions link in its footer' do
RSpec.shared_examples 'an email with a labels subscriptions link in its footer' do
it { is_expected.to have_body_text('label subscriptions') }
end
shared_examples 'a note email' do
RSpec.shared_examples 'a note email' do
it_behaves_like 'it should have Gmail Actions links'
it 'is sent to the given recipient as the author' do
......@@ -263,7 +239,7 @@ shared_examples 'a note email' do
end
end
shared_examples 'appearance header and footer enabled' do
RSpec.shared_examples 'appearance header and footer enabled' do
it "contains header and footer" do
create :appearance, header_message: "Foo", footer_message: "Bar", email_header_and_footer_enabled: true
......@@ -277,7 +253,7 @@ shared_examples 'appearance header and footer enabled' do
end
end
shared_examples 'appearance header and footer not enabled' do
RSpec.shared_examples 'appearance header and footer not enabled' do
it "does not contain header and footer" do
create :appearance, header_message: "Foo", footer_message: "Bar", email_header_and_footer_enabled: false
......
# frozen_string_literal: true
shared_examples 'having unique enum values' do
RSpec.shared_examples 'having unique enum values' do
described_class.defined_enums.each do |name, enum|
it "has unique values in #{name.inspect}" do
duplicated = enum.group_by(&:last).select { |key, value| value.size > 1 }
......
# frozen_string_literal: true
require 'spec_helper'
shared_examples_for 'AtomicInternalId' do |validate_presence: true|
RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
describe '.has_internal_id' do
describe 'Module inclusion' do
subject { described_class }
......
# frozen_string_literal: true
require "spec_helper"
shared_examples_for "chat service" do |service_name|
RSpec.shared_examples "chat service" do |service_name|
describe "Associations" do
it { is_expected.to belong_to :project }
it { is_expected.to have_one :service_hook }
......
......@@ -30,7 +30,7 @@ RSpec.shared_examples 'chat slash commands service' do
subject { described_class.new }
context 'no token is passed' do
let(:params) { Hash.new }
let(:params) { {} }
it 'returns nil' do
expect(subject.trigger(params)).to be_nil
......
# frozen_string_literal: true
shared_examples_for 'CI variable' do
RSpec.shared_examples 'CI variable' do
it { is_expected.to include_module(HasVariable) }
describe "variable type" do
......
# frozen_string_literal: true
shared_examples 'cluster application core specs' do |application_name|
RSpec.shared_examples 'cluster application core specs' do |application_name|
it { is_expected.to belong_to(:cluster) }
it { is_expected.to validate_presence_of(:cluster) }
......
# frozen_string_literal: true
shared_examples 'cluster application helm specs' do |application_name|
RSpec.shared_examples 'cluster application helm specs' do |application_name|
let(:application) { create(application_name) }
describe '#uninstall_command' do
......
# frozen_string_literal: true
shared_examples 'cluster application initial status specs' do
RSpec.shared_examples 'cluster application initial status specs' do
describe '#status' do
let(:cluster) { create(:cluster, :provided_by_gcp) }
......
# frozen_string_literal: true
shared_examples 'cluster application status specs' do |application_name|
RSpec.shared_examples 'cluster application status specs' do |application_name|
describe '#status_states' do
let(:cluster) { create(:cluster, :provided_by_gcp) }
......
# frozen_string_literal: true
shared_examples 'cluster application version specs' do |application_name|
RSpec.shared_examples 'cluster application version specs' do |application_name|
describe 'update_available?' do
let(:version) { '0.0.0' }
......
# frozen_string_literal: true
shared_examples 'cluster cleanup worker base specs' do
RSpec.shared_examples 'cluster cleanup worker base specs' do
it 'transitions to errored if sidekiq retries exhausted' do
job = { 'args' => [cluster.id, 0], 'jid' => '123' }
......
# frozen_string_literal: true
shared_examples 'provider status' do |factory|
RSpec.shared_examples 'provider status' do |factory|
describe 'state_machine' do
context 'when any => [:created]' do
let(:provider) { build(factory, :creating) }
......
# frozen_string_literal: true
shared_examples_for 'matches_cross_reference_regex? fails fast' do
RSpec.shared_examples 'matches_cross_reference_regex? fails fast' do
it 'fails fast for long strings' do
# took well under 1 second in CI https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/3267#note_172823
expect do
......@@ -9,7 +9,7 @@ shared_examples_for 'matches_cross_reference_regex? fails fast' do
end
end
shared_examples_for 'validates description length with custom validation' do
RSpec.shared_examples 'validates description length with custom validation' do
let(:issuable) { build(:issue, description: 'x' * (::Issuable::DESCRIPTION_LENGTH_MAX + 1)) }
let(:context) { :update }
......@@ -48,7 +48,7 @@ shared_examples_for 'validates description length with custom validation' do
end
end
shared_examples_for 'truncates the description to its allowed maximum length on import' do
RSpec.shared_examples 'truncates the description to its allowed maximum length on import' do
before do
allow(issuable).to receive(:importing?).and_return(true)
end
......
# frozen_string_literal: true
shared_examples 'model with redactable field' do
RSpec.shared_examples 'model with redactable field' do
it 'redacts unsubscribe token' do
model[field] = 'some text /sent_notifications/00000000000000000000000000000000/unsubscribe more text'
......
# frozen_string_literal: true
shared_examples_for 'cycle analytics stage' do
RSpec.shared_examples 'cycle analytics stage' do
let(:valid_params) do
{
name: 'My Stage',
......@@ -111,7 +111,7 @@ shared_examples_for 'cycle analytics stage' do
end
end
shared_examples_for 'cycle analytics label based stage' do
RSpec.shared_examples 'cycle analytics label based stage' do
context 'when creating label based event' do
context 'when the label id is not passed' do
it 'returns validation error when `start_event_label_id` is missing' do
......
# frozen_string_literal: true
shared_examples 'a valid diff note with after commit callback' do
RSpec.shared_examples 'a valid diff note with after commit callback' do
context 'when diff file is fetched from repository' do
before do
allow_any_instance_of(::Gitlab::Diff::Position).to receive(:diff_file).with(project.repository).and_return(diff_file_from_repository)
......
# frozen_string_literal: true
shared_examples_for 'a valid diff positionable note' do |factory_on_commit|
RSpec.shared_examples 'a valid diff positionable note' do |factory_on_commit|
context 'for commit' do
let(:project) { create(:project, :repository) }
let(:commit) { project.commit(sample_commit.id) }
......
......@@ -6,7 +6,7 @@
# Note: You have access to `email_value` which is the email address value
# being currently tested).
shared_examples 'an object with email-formated attributes' do |*attributes|
RSpec.shared_examples 'an object with email-formated attributes' do |*attributes|
attributes.each do |attribute|
describe "specifically its :#{attribute} attribute" do
%w[
......
# frozen_string_literal: true
# This shared example requires a `builder` and `user` variable
shared_examples 'issuable hook data' do |kind|
RSpec.shared_examples 'issuable hook data' do |kind|
let(:data) { builder.build(user: user) }
include_examples 'project hook data' do
......
# frozen_string_literal: true
shared_examples 'label note created from events' do
RSpec.shared_examples 'label note created from events' do
def create_event(params = {})
event_params = { action: :add, label: label, user: user }
resource_key = resource.class.name.underscore.to_s
......
# frozen_string_literal: true
shared_examples_for 'inherited access level as a member of entity' do
RSpec.shared_examples 'inherited access level as a member of entity' do
let(:parent_entity) { create(:group) }
let(:user) { create(:user) }
let(:member) { entity.is_a?(Group) ? entity.group_member(user) : entity.project_member(user) }
......@@ -57,7 +57,7 @@ shared_examples_for 'inherited access level as a member of entity' do
end
end
shared_examples_for '#valid_level_roles' do |entity_name|
RSpec.shared_examples '#valid_level_roles' do |entity_name|
let(:member_user) { create(:user) }
let(:group) { create(:group) }
let(:entity) { create(entity_name) }
......
......@@ -6,7 +6,7 @@
# - let(:backref_text) { "the way that +subject+ should refer to itself in backreferences " }
# - let(:set_mentionable_text) { lambda { |txt| "block that assigns txt to the subject's mentionable_text" } }
shared_context 'mentionable context' do
RSpec.shared_context 'mentionable context' do
let(:project) { subject.project }
let(:author) { subject.author }
......@@ -59,7 +59,7 @@ shared_context 'mentionable context' do
end
end
shared_examples 'a mentionable' do
RSpec.shared_examples 'a mentionable' do
include_context 'mentionable context'
it 'generates a descriptive back-reference' do
......@@ -115,7 +115,7 @@ shared_examples 'a mentionable' do
end
end
shared_examples 'an editable mentionable' do
RSpec.shared_examples 'an editable mentionable' do
include_context 'mentionable context'
it_behaves_like 'a mentionable'
......@@ -196,7 +196,7 @@ shared_examples 'an editable mentionable' do
end
end
shared_examples_for 'mentions in description' do |mentionable_type|
RSpec.shared_examples 'mentions in description' do |mentionable_type|
describe 'when store_mentioned_users_to_db feature disabled' do
before do
stub_feature_flags(store_mentioned_users_to_db: false)
......@@ -246,7 +246,7 @@ shared_examples_for 'mentions in description' do |mentionable_type|
end
end
shared_examples_for 'mentions in notes' do |mentionable_type|
RSpec.shared_examples 'mentions in notes' do |mentionable_type|
context 'when mentionable notes contain mentions' do
let(:user) { create(:user) }
let(:group) { create(:group) }
......@@ -268,7 +268,7 @@ shared_examples_for 'mentions in notes' do |mentionable_type|
end
end
shared_examples_for 'load mentions from DB' do |mentionable_type|
RSpec.shared_examples 'load mentions from DB' do |mentionable_type|
context 'load stored mentions' do
let_it_be(:user) { create(:user) }
let_it_be(:mentioned_user) { create(:user) }
......
# frozen_string_literal: true
shared_examples 'project hook data with deprecateds' do |project_key: :project|
RSpec.shared_examples 'project hook data with deprecateds' do |project_key: :project|
it 'contains project data' do
expect(data[project_key][:name]).to eq(project.name)
expect(data[project_key][:description]).to eq(project.description)
......@@ -19,7 +19,7 @@ shared_examples 'project hook data with deprecateds' do |project_key: :project|
end
end
shared_examples 'project hook data' do |project_key: :project|
RSpec.shared_examples 'project hook data' do |project_key: :project|
it 'contains project data' do
expect(data[project_key][:name]).to eq(project.name)
expect(data[project_key][:description]).to eq(project.description)
......@@ -34,7 +34,7 @@ shared_examples 'project hook data' do |project_key: :project|
end
end
shared_examples 'deprecated repository hook data' do
RSpec.shared_examples 'deprecated repository hook data' do
it 'contains deprecated repository data' do
expect(data[:repository][:name]).to eq(project.name)
expect(data[:repository][:description]).to eq(project.description)
......
# frozen_string_literal: true
shared_examples 'latest successful build for sha or ref' do
RSpec.shared_examples 'latest successful build for sha or ref' do
context 'with many builds' do
let(:other_pipeline) { create_pipeline(project) }
let(:other_build) { create_build(other_pipeline, 'test') }
......
# frozen_string_literal: true
shared_examples 'issue tracker fields' do
RSpec.shared_examples 'issue tracker fields' do
let(:title) { 'custom title' }
let(:description) { 'custom description' }
let(:url) { 'http://issue_tracker.example.com' }
......
......@@ -4,7 +4,7 @@
#
# Requires a context containing:
# subject { Issue or MergeRequest }
shared_examples 'a Taskable' do
RSpec.shared_examples 'a Taskable' do
describe 'with multiple tasks' do
before do
subject.description = <<-EOT.strip_heredoc
......
# frozen_string_literal: true
shared_examples_for 'throttled touch' do
RSpec.shared_examples 'throttled touch' do
describe '#touch' do
it 'updates the updated_at timestamp' do
Timecop.freeze do
......
# frozen_string_literal: true
require 'spec_helper'
shared_examples_for 'UpdateProjectStatistics' do
RSpec.shared_examples 'UpdateProjectStatistics' do
let(:project) { subject.project }
let(:project_statistics_name) { described_class.project_statistics_name }
let(:statistic_attribute) { described_class.statistic_attribute }
......
# frozen_string_literal: true
require 'spec_helper'
shared_examples_for 'has user mentions' do
RSpec.shared_examples 'has user mentions' do
describe '#has_mentions?' do
context 'when no mentions' do
it 'returns false' do
......
# frozen_string_literal: true
require 'spec_helper'
shared_examples_for 'model with uploads' do |supports_fileuploads|
RSpec.shared_examples 'model with uploads' do |supports_fileuploads|
describe '.destroy' do
before do
stub_uploads_object_storage(uploader_class)
......
# frozen_string_literal: true
require 'spec_helper'
shared_examples 'clusterable policies' do
RSpec.shared_examples 'clusterable policies' do
describe '#add_cluster?' do
let(:current_user) { create(:user) }
......
# frozen_string_literal: true
shared_examples 'tag quick action' do
RSpec.shared_examples 'tag quick action' do
context "post note to existing commit" do
it 'tags this commit' do
add_note("/tag #{tag_name} #{tag_message}")
......
# frozen_string_literal: true
shared_examples 'close quick action' do |issuable_type|
RSpec.shared_examples 'close quick action' do |issuable_type|
include Spec::Support::Helpers::Features::NotesHelpers
before do
......
# frozen_string_literal: true
shared_examples 'issuable quick actions' do
RSpec.shared_examples 'issuable quick actions' do
QuickAction = Struct.new(:action_text, :expectation, :before_action, keyword_init: true) do
# Pass a block as :before_action if
# issuable state needs to be changed before
......
# frozen_string_literal: true
shared_examples 'issuable time tracker' do |issuable_type|
RSpec.shared_examples 'issuable time tracker' do |issuable_type|
before do
project.add_maintainer(maintainer)
gitlab_sign_in(maintainer)
......
# frozen_string_literal: true
shared_examples 'board_move quick action' do
RSpec.shared_examples 'board_move quick action' do
end
# frozen_string_literal: true
shared_examples 'create_merge_request quick action' do
RSpec.shared_examples 'create_merge_request quick action' do
context 'create a merge request starting from an issue' do
def expect_mr_quickaction(success, branch_name = nil)
command_message = if branch_name
......
# frozen_string_literal: true
shared_examples 'move quick action' do
RSpec.shared_examples 'move quick action' do
context 'move the issue to another project' do
let(:target_project) { create(:project, :public) }
......
# frozen_string_literal: true
shared_examples 'zoom quick actions' do
RSpec.shared_examples 'zoom quick actions' do
let(:zoom_link) { 'https://zoom.us/j/123456789' }
let(:existing_zoom_link) { 'https://zoom.us/j/123456780' }
let(:invalid_zoom_link) { 'https://invalid-zoom' }
......
# frozen_string_literal: true
shared_examples 'merge quick action' do
RSpec.shared_examples 'merge quick action' do
context 'when the current user can merge the MR' do
before do
sign_in(user)
......
# frozen_string_literal: true
shared_examples_for 'group and project boards' do |route_definition, ee = false|
RSpec.shared_examples 'group and project boards' do |route_definition, ee = false|
let(:root_url) { route_definition.gsub(":id", board_parent.id.to_s) }
before do
......@@ -31,7 +31,7 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
it "returns authentication error" do
get api(root_url)
expect(response).to have_gitlab_http_status(401)
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
......@@ -39,7 +39,7 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
it "returns the issue boards" do
get api(root_url, user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect_schema_match_for(response, 'public_api/v4/boards', ee)
......@@ -63,7 +63,7 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
it 'returns issue board lists' do
get api(url, user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.length).to eq(2)
......@@ -73,7 +73,7 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
it 'returns 404 if board not found' do
get api("#{root_url}/22343/lists", user)
expect(response).to have_gitlab_http_status(404)
expect(response).to have_gitlab_http_status(:not_found)
end
end
......@@ -83,7 +83,7 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
it 'returns a list' do
get api("#{url}/#{dev_list.id}", user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['id']).to eq(dev_list.id)
expect(json_response['label']['name']).to eq(dev_label.title)
expect(json_response['position']).to eq(1)
......@@ -92,7 +92,7 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
it 'returns 404 if list not found' do
get api("#{url}/5324", user)
expect(response).to have_gitlab_http_status(404)
expect(response).to have_gitlab_http_status(:not_found)
end
end
......@@ -102,7 +102,7 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
it 'creates a new issue board list for labels' do
post api(url, user), params: { label_id: ux_label.id }
expect(response).to have_gitlab_http_status(201)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['label']['name']).to eq(ux_label.title)
expect(json_response['position']).to eq(3)
end
......@@ -110,13 +110,13 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
it 'returns 400 when creating a new list if label_id is invalid' do
post api(url, user), params: { label_id: 23423 }
expect(response).to have_gitlab_http_status(400)
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'returns 403 for members with guest role' do
put api("#{url}/#{test_list.id}", guest), params: { position: 1 }
expect(response).to have_gitlab_http_status(403)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
......@@ -126,20 +126,20 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
it "updates a list" do
put api("#{url}/#{test_list.id}", user), params: { position: 1 }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['position']).to eq(1)
end
it "returns 404 error if list id not found" do
put api("#{url}/44444", user), params: { position: 1 }
expect(response).to have_gitlab_http_status(404)
expect(response).to have_gitlab_http_status(:not_found)
end
it "returns 403 for members with guest role" do
put api("#{url}/#{test_list.id}", guest), params: { position: 1 }
expect(response).to have_gitlab_http_status(403)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
......@@ -149,19 +149,19 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
it "rejects a non member from deleting a list" do
delete api("#{url}/#{dev_list.id}", non_member)
expect(response).to have_gitlab_http_status(403)
expect(response).to have_gitlab_http_status(:forbidden)
end
it "rejects a user with guest role from deleting a list" do
delete api("#{url}/#{dev_list.id}", guest)
expect(response).to have_gitlab_http_status(403)
expect(response).to have_gitlab_http_status(:forbidden)
end
it "returns 404 error if list id not found" do
delete api("#{url}/44444", user)
expect(response).to have_gitlab_http_status(404)
expect(response).to have_gitlab_http_status(:not_found)
end
context "when the user is parent owner" do
......@@ -178,7 +178,7 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
it "deletes the list if an admin requests it" do
delete api("#{url}/#{dev_list.id}", owner)
expect(response).to have_gitlab_http_status(204)
expect(response).to have_gitlab_http_status(:no_content)
end
it_behaves_like '412 response' do
......
# frozen_string_literal: true
shared_examples 'rejected container repository access' do |user_type, status|
RSpec.shared_examples 'rejected container repository access' do |user_type, status|
context "for #{user_type}" do
let(:api_user) { users[user_type] }
......@@ -12,7 +12,7 @@ shared_examples 'rejected container repository access' do |user_type, status|
end
end
shared_examples 'returns repositories for allowed users' do |user_type, scope|
RSpec.shared_examples 'returns repositories for allowed users' do |user_type, scope|
context "for #{user_type}" do
it 'returns a list of repositories' do
subject
......@@ -57,7 +57,7 @@ shared_examples 'returns repositories for allowed users' do |user_type, scope|
end
end
shared_examples 'a gitlab tracking event' do |category, action|
RSpec.shared_examples 'a gitlab tracking event' do |category, action|
it "creates a gitlab tracking event #{action}" do
expect(Gitlab::Tracking).to receive(:event).with(category, action, {})
......
# frozen_string_literal: true
shared_examples 'custom attributes endpoints' do |attributable_name|
RSpec.shared_examples 'custom attributes endpoints' do |attributable_name|
let!(:custom_attribute1) { attributable.custom_attributes.create key: 'foo', value: 'foo' }
let!(:custom_attribute2) { attributable.custom_attributes.create key: 'bar', value: 'bar' }
......
# frozen_string_literal: true
shared_examples 'diff discussions API' do |parent_type, noteable_type, id_name|
RSpec.shared_examples 'diff discussions API' do |parent_type, noteable_type, id_name|
describe "GET /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions" do
it "includes diff discussions" do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user)
......
# frozen_string_literal: true
shared_examples 'with cross-reference system notes' do
RSpec.shared_examples 'with cross-reference system notes' do
let(:merge_request) { create(:merge_request) }
let(:project) { merge_request.project }
let(:new_merge_request) { create(:merge_request) }
......@@ -54,7 +54,7 @@ shared_examples 'with cross-reference system notes' do
end
end
shared_examples 'discussions API' do |parent_type, noteable_type, id_name, can_reply_to_individual_notes: false|
RSpec.shared_examples 'discussions API' do |parent_type, noteable_type, id_name, can_reply_to_individual_notes: false|
describe "GET /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions" do
it "returns an array of discussions" do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user)
......
# frozen_string_literal: true
shared_examples 'issuable participants endpoint' do
RSpec.shared_examples 'issuable participants endpoint' do
let(:area) { entity.class.name.underscore.pluralize }
it 'returns participants' do
......
......@@ -4,7 +4,7 @@ def get_issue
json_response.is_a?(Array) ? json_response.detect {|issue| issue['id'] == target_issue.id} : json_response
end
shared_examples 'accessible merge requests count' do
RSpec.shared_examples 'accessible merge requests count' do
it 'returns anonymous accessible merge requests count' do
get api(api_url), params: { scope: 'all' }
......
# frozen_string_literal: true
shared_examples 'creating an issue resolving discussions through the API' do
RSpec.shared_examples 'creating an issue resolving discussions through the API' do
it 'creates a new project issue' do
expect(response).to have_gitlab_http_status(:created)
end
......
# frozen_string_literal: true
shared_examples 'labeled issues with labels and label_name params' do
RSpec.shared_examples 'labeled issues with labels and label_name params' do
shared_examples 'returns label names' do
it 'returns label names' do
expect_paginated_array_response(issue.id)
......
# frozen_string_literal: true
shared_examples 'a 404 response when source is private' do
RSpec.shared_examples 'a 404 response when source is private' do
before do
source.update_column(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
end
......@@ -8,6 +8,6 @@ shared_examples 'a 404 response when source is private' do
it 'returns 404' do
route
expect(response).to have_gitlab_http_status(404)
expect(response).to have_gitlab_http_status(:not_found)
end
end
# frozen_string_literal: true
shared_examples_for 'group and project milestones' do |route_definition|
RSpec.shared_examples 'group and project milestones' do |route_definition|
let(:resource_route) { "#{route}/#{milestone.id}" }
let(:label_1) { create(:label, title: 'label_1', project: project, priority: 1) }
let(:label_2) { create(:label, title: 'label_2', project: project, priority: 2) }
......@@ -12,7 +12,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'returns milestones list' do
get api(route, user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.first['title']).to eq(milestone.title)
......@@ -21,13 +21,13 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'returns a 401 error if user not authenticated' do
get api(route)
expect(response).to have_gitlab_http_status(401)
expect(response).to have_gitlab_http_status(:unauthorized)
end
it 'returns an array of active milestones' do
get api("#{route}/?state=active", user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.length).to eq(1)
......@@ -37,7 +37,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'returns an array of closed milestones' do
get api("#{route}/?state=closed", user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.length).to eq(1)
......@@ -49,7 +49,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
get api(route, user), params: { iids: [closed_milestone.iid, other_milestone.iid] }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
expect(json_response.length).to eq(2)
expect(json_response.map { |m| m['id'] }).to match_array([closed_milestone.id, other_milestone.id])
......@@ -58,7 +58,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'does not return any milestone if none found' do
get api(route, user), params: { iids: [Milestone.maximum(:iid).succ] }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
expect(json_response.length).to eq(0)
end
......@@ -77,7 +77,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'returns a milestone by title' do
get api(route, user), params: { title: 'version2' }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.size).to eq(1)
expect(json_response.first['title']).to eq milestone.title
expect(json_response.first['id']).to eq milestone.id
......@@ -86,7 +86,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'returns a milestone by searching for title' do
get api(route, user), params: { search: 'version2' }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response.size).to eq(1)
expect(json_response.first['title']).to eq milestone.title
......@@ -96,7 +96,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'returns a milestones by searching for description' do
get api(route, user), params: { search: 'open' }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response.size).to eq(1)
expect(json_response.first['title']).to eq milestone.title
......@@ -108,7 +108,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'returns a milestone by id' do
get api(resource_route, user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['title']).to eq(milestone.title)
expect(json_response['iid']).to eq(milestone.iid)
end
......@@ -116,13 +116,13 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'returns 401 error if user not authenticated' do
get api(resource_route)
expect(response).to have_gitlab_http_status(401)
expect(response).to have_gitlab_http_status(:unauthorized)
end
it 'returns a 404 error if milestone id not found' do
get api("#{route}/1234", user)
expect(response).to have_gitlab_http_status(404)
expect(response).to have_gitlab_http_status(:not_found)
end
end
......@@ -130,7 +130,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'creates a new milestone' do
post api(route, user), params: { title: 'new milestone' }
expect(response).to have_gitlab_http_status(201)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['title']).to eq('new milestone')
expect(json_response['description']).to be_nil
end
......@@ -138,7 +138,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'creates a new milestone with description and dates' do
post api(route, user), params: { title: 'new milestone', description: 'release', due_date: '2013-03-02', start_date: '2013-02-02' }
expect(response).to have_gitlab_http_status(201)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['description']).to eq('release')
expect(json_response['due_date']).to eq('2013-03-02')
expect(json_response['start_date']).to eq('2013-02-02')
......@@ -147,19 +147,19 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'returns a 400 error if title is missing' do
post api(route, user)
expect(response).to have_gitlab_http_status(400)
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'returns a 400 error if params are invalid (duplicate title)' do
post api(route, user), params: { title: milestone.title, description: 'release', due_date: '2013-03-02' }
expect(response).to have_gitlab_http_status(400)
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'creates a new milestone with reserved html characters' do
post api(route, user), params: { title: 'foo & bar 1.1 -> 2.2' }
expect(response).to have_gitlab_http_status(201)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['title']).to eq('foo & bar 1.1 -> 2.2')
expect(json_response['description']).to be_nil
end
......@@ -169,7 +169,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'updates a milestone' do
put api(resource_route, user), params: { title: 'updated title' }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['title']).to eq('updated title')
end
......@@ -178,19 +178,19 @@ shared_examples_for 'group and project milestones' do |route_definition|
put api(resource_route, user), params: { due_date: nil }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['due_date']).to be_nil
end
it 'returns a 404 error if milestone id not found' do
put api("#{route}/1234", user), params: { title: 'updated title' }
expect(response).to have_gitlab_http_status(404)
expect(response).to have_gitlab_http_status(:not_found)
end
it 'closes milestone' do
put api(resource_route, user), params: { state_event: 'close' }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['state']).to eq('closed')
end
......@@ -198,7 +198,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'updates milestone with only start date' do
put api(resource_route, user), params: { start_date: Date.tomorrow }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
end
......@@ -209,14 +209,14 @@ shared_examples_for 'group and project milestones' do |route_definition|
delete api(resource_route, reporter)
expect(response).to have_gitlab_http_status(403)
expect(response).to have_gitlab_http_status(:forbidden)
end
it 'deletes the milestone when the user has developer access to the project' do
delete api(resource_route, user)
expect(project.milestones.find_by_id(milestone.id)).to be_nil
expect(response).to have_gitlab_http_status(204)
expect(response).to have_gitlab_http_status(:no_content)
end
end
......@@ -229,7 +229,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'returns issues for a particular milestone' do
get api(issues_route, user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.first['milestone']['title']).to eq(milestone.title)
......@@ -250,14 +250,14 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'matches V4 response schema for a list of issues' do
get api(issues_route, user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/issues')
end
it 'returns a 401 error if user not authenticated' do
get api(issues_route)
expect(response).to have_gitlab_http_status(401)
expect(response).to have_gitlab_http_status(:unauthorized)
end
describe 'confidential issues' do
......@@ -287,7 +287,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'returns confidential issues to team members' do
get api(issues_route, user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
# 2 for projects, 3 for group(which has another project with an issue)
......@@ -301,7 +301,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
get api(issues_route, member)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.size).to eq(1)
......@@ -311,7 +311,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'does not return confidential issues to regular users' do
get api(issues_route, create(:user))
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.size).to eq(1)
......@@ -324,7 +324,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
get api(issues_route, user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
# 2 for projects, 3 for group(which has another project with an issue)
......@@ -347,7 +347,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
another_merge_request
get api(merge_requests_route, user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
expect(json_response.size).to eq(1)
expect(json_response.first['title']).to eq(merge_request.title)
......@@ -371,20 +371,20 @@ shared_examples_for 'group and project milestones' do |route_definition|
get api(not_found_route, user)
expect(response).to have_gitlab_http_status(404)
expect(response).to have_gitlab_http_status(:not_found)
end
it 'returns a 404 if the user has no access to the milestone' do
new_user = create :user
get api(merge_requests_route, new_user)
expect(response).to have_gitlab_http_status(404)
expect(response).to have_gitlab_http_status(:not_found)
end
it 'returns a 401 error if user not authenticated' do
get api(merge_requests_route)
expect(response).to have_gitlab_http_status(401)
expect(response).to have_gitlab_http_status(:unauthorized)
end
it 'returns merge_requests ordered by position asc' do
......@@ -394,7 +394,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
get api(merge_requests_route, user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.size).to eq(2)
......
# frozen_string_literal: true
shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
describe "GET /#{parent_type}/:id/#{noteable_type}/:noteable_id/notes" do
context 'sorting' do
before do
......
# frozen_string_literal: true
shared_examples 'pipelines visibility table' do
RSpec.shared_examples 'pipelines visibility table' do
using RSpec::Parameterized::TableSyntax
let(:ci_user) { create(:user) }
......
# frozen_string_literal: true
shared_examples_for 'allows the "read_user" scope' do |api_version|
RSpec.shared_examples 'allows the "read_user" scope' do |api_version|
let(:version) { api_version || 'v4' }
context 'for personal access tokens' do
......@@ -10,7 +10,7 @@ shared_examples_for 'allows the "read_user" scope' do |api_version|
it 'returns a "200" response' do
get api_call.call(path, user, personal_access_token: token, version: version)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
end
......@@ -20,7 +20,7 @@ shared_examples_for 'allows the "read_user" scope' do |api_version|
it 'returns a "200" response' do
get api_call.call(path, user, personal_access_token: token, version: version)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
end
......@@ -34,7 +34,7 @@ shared_examples_for 'allows the "read_user" scope' do |api_version|
it 'returns a "403" response' do
get api_call.call(path, user, personal_access_token: token, version: version)
expect(response).to have_gitlab_http_status(403)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
......@@ -48,7 +48,7 @@ shared_examples_for 'allows the "read_user" scope' do |api_version|
it 'returns a "200" response' do
get api_call.call(path, user, oauth_access_token: token)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
end
......@@ -58,7 +58,7 @@ shared_examples_for 'allows the "read_user" scope' do |api_version|
it 'returns a "200" response' do
get api_call.call(path, user, oauth_access_token: token)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
end
end
......@@ -68,20 +68,20 @@ shared_examples_for 'allows the "read_user" scope' do |api_version|
it 'returns a "403" response' do
get api_call.call(path, user, oauth_access_token: token)
expect(response).to have_gitlab_http_status(403)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
end
shared_examples_for 'does not allow the "read_user" scope' do
RSpec.shared_examples 'does not allow the "read_user" scope' do
context 'when the requesting token has the "read_user" scope' do
let(:token) { create(:personal_access_token, scopes: ['read_user'], user: user) }
it 'returns a "403" response' do
post api_call.call(path, user, personal_access_token: token), params: attributes_for(:user, projects_limit: 3)
expect(response).to have_gitlab_http_status(403)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
# frozen_string_literal: true
shared_context 'disabled repository' do
RSpec.shared_context 'disabled repository' do
before do
project.project_feature.update!(
repository_access_level: ProjectFeature::DISABLED,
......
# frozen_string_literal: true
shared_examples 'resolvable discussions API' do |parent_type, noteable_type, id_name|
RSpec.shared_examples 'resolvable discussions API' do |parent_type, noteable_type, id_name|
describe "PUT /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions/:discussion_id" do
it "resolves discussion if resolved is true" do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
......
# frozen_string_literal: true
shared_examples 'resource_label_events API' do |parent_type, eventable_type, id_name|
RSpec.shared_examples 'resource_label_events API' do |parent_type, eventable_type, id_name|
describe "GET /#{parent_type}/:id/#{eventable_type}/:noteable_id/resource_label_events" do
context "with local label reference" do
let!(:event) { create_event(label) }
......
......@@ -4,7 +4,7 @@
#
# Requires an API request:
# let(:request) { get api("/projects/#{project.id}/repository/branches", user) }
shared_examples_for '400 response' do
RSpec.shared_examples '400 response' do
let(:message) { nil }
before do
......@@ -21,7 +21,7 @@ shared_examples_for '400 response' do
end
end
shared_examples_for '403 response' do
RSpec.shared_examples '403 response' do
before do
# Fires the request
request
......@@ -32,7 +32,7 @@ shared_examples_for '403 response' do
end
end
shared_examples_for '404 response' do
RSpec.shared_examples '404 response' do
let(:message) { nil }
before do
......@@ -50,7 +50,7 @@ shared_examples_for '404 response' do
end
end
shared_examples_for '412 response' do
RSpec.shared_examples '412 response' do
let(:params) { nil }
let(:success_status) { 204 }
......
# frozen_string_literal: true
shared_examples 'an unauthorized API user' do
RSpec.shared_examples 'an unauthorized API user' do
it { is_expected.to eq(403) }
end
shared_examples 'time tracking endpoints' do |issuable_name|
RSpec.shared_examples 'time tracking endpoints' do |issuable_name|
let(:non_member) { create(:user) }
issuable_collection_name = issuable_name.pluralize
......@@ -19,7 +19,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
it "sets the time estimate for #{issuable_name}" do
post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: '1w' }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['human_time_estimate']).to eq('1w')
end
......@@ -32,7 +32,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
it 'does not modify the original estimate' do
post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: 'foo' }
expect(response).to have_gitlab_http_status(400)
expect(response).to have_gitlab_http_status(:bad_request)
expect(issuable.reload.human_time_estimate).to eq('1w')
end
end
......@@ -41,7 +41,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
it 'updates the estimate' do
post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: '3w1h' }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(issuable.reload.human_time_estimate).to eq('3w 1h')
end
end
......@@ -58,7 +58,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
it "resets the time estimate for #{issuable_name}" do
post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/reset_time_estimate", user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['time_estimate']).to eq(0)
end
end
......@@ -79,7 +79,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
end.to change { issuable.reload.updated_at }
end
expect(response).to have_gitlab_http_status(201)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['human_total_time_spent']).to eq('2h')
end
......@@ -93,7 +93,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user), params: { duration: '-1h' }
expect(response).to have_gitlab_http_status(201)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['total_time_spent']).to eq(3600)
end
end
......@@ -108,7 +108,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
end.not_to change { issuable.reload.updated_at }
end
expect(response).to have_gitlab_http_status(400)
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['message']['time_spent'].first).to match(/exceeds the total time spent/)
end
end
......@@ -128,7 +128,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
end.to change { issuable.reload.updated_at }
end
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['total_time_spent']).to eq(0)
end
end
......@@ -140,7 +140,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
get api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_stats", user)
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['total_time_spent']).to eq(1800)
expect(json_response['time_estimate']).to eq(3600)
end
......
# frozen_string_literal: true
require 'spec_helper'
shared_examples 'a working graphql query' do
RSpec.shared_examples 'a working graphql query' do
include GraphqlHelpers
it 'returns a successful response', :aggregate_failures do
......
# frozen_string_literal: true
shared_examples 'LFS http 200 response' do
RSpec.shared_examples 'LFS http 200 response' do
it_behaves_like 'LFS http expected response code and message' do
let(:response_code) { 200 }
end
end
shared_examples 'LFS http 401 response' do
RSpec.shared_examples 'LFS http 401 response' do
it_behaves_like 'LFS http expected response code and message' do
let(:response_code) { 401 }
end
end
shared_examples 'LFS http 403 response' do
RSpec.shared_examples 'LFS http 403 response' do
it_behaves_like 'LFS http expected response code and message' do
let(:response_code) { 403 }
let(:message) { 'Access forbidden. Check your access level.' }
end
end
shared_examples 'LFS http 501 response' do
RSpec.shared_examples 'LFS http 501 response' do
it_behaves_like 'LFS http expected response code and message' do
let(:response_code) { 501 }
let(:message) { 'Git LFS is not enabled on this GitLab server, contact your admin.' }
end
end
shared_examples 'LFS http 404 response' do
RSpec.shared_examples 'LFS http 404 response' do
it_behaves_like 'LFS http expected response code and message' do
let(:response_code) { 404 }
end
end
shared_examples 'LFS http expected response code and message' do
RSpec.shared_examples 'LFS http expected response code and message' do
let(:response_code) { }
let(:message) { }
......
......@@ -8,7 +8,7 @@
# * requests_per_period
# * period_in_seconds
# * period
shared_examples_for 'rate-limited token-authenticated requests' do
RSpec.shared_examples 'rate-limited token-authenticated requests' do
let(:throttle_types) do
{
"throttle_protected_paths" => "throttle_authenticated_protected_paths_api",
......@@ -134,7 +134,7 @@ end
# * requests_per_period
# * period_in_seconds
# * period
shared_examples_for 'rate-limited web authenticated requests' do
RSpec.shared_examples 'rate-limited web authenticated requests' do
let(:throttle_types) do
{
"throttle_protected_paths" => "throttle_authenticated_protected_paths_web",
......
# frozen_string_literal: true
RSpec.shared_examples 'redirecting a legacy project path' do |source, target|
include RSpec::Rails::RequestExampleGroup
it "redirects #{source} to #{target}" do
expect(get(source)).to redirect_to(target)
end
end
# frozen_string_literal: true
shared_examples 'diff file base entity' do
RSpec.shared_examples 'diff file base entity' do
it 'exposes essential attributes' do
expect(subject).to include(:content_sha, :submodule, :submodule_link,
:submodule_tree_url, :old_path_html,
......@@ -26,7 +26,7 @@ shared_examples 'diff file base entity' do
end
end
shared_examples 'diff file entity' do
RSpec.shared_examples 'diff file entity' do
it_behaves_like 'diff file base entity'
it 'exposes correct attributes' do
......@@ -70,6 +70,6 @@ shared_examples 'diff file entity' do
end
end
shared_examples 'diff file discussion entity' do
RSpec.shared_examples 'diff file discussion entity' do
it_behaves_like 'diff file base entity'
end
# frozen_string_literal: true
shared_examples 'note entity' do
RSpec.shared_examples 'note entity' do
subject { entity.as_json }
context 'basic note' do
......
# frozen_string_literal: true
shared_examples 'logs kubernetes errors' do
RSpec.shared_examples 'logs kubernetes errors' do
let(:error_hash) do
{
service: service.class.name,
......
# frozen_string_literal: true
shared_examples 'boards create service' do
RSpec.shared_examples 'boards create service' do
context 'when parent does not have a board' do
it 'creates a new board' do
expect { service.execute }.to change(Board, :count).by(1)
......
# frozen_string_literal: true
shared_examples 'boards list service' do
RSpec.shared_examples 'boards list service' do
context 'when parent does not have a board' do
it 'creates a new parent board' do
expect { service.execute }.to change(parent.boards, :count).by(1)
......@@ -30,7 +30,7 @@ shared_examples 'boards list service' do
end
end
shared_examples 'multiple boards list service' do
RSpec.shared_examples 'multiple boards list service' do
let(:service) { described_class.new(parent, double) }
let!(:board_B) { create(:board, resource_parent: parent, name: 'B-board') }
let!(:board_c) { create(:board, resource_parent: parent, name: 'c-board') }
......
# frozen_string_literal: true
shared_examples 'issues list service' do
RSpec.shared_examples 'issues list service' do
it 'delegates search to IssuesFinder' do
params = { board_id: board.id, id: list1.id }
......
# frozen_string_literal: true
shared_examples 'issues move service' do |group|
RSpec.shared_examples 'issues move service' do |group|
shared_examples 'updating timestamps' do
it 'updates updated_at' do
expect {described_class.new(parent, user, params).execute(issue)}
......
# frozen_string_literal: true
shared_examples 'lists destroy service' do
RSpec.shared_examples 'lists destroy service' do
context 'when list type is label' do
it 'removes list from board' do
list = create(:list, board: board)
......
# frozen_string_literal: true
shared_examples 'lists list service' do
RSpec.shared_examples 'lists list service' do
context 'when the board has a backlog list' do
let!(:backlog_list) { create(:backlog_list, board: board) }
......
# frozen_string_literal: true
shared_examples 'lists move service' do
RSpec.shared_examples 'lists move service' do
let!(:planning) { create(:list, board: board, position: 0) }
let!(:development) { create(:list, board: board, position: 1) }
let!(:review) { create(:list, board: board, position: 2) }
......
# frozen_string_literal: true
shared_examples 'check ingress ip executions' do |app_name|
RSpec.shared_examples 'check ingress ip executions' do |app_name|
describe '#execute' do
let(:application) { create(app_name, :installed) }
let(:service) { described_class.new(application) }
......
# frozen_string_literal: true
shared_examples 'system note creation' do |update_params, note_text|
RSpec.shared_examples 'system note creation' do |update_params, note_text|
subject { described_class.new(project, user).execute(issuable, old_labels: []) }
before do
......@@ -17,7 +17,7 @@ shared_examples 'system note creation' do |update_params, note_text|
end
end
shared_examples 'WIP notes creation' do |wip_action|
RSpec.shared_examples 'WIP notes creation' do |wip_action|
subject { described_class.new(project, user).execute(issuable, old_labels: []) }
it 'creates WIP toggle and title change notes' do
......@@ -28,7 +28,7 @@ shared_examples 'WIP notes creation' do |wip_action|
end
end
shared_examples_for 'a note with overridable created_at' do
RSpec.shared_examples 'a note with overridable created_at' do
let(:noteable) { create(:issue, project: project, system_note_timestamp: Time.at(42)) }
it 'the note has the correct time' do
......@@ -36,7 +36,7 @@ shared_examples_for 'a note with overridable created_at' do
end
end
shared_examples_for 'a system note' do |params|
RSpec.shared_examples 'a system note' do |params|
let(:expected_noteable) { noteable }
let(:commit_count) { nil }
......
......@@ -6,7 +6,7 @@
# describe MyCountService, :use_clean_rails_memory_store_caching do
# it_behaves_like 'a counter caching service'
# end
shared_examples 'a counter caching service' do
RSpec.shared_examples 'a counter caching service' do
describe '#count' do
it 'caches the count', :request_store do
subject.delete_cache
......
# frozen_string_literal: true
shared_examples 'error tracking service data not ready' do |service_call|
RSpec.shared_examples 'error tracking service data not ready' do |service_call|
context "when #{service_call} returns nil" do
before do
expect(error_tracking_setting)
......@@ -14,7 +14,7 @@ shared_examples 'error tracking service data not ready' do |service_call|
end
end
shared_examples 'error tracking service sentry error handling' do |service_call|
RSpec.shared_examples 'error tracking service sentry error handling' do |service_call|
context "when #{service_call} returns error" do
before do
allow(error_tracking_setting)
......@@ -35,7 +35,7 @@ shared_examples 'error tracking service sentry error handling' do |service_call|
end
end
shared_examples 'error tracking service http status handling' do |service_call|
RSpec.shared_examples 'error tracking service http status handling' do |service_call|
context "when #{service_call} returns error with http_status" do
before do
allow(error_tracking_setting)
......@@ -56,7 +56,7 @@ shared_examples 'error tracking service http status handling' do |service_call|
end
end
shared_examples 'error tracking service unauthorized user' do
RSpec.shared_examples 'error tracking service unauthorized user' do
context 'with unauthorized user' do
let(:unauthorized_user) { create(:user) }
......@@ -74,7 +74,7 @@ shared_examples 'error tracking service unauthorized user' do
end
end
shared_examples 'error tracking service disabled' do
RSpec.shared_examples 'error tracking service disabled' do
context 'with error tracking disabled' do
before do
error_tracking_setting.enabled = false
......
# frozen_string_literal: true
shared_examples 'gitlab projects import validations' do
RSpec.shared_examples 'gitlab projects import validations' do
context 'with an invalid path' do
let(:path) { '/invalid-path/' }
......
# frozen_string_literal: true
shared_examples 'cache counters invalidator' do
RSpec.shared_examples 'cache counters invalidator' do
it 'invalidates counter cache for assignees' do
expect_any_instance_of(User).to receive(:invalidate_merge_request_cache_counts)
......@@ -8,7 +8,7 @@ shared_examples 'cache counters invalidator' do
end
end
shared_examples 'system notes for milestones' do
RSpec.shared_examples 'system notes for milestones' do
def update_issuable(opts)
issuable = try(:issue) || try(:merge_request)
described_class.new(project, user, opts).execute(issuable)
......@@ -39,7 +39,7 @@ shared_examples 'system notes for milestones' do
end
end
shared_examples 'updating a single task' do
RSpec.shared_examples 'updating a single task' do
def update_issuable(opts)
issuable = try(:issue) || try(:merge_request)
described_class.new(project, user, opts).execute(issuable)
......
# frozen_string_literal: true
shared_examples_for 'misconfigured dashboard service response' do |status_code, message = nil|
RSpec.shared_examples 'misconfigured dashboard service response' do |status_code, message = nil|
it 'returns an appropriate message and status code', :aggregate_failures do
result = service_call
......@@ -11,7 +11,7 @@ shared_examples_for 'misconfigured dashboard service response' do |status_code,
end
end
shared_examples_for 'valid dashboard service response for schema' do
RSpec.shared_examples 'valid dashboard service response for schema' do
it 'returns a json representation of the dashboard' do
result = service_call
......@@ -22,13 +22,13 @@ shared_examples_for 'valid dashboard service response for schema' do
end
end
shared_examples_for 'valid dashboard service response' do
RSpec.shared_examples 'valid dashboard service response' do
let(:dashboard_schema) { JSON.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/dashboard.json')) }
it_behaves_like 'valid dashboard service response for schema'
end
shared_examples_for 'caches the unprocessed dashboard for subsequent calls' do
RSpec.shared_examples 'caches the unprocessed dashboard for subsequent calls' do
it do
expect(YAML).to receive(:safe_load).once.and_call_original
......@@ -37,13 +37,13 @@ shared_examples_for 'caches the unprocessed dashboard for subsequent calls' do
end
end
shared_examples_for 'valid embedded dashboard service response' do
RSpec.shared_examples 'valid embedded dashboard service response' do
let(:dashboard_schema) { JSON.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/embedded_dashboard.json')) }
it_behaves_like 'valid dashboard service response for schema'
end
shared_examples_for 'raises error for users with insufficient permissions' do
RSpec.shared_examples 'raises error for users with insufficient permissions' do
context 'when the user does not have sufficient access' do
let(:user) { build(:user) }
......
......@@ -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.
shared_examples 'project emails are disabled' do
RSpec.shared_examples 'project emails are disabled' do
let(:target_project) { notification_target.is_a?(Project) ? notification_target : notification_target.project }
before do
......@@ -28,7 +28,7 @@ shared_examples 'project emails are disabled' do
end
end
shared_examples 'group emails are disabled' do
RSpec.shared_examples 'group emails are disabled' do
let(:target_group) { notification_target.is_a?(Group) ? notification_target : notification_target.project.group }
before do
......@@ -53,7 +53,7 @@ shared_examples 'group emails are disabled' do
end
end
shared_examples 'sends notification only to a maximum of ten, most recently active group owners' do
RSpec.shared_examples 'sends notification only to a maximum of ten, most recently active group owners' do
let(:owners) { create_list(:user, 12, :with_sign_ins) }
before do
......@@ -75,7 +75,7 @@ shared_examples 'sends notification only to a maximum of ten, most recently acti
end
end
shared_examples 'sends notification only to a maximum of ten, most recently active project maintainers' do
RSpec.shared_examples 'sends notification only to a maximum of ten, most recently active project maintainers' do
let(:maintainers) { create_list(:user, 12, :with_sign_ins) }
before do
......
# frozen_string_literal: true
shared_examples 'pages size limit is' do |size_limit|
RSpec.shared_examples 'pages size limit is' do |size_limit|
context "when size is below the limit" do
before do
allow(metadata).to receive(:total_size).and_return(size_limit - 1.megabyte)
......
# frozen_string_literal: true
shared_examples "matches the method pattern" do |method|
RSpec.shared_examples "matches the method pattern" do |method|
let(:target) { subject }
let(:args) { nil }
let(:pattern) { patterns[method] }
......@@ -12,7 +12,7 @@ shared_examples "matches the method pattern" do |method|
end
end
shared_examples "builds correct paths" do |**patterns|
RSpec.shared_examples "builds correct paths" do |**patterns|
let(:patterns) { patterns }
before do
......
# frozen_string_literal: true
shared_context 'with storage' do |store, **stub_params|
RSpec.shared_context 'with storage' do |store, **stub_params|
before do
subject.object_store = store
end
end
shared_examples "migrates" do |to_store:, from_store: nil|
RSpec.shared_examples "migrates" do |to_store:, from_store: nil|
let(:to) { to_store }
let(:from) { from_store || subject.object_store }
......
......@@ -5,13 +5,13 @@ def check_content_matches_extension!(file = double(read: nil, path: ''))
uploader.check_content_matches_extension!(magic_file)
end
shared_examples 'upload passes content type check' do
RSpec.shared_examples 'upload passes content type check' do
it 'does not raise error' do
expect { check_content_matches_extension! }.not_to raise_error
end
end
shared_examples 'upload fails content type check' do
RSpec.shared_examples 'upload fails content type check' do
it 'raises error' do
expect { check_content_matches_extension! }.to raise_error(CarrierWave::IntegrityError)
end
......@@ -42,7 +42,7 @@ def upload_type_checked_fixtures(upload_fixtures)
end
end
shared_examples 'type checked uploads' do |upload_fixtures = nil, filenames: nil|
RSpec.shared_examples 'type checked uploads' do |upload_fixtures = nil, filenames: nil|
it 'check type' do
upload_fixtures = Array(upload_fixtures)
filenames = Array(filenames)
......@@ -55,7 +55,7 @@ shared_examples 'type checked uploads' do |upload_fixtures = nil, filenames: nil
end
end
shared_examples 'skipped type checked uploads' do |upload_fixtures = nil, filenames: nil|
RSpec.shared_examples 'skipped type checked uploads' do |upload_fixtures = nil, filenames: nil|
it 'skip type check' do
expect(uploader).not_to receive(:check_content_matches_extension!)
......
# frozen_string_literal: true
shared_examples 'has nav sidebar' do
RSpec.shared_examples 'has nav sidebar' do
it 'has collapsed nav sidebar on mobile' do
render
......
# frozen_string_literal: true
# Expects `worker_class` to be defined
shared_examples_for 'reenqueuer' do
RSpec.shared_examples 'reenqueuer' do
subject(:job) { worker_class.new }
before do
......@@ -28,7 +28,7 @@ end
# let(:rate_limited_method) { subject.perform }
# end
#
shared_examples_for 'it is rate limited to 1 call per' do |minimum_duration|
RSpec.shared_examples 'it is rate limited to 1 call per' do |minimum_duration|
before do
# Allow Timecop freeze and travel without the block form
Timecop.safe_mode = false
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment