Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
5b80d465ae
commit
4e8c8922da
24 changed files with 135 additions and 127 deletions
|
@ -128,13 +128,11 @@ update-storybook-yarn-cache:
|
|||
- tmp/tests/frontend/
|
||||
- knapsack/
|
||||
|
||||
# In gitlab-foss, generates FOSS fixtures. In gitlab, generates FOSS & EE fixtures.
|
||||
# That way, we don't need to have two separate jobs.
|
||||
rspec-all frontend_fixture:
|
||||
rspec frontend_fixture:
|
||||
extends:
|
||||
- .frontend-fixtures-base
|
||||
- .frontend:rules:default-frontend-jobs
|
||||
parallel: 5
|
||||
parallel: 2
|
||||
|
||||
rspec frontend_fixture as-if-foss:
|
||||
extends:
|
||||
|
@ -142,6 +140,12 @@ rspec frontend_fixture as-if-foss:
|
|||
- .frontend:rules:default-frontend-jobs-as-if-foss
|
||||
- .as-if-foss
|
||||
|
||||
rspec-ee frontend_fixture:
|
||||
extends:
|
||||
- .frontend-fixtures-base
|
||||
- .frontend:rules:default-frontend-jobs-ee
|
||||
parallel: 3
|
||||
|
||||
graphql-schema-dump:
|
||||
variables:
|
||||
SETUP_DB: "false"
|
||||
|
@ -192,7 +196,9 @@ jest:
|
|||
- .frontend:rules:jest
|
||||
needs:
|
||||
- job: "detect-tests"
|
||||
- job: "rspec-all frontend_fixture"
|
||||
- job: "rspec frontend_fixture"
|
||||
- job: "rspec-ee frontend_fixture"
|
||||
optional: true
|
||||
artifacts:
|
||||
name: coverage-frontend
|
||||
expire_in: 31d
|
||||
|
@ -219,7 +225,9 @@ jest-integration:
|
|||
script:
|
||||
- run_timed_command "yarn jest:integration --ci"
|
||||
needs:
|
||||
- job: "rspec-all frontend_fixture"
|
||||
- job: "rspec frontend_fixture"
|
||||
- job: "rspec-ee frontend_fixture"
|
||||
optional: true
|
||||
- job: "graphql-schema-dump"
|
||||
|
||||
jest-as-if-foss:
|
||||
|
@ -333,7 +341,9 @@ startup-css-check:
|
|||
- .frontend:rules:default-frontend-jobs
|
||||
needs:
|
||||
- job: "compile-test-assets"
|
||||
- job: "rspec-all frontend_fixture"
|
||||
- job: "rspec frontend_fixture"
|
||||
- job: "rspec-ee frontend_fixture"
|
||||
optional: true
|
||||
|
||||
startup-css-check as-if-foss:
|
||||
extends:
|
||||
|
|
|
@ -495,6 +495,13 @@
|
|||
- <<: *if-default-refs
|
||||
changes: *code-backstage-patterns
|
||||
|
||||
.frontend:rules:default-frontend-jobs-ee:
|
||||
rules:
|
||||
- <<: *if-not-ee
|
||||
when: never
|
||||
- <<: *if-default-refs
|
||||
changes: *code-backstage-patterns
|
||||
|
||||
.frontend:rules:default-frontend-jobs-as-if-foss:
|
||||
rules:
|
||||
- <<: *if-not-ee
|
||||
|
|
|
@ -29,7 +29,8 @@ update-tests-metadata:
|
|||
- retrieve-tests-metadata
|
||||
- setup-test-env
|
||||
- rspec migration pg12
|
||||
- rspec-all frontend_fixture
|
||||
- rspec frontend_fixture
|
||||
- rspec-ee frontend_fixture
|
||||
- rspec unit pg12
|
||||
- rspec integration pg12
|
||||
- rspec system pg12
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script>
|
||||
import { GlLink, GlLoadingIcon, GlPagination, GlTable } from '@gitlab/ui';
|
||||
import { GlLink, GlLoadingIcon, GlPagination, GlTable, GlAlert } from '@gitlab/ui';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
|
||||
import { DEFAULT_PER_PAGE } from '~/api';
|
||||
import createFlash from '~/flash';
|
||||
import { fetchOverrides } from '~/integrations/overrides/api';
|
||||
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
|
||||
import { truncateNamespace } from '~/lib/utils/text_utility';
|
||||
|
@ -16,6 +16,7 @@ export default {
|
|||
GlLoadingIcon,
|
||||
GlPagination,
|
||||
GlTable,
|
||||
GlAlert,
|
||||
ProjectAvatar,
|
||||
},
|
||||
props: {
|
||||
|
@ -36,6 +37,7 @@ export default {
|
|||
overrides: [],
|
||||
page: 1,
|
||||
totalItems: 0,
|
||||
errorMessage: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -49,6 +51,7 @@ export default {
|
|||
methods: {
|
||||
loadOverrides(page = this.page) {
|
||||
this.isLoading = true;
|
||||
this.errorMessage = null;
|
||||
|
||||
fetchOverrides(this.overridesPath, {
|
||||
page,
|
||||
|
@ -61,11 +64,9 @@ export default {
|
|||
this.overrides = data;
|
||||
})
|
||||
.catch((error) => {
|
||||
createFlash({
|
||||
message: this.$options.i18n.defaultErrorMessage,
|
||||
error,
|
||||
captureError: true,
|
||||
});
|
||||
this.errorMessage = this.$options.i18n.defaultErrorMessage;
|
||||
|
||||
Sentry.captureException(error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false;
|
||||
|
@ -85,7 +86,11 @@ export default {
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<gl-alert v-if="errorMessage" variant="danger" :dismissible="false">
|
||||
{{ errorMessage }}
|
||||
</gl-alert>
|
||||
<gl-table
|
||||
v-else
|
||||
:items="overrides"
|
||||
:fields="$options.fields"
|
||||
:busy="isLoading"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { GlButton, GlLoadingIcon, GlIcon, GlLink, GlBadge, GlSafeHtmlDirective } from '@gitlab/ui';
|
||||
import { GlButton, GlLoadingIcon, GlLink, GlBadge, GlSafeHtmlDirective } from '@gitlab/ui';
|
||||
import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
|
||||
import { EXTENSION_ICON_CLASS } from '../../constants';
|
||||
import StatusIcon from './status_icon.vue';
|
||||
|
@ -14,7 +14,6 @@ export default {
|
|||
components: {
|
||||
GlButton,
|
||||
GlLoadingIcon,
|
||||
GlIcon,
|
||||
GlLink,
|
||||
GlBadge,
|
||||
SmartVirtualList,
|
||||
|
@ -139,9 +138,7 @@ export default {
|
|||
class="report-block-container"
|
||||
>
|
||||
<li v-for="data in fullData" :key="data.id" class="d-flex align-items-center">
|
||||
<div v-if="data.icon" :class="data.icon.class" class="d-flex">
|
||||
<gl-icon :name="data.icon.name" :size="24" />
|
||||
</div>
|
||||
<status-icon v-if="data.icon" :icon-name="data.icon.name" :size="12" />
|
||||
<div
|
||||
class="gl-mt-2 gl-mb-2 align-content-around align-items-start flex-wrap align-self-center d-flex"
|
||||
>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
|
||||
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
|
||||
import { EXTENSION_ICON_CLASS, EXTENSION_ICONS } from '../../constants';
|
||||
import { EXTENSION_ICON_CLASS, EXTENSION_ICON_NAMES } from '../../constants';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -11,41 +11,48 @@ export default {
|
|||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
isLoading: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
iconName: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 16,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
iconAriaLabel() {
|
||||
const statusLabel = Object.keys(EXTENSION_ICONS).find(
|
||||
(k) => EXTENSION_ICONS[k] === this.iconName,
|
||||
);
|
||||
|
||||
return `${capitalizeFirstCharacter(statusLabel)} ${this.name}`;
|
||||
return `${capitalizeFirstCharacter(this.iconName)} ${this.name}`;
|
||||
},
|
||||
},
|
||||
EXTENSION_ICON_NAMES,
|
||||
EXTENSION_ICON_CLASS,
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="[$options.EXTENSION_ICON_CLASS[iconName], { 'mr-widget-extension-icon': !isLoading }]"
|
||||
:class="[
|
||||
$options.EXTENSION_ICON_CLASS[iconName],
|
||||
{ 'mr-widget-extension-icon': !isLoading && size === 16 },
|
||||
]"
|
||||
class="align-self-center gl-rounded-full gl-mr-3 gl-relative gl-p-2"
|
||||
>
|
||||
<gl-loading-icon v-if="isLoading" size="md" inline class="gl-display-block" />
|
||||
<gl-icon
|
||||
v-else
|
||||
:name="iconName"
|
||||
:size="16"
|
||||
:name="$options.EXTENSION_ICON_NAMES[iconName]"
|
||||
:size="size"
|
||||
:aria-label="iconAriaLabel"
|
||||
class="gl-display-block"
|
||||
/>
|
||||
|
|
|
@ -93,17 +93,30 @@ export const stateToComponentMap = {
|
|||
};
|
||||
|
||||
export const EXTENSION_ICONS = {
|
||||
failed: 'failed',
|
||||
warning: 'warning',
|
||||
success: 'success',
|
||||
neutral: 'neutral',
|
||||
error: 'error',
|
||||
notice: 'notice',
|
||||
};
|
||||
|
||||
export const EXTENSION_ICON_NAMES = {
|
||||
failed: 'status-failed',
|
||||
warning: 'status-alert',
|
||||
success: 'status-success',
|
||||
neutral: 'status-neutral',
|
||||
error: 'status-alert',
|
||||
notice: 'status-alert',
|
||||
};
|
||||
|
||||
export const EXTENSION_ICON_CLASS = {
|
||||
[EXTENSION_ICONS.failed]: 'gl-text-red-500',
|
||||
[EXTENSION_ICONS.warning]: 'gl-text-orange-500',
|
||||
[EXTENSION_ICONS.success]: 'gl-text-green-500',
|
||||
[EXTENSION_ICONS.neutral]: 'gl-text-gray-400',
|
||||
failed: 'gl-text-red-500',
|
||||
warning: 'gl-text-orange-500',
|
||||
success: 'gl-text-green-500',
|
||||
neutral: 'gl-text-gray-400',
|
||||
error: 'gl-text-red-500',
|
||||
notice: 'gl-text-gray-500',
|
||||
};
|
||||
|
||||
export { STATE_MACHINE };
|
||||
|
|
|
@ -45,10 +45,7 @@ export default {
|
|||
// Icon to get rendered on the side of each row
|
||||
icon: {
|
||||
// Required: Name maps to an icon in GitLabs SVG
|
||||
name:
|
||||
issue.state === 'closed' ? 'status_failed_borderless' : 'status_success_borderless',
|
||||
// Optional: An extra class to be added to the icon for additional styling
|
||||
class: issue.state === 'closed' ? 'text-danger' : 'text-success',
|
||||
name: issue.state === 'closed' ? EXTENSION_ICONS.error : EXTENSION_ICONS.success,
|
||||
},
|
||||
// Badges get rendered next to the text on each row
|
||||
badge: issue.state === 'closed' && {
|
||||
|
|
|
@ -206,6 +206,12 @@
|
|||
padding: 0;
|
||||
height: 100%;
|
||||
|
||||
&.with-system-header {
|
||||
.login-page-broadcast {
|
||||
margin-top: $system-header-height + $header-height;
|
||||
}
|
||||
}
|
||||
|
||||
// Fixes footer container to bottom of viewport
|
||||
body {
|
||||
// offset height of fixed header + 1 to avoid scroll
|
||||
|
|
|
@ -446,10 +446,10 @@ List the artifacts for a single project, sorted by artifact size. The output inc
|
|||
- on-disk location of the artifact
|
||||
|
||||
```ruby
|
||||
p = Project.find_by_id(:project ID)
|
||||
p = Project.find_by_id(<project_id>)
|
||||
arts = Ci::JobArtifact.where(project: p)
|
||||
|
||||
list = arts.order('sort DESC').limit(50).each do |art|
|
||||
list = arts.order(size: :desc).limit(50).each do |art|
|
||||
puts "Job ID: #{art.job_id} - Size: #{art.size}b - Type: #{art.file_type} - Created: #{art.created_at} - File loc: #{art.file}"
|
||||
end
|
||||
```
|
||||
|
|
|
@ -31,8 +31,8 @@ The hard-coded rules only permit:
|
|||
|
||||
Furthermore, configuration in Workhorse can lead to the image scaler rejecting a request if:
|
||||
|
||||
- The image file is too large (controlled by [`max_filesize`](- we only rescale images that do not exceed a configured size in bytes (see [`max_filesize`](https://gitlab.com/gitlab-org/gitlab-workhorse/-/blob/67ab3a2985d2097392f93523ae1cffe0dbf01b31/config.toml.example#L17)))).
|
||||
- Too many image scalers are already running (controlled by [`max_scaler_procs`](https://gitlab.com/gitlab-org/gitlab-workhorse/-/blob/67ab3a2985d2097392f93523ae1cffe0dbf01b31/config.toml.example#L16)).
|
||||
- The image file is too large (controlled by [`max_filesize`](- we only rescale images that do not exceed a configured size in bytes (see [`max_filesize`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/workhorse/config.toml.example#L22)))).
|
||||
- Too many image scalers are already running (controlled by [`max_scaler_procs`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/workhorse/config.toml.example#L21)).
|
||||
|
||||
For instance, here are two different URLs that serve the GitLab project avatar both in its
|
||||
original size and scaled down to 64 pixels. Only the second request will trigger the image scaler:
|
||||
|
@ -73,7 +73,7 @@ we simply follow the path we take to serve any ordinary upload.
|
|||
### Workhorse
|
||||
|
||||
Assuming Rails decided the request to be valid, Workhorse will take over. Upon receiving the `send-scaled-image`
|
||||
instruction through the Rails response, a [special response injector](https://gitlab.com/gitlab-org/gitlab-workhorse/-/blob/master/internal/imageresizer/image_resizer.go)
|
||||
instruction through the Rails response, a [special response injector](https://gitlab.com/gitlab-org/gitlab/-/blob/master/workhorse/internal/imageresizer/image_resizer.go)
|
||||
will be invoked that knows how to rescale images. The only inputs it requires are the location of the image
|
||||
(a path if the image resides in block storage, or a URL to remote storage otherwise) and the desired width.
|
||||
Workhorse will handle the location transparently so Rails does not need to be concerned with where the image
|
||||
|
|
|
@ -252,7 +252,7 @@ graph RL;
|
|||
2_1-1 & 2_1-2 & 2_1-3 & 2_1-4 --> 1-6;
|
||||
end
|
||||
|
||||
2_2-2["rspec-all frontend_fixture (7 minutes)"];
|
||||
2_2-2["rspec frontend_fixture/rspec-ee frontend_fixture (7 minutes)"];
|
||||
class 2_2-2 criticalPath;
|
||||
click 2_2-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910143&udv=0"
|
||||
2_2-4["memory-on-boot (3.5 minutes)"];
|
||||
|
@ -284,7 +284,7 @@ graph RL;
|
|||
3_1-1["jest (14.5 minutes)"];
|
||||
class 3_1-1 criticalPath;
|
||||
click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0"
|
||||
subgraph "Needs `rspec-all frontend_fixture`";
|
||||
subgraph "Needs `rspec frontend_fixture/rspec-ee frontend_fixture`";
|
||||
3_1-1 --> 2_2-2;
|
||||
end
|
||||
|
||||
|
@ -355,7 +355,7 @@ graph RL;
|
|||
2_1-1 & 2_1-2 & 2_1-3 & 2_1-4 --> 1-6;
|
||||
end
|
||||
|
||||
2_2-2["rspec-all frontend_fixture (7 minutes)"];
|
||||
2_2-2["rspec frontend_fixture/rspec-ee frontend_fixture (7 minutes)"];
|
||||
class 2_2-2 criticalPath;
|
||||
click 2_2-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910143&udv=0"
|
||||
2_2-4["memory-on-boot (3.5 minutes)"];
|
||||
|
@ -395,7 +395,7 @@ graph RL;
|
|||
3_1-1["jest (14.5 minutes)"];
|
||||
class 3_1-1 criticalPath;
|
||||
click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0"
|
||||
subgraph "Needs `rspec-all frontend_fixture`";
|
||||
subgraph "Needs `rspec frontend_fixture/rspec-ee frontend_fixture`";
|
||||
3_1-1 --> 2_2-2;
|
||||
end
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ it('does not display a dropdown if no metricTypes exist', () => {
|
|||
});
|
||||
```
|
||||
|
||||
Keep an eye out for these kinds of tests, as they just make updating logic more fragile and tedious than it needs to be. This is also true for other libraries. A rule of thumb here is: if you are checking a `wrapper.vm` property, you should probably stop and rethink the test to check the rendered template instead.
|
||||
Keep an eye out for these kinds of tests, as they just make updating logic more fragile and tedious than it needs to be. This is also true for other libraries. A suggestion here is: if you are checking a `wrapper.vm` property, you should probably stop and rethink the test to check the rendered template instead.
|
||||
|
||||
Some more examples can be found in the [Frontend unit tests section](testing_levels.md#frontend-unit-tests)
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ tags:
|
|||
- windows-1809
|
||||
```
|
||||
|
||||
A list of software preinstalled on the Windows images is available at: [Preinstalled software](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/master/cookbooks/preinstalled-software/README.md).
|
||||
A list of software preinstalled on the Windows images is available at: [Preinstalled software](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/main/cookbooks/preinstalled-software/README.md).
|
||||
|
||||
## GCP Windows image for development
|
||||
|
||||
|
@ -57,7 +57,7 @@ Build a Google Cloud image with the above shared runners repository by doing the
|
|||
1. Clone the repository <https://github.com/rgl/packer-provisioner-windows-update> and `cd` into the cloned directory.
|
||||
1. Run the command `go build -o packer-provisioner-windows-update` (requires `go` to be installed).
|
||||
1. Verify `packer-provisioner-windows-update` is in the `PATH` environment variable.
|
||||
1. Add all [required environment variables](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/-/blob/master/packer.json#L2-10)
|
||||
1. Add all [required environment variables](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/-/blob/main/packer.json#L2-10)
|
||||
in the `packer.json` file to your environment (perhaps use [`direnv`](https://direnv.net/)).
|
||||
1. Build the image by running the command: `packer build packer.json`.
|
||||
|
||||
|
|
|
@ -40,10 +40,6 @@ module Gitlab
|
|||
},
|
||||
invite_members_new_dropdown: {
|
||||
tracking_category: 'Growth::Expansion::Experiment::InviteMembersNewDropdown'
|
||||
},
|
||||
show_trial_status_in_sidebar: {
|
||||
tracking_category: 'Growth::Conversion::Experiment::ShowTrialStatusInSidebar',
|
||||
rollout_strategy: :group
|
||||
}
|
||||
}.freeze
|
||||
|
||||
|
|
|
@ -46,21 +46,14 @@ class GithubImport
|
|||
def import!
|
||||
@project.import_state.force_start
|
||||
|
||||
import_success = false
|
||||
|
||||
timings = Benchmark.measure do
|
||||
import_success = Gitlab::GithubImport::SequentialImporter
|
||||
Gitlab::GithubImport::SequentialImporter
|
||||
.new(@project, token: @options[:token])
|
||||
.execute
|
||||
end
|
||||
|
||||
if import_success
|
||||
@project.after_import
|
||||
puts "Import finished. Timings: #{timings}".color(:green)
|
||||
else
|
||||
puts "Import was not successful. Errors were as follows:"
|
||||
puts @project.import_state.last_error
|
||||
end
|
||||
end
|
||||
|
||||
def new_project
|
||||
|
|
|
@ -9,7 +9,8 @@ module QA
|
|||
element :directory_name_link
|
||||
end
|
||||
|
||||
def go_to_directory(name)
|
||||
def go_to_directory(name, retry_attempts = 1)
|
||||
retry_on_exception(max_attempts: retry_attempts, reload: true, sleep_interval: 10) do
|
||||
click_element(:directory_name_link, directory_name: name)
|
||||
end
|
||||
end
|
||||
|
@ -17,3 +18,4 @@ module QA
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -109,18 +109,14 @@ function rspec_paralellized_job() {
|
|||
local test_level="${job_name[1]}"
|
||||
local report_name=$(echo "${CI_JOB_NAME}" | sed -E 's|[/ ]|_|g') # e.g. 'rspec unit pg12 1/24' would become 'rspec_unit_pg12_1_24'
|
||||
local rspec_opts="${1}"
|
||||
local spec_folder_prefixes=""
|
||||
local spec_folder_prefix=""
|
||||
|
||||
if [[ "${test_tool}" =~ "-ee" ]]; then
|
||||
spec_folder_prefixes="'ee/'"
|
||||
spec_folder_prefix="ee/"
|
||||
fi
|
||||
|
||||
if [[ "${test_tool}" =~ "-jh" ]]; then
|
||||
spec_folder_prefixes="'jh/'"
|
||||
fi
|
||||
|
||||
if [[ "${test_tool}" =~ "-all" ]]; then
|
||||
spec_folder_prefixes="['', 'ee/']"
|
||||
spec_folder_prefix="jh/"
|
||||
fi
|
||||
|
||||
export KNAPSACK_LOG_LEVEL="debug"
|
||||
|
@ -135,7 +131,7 @@ function rspec_paralellized_job() {
|
|||
cp "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "${KNAPSACK_REPORT_PATH}"
|
||||
|
||||
if [[ -z "${KNAPSACK_TEST_FILE_PATTERN}" ]]; then
|
||||
pattern=$(ruby -r./tooling/quality/test_level.rb -e "puts Quality::TestLevel.new(${spec_folder_prefixes}).pattern(:${test_level})")
|
||||
pattern=$(ruby -r./tooling/quality/test_level.rb -e "puts Quality::TestLevel.new(%(${spec_folder_prefix})).pattern(:${test_level})")
|
||||
export KNAPSACK_TEST_FILE_PATTERN="${pattern}"
|
||||
fi
|
||||
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
import { GlTable, GlLink, GlPagination } from '@gitlab/ui';
|
||||
import { GlTable, GlLink, GlPagination, GlAlert } from '@gitlab/ui';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import { shallowMount, mount } from '@vue/test-utils';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { DEFAULT_PER_PAGE } from '~/api';
|
||||
import createFlash from '~/flash';
|
||||
import IntegrationOverrides from '~/integrations/overrides/components/integration_overrides.vue';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import httpStatus from '~/lib/utils/http_status';
|
||||
import ProjectAvatar from '~/vue_shared/components/project_avatar.vue';
|
||||
|
||||
jest.mock('~/flash');
|
||||
|
||||
const mockOverrides = Array(DEFAULT_PER_PAGE * 3)
|
||||
.fill(1)
|
||||
.map((_, index) => ({
|
||||
|
@ -62,6 +60,7 @@ describe('IntegrationOverrides', () => {
|
|||
text: link.text(),
|
||||
};
|
||||
});
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
|
||||
describe('while loading', () => {
|
||||
it('sets GlTable `busy` attribute to `true`', () => {
|
||||
|
@ -104,18 +103,26 @@ describe('IntegrationOverrides', () => {
|
|||
|
||||
describe('when request fails', () => {
|
||||
beforeEach(async () => {
|
||||
jest.spyOn(Sentry, 'captureException');
|
||||
mockAxios.onGet(defaultProps.overridesPath).reply(httpStatus.INTERNAL_SERVER_ERROR);
|
||||
|
||||
createComponent();
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('calls createFlash', () => {
|
||||
expect(createFlash).toHaveBeenCalledTimes(1);
|
||||
expect(createFlash).toHaveBeenCalledWith({
|
||||
message: IntegrationOverrides.i18n.defaultErrorMessage,
|
||||
captureError: true,
|
||||
error: expect.any(Error),
|
||||
it('displays error alert', () => {
|
||||
const alert = findAlert();
|
||||
expect(alert.exists()).toBe(true);
|
||||
expect(alert.text()).toBe(IntegrationOverrides.i18n.defaultErrorMessage);
|
||||
});
|
||||
|
||||
it('hides overrides table', () => {
|
||||
const table = findGlTable();
|
||||
expect(table.exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('captures exception in Sentry', () => {
|
||||
expect(Sentry.captureException).toHaveBeenCalledWith(expect.any(Error));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -16,20 +16,20 @@ describe('MR widget extensions status icon', () => {
|
|||
});
|
||||
|
||||
it('renders loading icon', () => {
|
||||
factory({ name: 'test', isLoading: true, iconName: 'status-failed' });
|
||||
factory({ name: 'test', isLoading: true, iconName: 'failed' });
|
||||
|
||||
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders status icon', () => {
|
||||
factory({ name: 'test', isLoading: false, iconName: 'status-failed' });
|
||||
factory({ name: 'test', isLoading: false, iconName: 'failed' });
|
||||
|
||||
expect(wrapper.findComponent(GlIcon).exists()).toBe(true);
|
||||
expect(wrapper.findComponent(GlIcon).props('name')).toBe('status-failed');
|
||||
});
|
||||
|
||||
it('sets aria-label for status icon', () => {
|
||||
factory({ name: 'test', isLoading: false, iconName: 'status-failed' });
|
||||
factory({ name: 'test', isLoading: false, iconName: 'failed' });
|
||||
|
||||
expect(wrapper.findComponent(GlIcon).props('ariaLabel')).toBe('Failed test');
|
||||
});
|
||||
|
|
|
@ -919,7 +919,7 @@ describe('MrWidgetOptions', () => {
|
|||
|
||||
// Renders icon in the row
|
||||
expect(collapsedSection.find(GlIcon).exists()).toBe(true);
|
||||
expect(collapsedSection.find(GlIcon).props('name')).toBe('status_failed_borderless');
|
||||
expect(collapsedSection.find(GlIcon).props('name')).toBe('status-failed');
|
||||
|
||||
// Renders badge in the row
|
||||
expect(collapsedSection.find(GlBadge).exists()).toBe(true);
|
||||
|
|
|
@ -21,8 +21,7 @@ export default {
|
|||
id: 1,
|
||||
text: 'Hello world',
|
||||
icon: {
|
||||
name: 'status_failed_borderless',
|
||||
class: 'text-danger',
|
||||
name: EXTENSION_ICONS.failed,
|
||||
},
|
||||
badge: {
|
||||
text: 'Closed',
|
||||
|
|
|
@ -63,14 +63,7 @@ RSpec.describe Quality::TestLevel do
|
|||
context 'with a prefix' do
|
||||
it 'returns a pattern' do
|
||||
expect(described_class.new('ee/').pattern(:system))
|
||||
.to eq("{ee/}spec/{features}{,/**/}*_spec.rb")
|
||||
end
|
||||
end
|
||||
|
||||
context 'with several prefixes' do
|
||||
it 'returns a pattern' do
|
||||
expect(described_class.new(['', 'ee/', 'jh/']).pattern(:system))
|
||||
.to eq("{,ee/,jh/}spec/{features}{,/**/}*_spec.rb")
|
||||
.to eq("ee/spec/{features}{,/**/}*_spec.rb")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -145,14 +138,7 @@ RSpec.describe Quality::TestLevel do
|
|||
context 'with a prefix' do
|
||||
it 'returns a regexp' do
|
||||
expect(described_class.new('ee/').regexp(:system))
|
||||
.to eq(%r{(ee/)spec/(features)})
|
||||
end
|
||||
end
|
||||
|
||||
context 'with several prefixes' do
|
||||
it 'returns a regexp' do
|
||||
expect(described_class.new(['', 'ee/', 'jh/']).regexp(:system))
|
||||
.to eq(%r{(|ee/|jh/)spec/(features)})
|
||||
.to eq(%r{ee/spec/(features)})
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -60,20 +60,20 @@ module Quality
|
|||
system: ['features']
|
||||
}.freeze
|
||||
|
||||
attr_reader :prefixes
|
||||
attr_reader :prefix
|
||||
|
||||
def initialize(prefixes = nil)
|
||||
@prefixes = Array(prefixes)
|
||||
def initialize(prefix = nil)
|
||||
@prefix = prefix
|
||||
@patterns = {}
|
||||
@regexps = {}
|
||||
end
|
||||
|
||||
def pattern(level)
|
||||
@patterns[level] ||= "#{prefixes_for_pattern}spec/#{folders_pattern(level)}{,/**/}*#{suffix(level)}"
|
||||
@patterns[level] ||= "#{prefix}spec/#{folders_pattern(level)}{,/**/}*#{suffix(level)}"
|
||||
end
|
||||
|
||||
def regexp(level)
|
||||
@regexps[level] ||= Regexp.new("#{prefixes_for_regex}spec/#{folders_regex(level)}").freeze
|
||||
@regexps[level] ||= Regexp.new("#{prefix}spec/#{folders_regex(level)}").freeze
|
||||
end
|
||||
|
||||
def level_for(file_path)
|
||||
|
@ -102,20 +102,6 @@ module Quality
|
|||
|
||||
private
|
||||
|
||||
def prefixes_for_pattern
|
||||
return '' if prefixes.empty?
|
||||
|
||||
"{#{prefixes.join(',')}}"
|
||||
end
|
||||
|
||||
def prefixes_for_regex
|
||||
return '' if prefixes.empty?
|
||||
|
||||
regex_prefix = prefixes.map(&Regexp.method(:escape)).join('|')
|
||||
|
||||
"(#{regex_prefix})"
|
||||
end
|
||||
|
||||
def suffix(level)
|
||||
case level
|
||||
when :frontend_fixture
|
||||
|
|
Loading…
Reference in a new issue