Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-12-02 12:10:10 +00:00
parent 78bc39880c
commit 02e597943f
25 changed files with 27 additions and 859 deletions

View File

@ -14,7 +14,6 @@ Style/OpenStructUse:
- lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
- lib/gitlab/testing/request_inspector_middleware.rb
- lib/mattermost/session.rb
- spec/controllers/admin/clusters_controller_spec.rb
- spec/controllers/groups/clusters_controller_spec.rb
- spec/controllers/import/fogbugz_controller_spec.rb
- spec/controllers/import/gitlab_controller_spec.rb
@ -22,7 +21,6 @@ Style/OpenStructUse:
- spec/dependencies/omniauth_saml_spec.rb
- spec/factories/go_module_versions.rb
- spec/factories/wiki_pages.rb
- spec/features/projects/clusters/gcp_spec.rb
- spec/features/projects/clusters_spec.rb
- spec/finders/template_finder_spec.rb
- spec/graphql/mutations/branches/create_spec.rb
@ -34,7 +32,6 @@ Style/OpenStructUse:
- spec/helpers/profiles_helper_spec.rb
- spec/initializers/doorkeeper_spec.rb
- spec/lib/gitlab/auth/o_auth/provider_spec.rb
- spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb
- spec/lib/gitlab/database/migrations/runner_spec.rb
- spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb
- spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb

View File

@ -16,24 +16,24 @@ import {
ListTypeTitles,
DraggableItemTypes,
} from 'ee_else_ce/boards/constants';
import {
formatIssueInput,
formatBoardLists,
formatListIssues,
formatListsPageInfo,
formatIssue,
updateListPosition,
moveItemListHelper,
getMoveData,
FiltersInfo,
filterVariables,
} from 'ee_else_ce/boards/boards_util';
import createBoardListMutation from 'ee_else_ce/boards/graphql/board_list_create.mutation.graphql';
import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { queryToObject } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import {
formatBoardLists,
formatListIssues,
formatListsPageInfo,
formatIssue,
formatIssueInput,
updateListPosition,
moveItemListHelper,
getMoveData,
FiltersInfo,
filterVariables,
} from '../boards_util';
import { gqlClient } from '../graphql';
import boardLabelsQuery from '../graphql/board_labels.query.graphql';
import groupBoardMilestonesQuery from '../graphql/group_board_milestones.query.graphql';

View File

@ -1,23 +0,0 @@
import LinkedTabs from '~/lib/utils/bootstrap_linked_tabs';
import storageCounter from '~/projects/storage_counter';
import initSearchSettings from '~/search_settings';
const initLinkedTabs = () => {
if (!document.querySelector('.js-usage-quota-tabs')) {
return false;
}
return new LinkedTabs({
defaultAction: '#storage-quota-tab',
parentEl: '.js-usage-quota-tabs',
hashedTabs: true,
});
};
const initVueApp = () => {
storageCounter('js-project-storage-count-app');
};
initVueApp();
initLinkedTabs();
initSearchSettings();

View File

@ -1,106 +0,0 @@
<script>
import { GlAlert, GlLink, GlLoadingIcon } from '@gitlab/ui';
import { sprintf } from '~/locale';
import UsageGraph from '~/vue_shared/components/storage_counter/usage_graph.vue';
import {
ERROR_MESSAGE,
LEARN_MORE_LABEL,
USAGE_QUOTAS_LABEL,
TOTAL_USAGE_TITLE,
TOTAL_USAGE_SUBTITLE,
TOTAL_USAGE_DEFAULT_TEXT,
HELP_LINK_ARIA_LABEL,
} from '../constants';
import getProjectStorageCount from '../queries/project_storage.query.graphql';
import { parseGetProjectStorageResults } from '../utils';
import StorageTable from './storage_table.vue';
export default {
name: 'StorageCounterApp',
components: {
GlAlert,
GlLink,
GlLoadingIcon,
StorageTable,
UsageGraph,
},
inject: ['projectPath', 'helpLinks'],
apollo: {
project: {
query: getProjectStorageCount,
variables() {
return {
fullPath: this.projectPath,
};
},
update(data) {
return parseGetProjectStorageResults(data, this.helpLinks);
},
error() {
this.error = ERROR_MESSAGE;
},
},
},
data() {
return {
project: {},
error: '',
};
},
computed: {
totalUsage() {
return this.project?.storage?.totalUsage || TOTAL_USAGE_DEFAULT_TEXT;
},
storageTypes() {
return this.project?.storage?.storageTypes || [];
},
},
methods: {
clearError() {
this.error = '';
},
helpLinkAriaLabel(linkTitle) {
return sprintf(HELP_LINK_ARIA_LABEL, {
linkTitle,
});
},
},
LEARN_MORE_LABEL,
USAGE_QUOTAS_LABEL,
TOTAL_USAGE_TITLE,
TOTAL_USAGE_SUBTITLE,
};
</script>
<template>
<gl-loading-icon v-if="$apollo.queries.project.loading" class="gl-mt-5" size="md" />
<gl-alert v-else-if="error" variant="danger" @dismiss="clearError">
{{ error }}
</gl-alert>
<div v-else>
<div class="gl-pt-5 gl-px-3">
<div class="gl-display-flex gl-justify-content-space-between gl-align-items-center">
<div>
<p class="gl-m-0 gl-font-lg gl-font-weight-bold">{{ $options.TOTAL_USAGE_TITLE }}</p>
<p class="gl-m-0 gl-text-gray-400">
{{ $options.TOTAL_USAGE_SUBTITLE }}
<gl-link
:href="helpLinks.usageQuotasHelpPagePath"
target="_blank"
:aria-label="helpLinkAriaLabel($options.USAGE_QUOTAS_LABEL)"
data-testid="usage-quotas-help-link"
>
{{ $options.LEARN_MORE_LABEL }}
</gl-link>
</p>
</div>
<p class="gl-m-0 gl-font-size-h-display gl-font-weight-bold" data-testid="total-usage">
{{ totalUsage }}
</p>
</div>
</div>
<div v-if="project.statistics" class="gl-w-full">
<usage-graph :root-storage-statistics="project.statistics" :limit="0" />
</div>
<storage-table :storage-types="storageTypes" />
</div>
</template>

View File

@ -1,88 +0,0 @@
<script>
import { GlLink, GlIcon, GlTableLite as GlTable, GlSprintf } from '@gitlab/ui';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { thWidthClass } from '~/lib/utils/table_utility';
import { sprintf } from '~/locale';
import { PROJECT_TABLE_LABELS, HELP_LINK_ARIA_LABEL } from '../constants';
import StorageTypeIcon from './storage_type_icon.vue';
export default {
name: 'StorageTable',
components: {
GlLink,
GlIcon,
GlTable,
GlSprintf,
StorageTypeIcon,
},
props: {
storageTypes: {
type: Array,
required: true,
},
},
methods: {
helpLinkAriaLabel(linkTitle) {
return sprintf(HELP_LINK_ARIA_LABEL, {
linkTitle,
});
},
},
projectTableFields: [
{
key: 'storageType',
label: PROJECT_TABLE_LABELS.STORAGE_TYPE,
thClass: thWidthClass(90),
sortable: true,
},
{
key: 'value',
label: PROJECT_TABLE_LABELS.VALUE,
thClass: thWidthClass(10),
sortable: true,
formatter: (value) => {
return numberToHumanSize(value, 1);
},
},
],
};
</script>
<template>
<gl-table :items="storageTypes" :fields="$options.projectTableFields">
<template #cell(storageType)="{ item }">
<div class="gl-display-flex gl-flex-direction-row">
<storage-type-icon
:name="item.storageType.id"
:data-testid="`${item.storageType.id}-icon`"
/>
<div>
<p class="gl-font-weight-bold gl-mb-0" :data-testid="`${item.storageType.id}-name`">
{{ item.storageType.name }}
<gl-link
v-if="item.storageType.helpPath"
:href="item.storageType.helpPath"
target="_blank"
:aria-label="helpLinkAriaLabel(item.storageType.name)"
:data-testid="`${item.storageType.id}-help-link`"
>
<gl-icon name="question" :size="12" />
</gl-link>
</p>
<p class="gl-mb-0" :data-testid="`${item.storageType.id}-description`">
{{ item.storageType.description }}
</p>
<p v-if="item.storageType.warningMessage" class="gl-mb-0 gl-font-sm">
<gl-icon name="warning" :size="12" />
<gl-sprintf :message="item.storageType.warningMessage">
<template #warningLink="{ content }">
<gl-link :href="item.storageType.warningLink" target="_blank" class="gl-font-sm">{{
content
}}</gl-link>
</template>
</gl-sprintf>
</p>
</div>
</div>
</template>
</gl-table>
</template>

View File

@ -1,35 +0,0 @@
<script>
import { GlIcon } from '@gitlab/ui';
export default {
components: { GlIcon },
props: {
name: {
type: String,
required: false,
default: '',
},
},
methods: {
iconName(storageTypeName) {
const defaultStorageTypeIcon = 'disk';
const storageTypeIconMap = {
lfsObjectsSize: 'doc-image',
snippetsSize: 'snippet',
uploadsSize: 'upload',
repositorySize: 'infrastructure-registry',
packagesSize: 'package',
};
return storageTypeIconMap[`${storageTypeName}`] ?? defaultStorageTypeIcon;
},
},
};
</script>
<template>
<span
class="gl-display-inline-flex gl-align-items-flex-start gl-justify-content-center gl-min-w-8 gl-pr-2 gl-pt-1"
>
<gl-icon :name="iconName(name)" :size="16" class="gl-mt-1" />
</span>
</template>

View File

@ -1,61 +0,0 @@
import { s__, __ } from '~/locale';
export const PROJECT_STORAGE_TYPES = [
{
id: 'buildArtifactsSize',
name: s__('UsageQuota|Artifacts'),
description: s__('UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD.'),
warningMessage: s__(
'UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}.',
),
warningLink: 'https://gitlab.com/groups/gitlab-org/-/epics/5380',
},
{
id: 'lfsObjectsSize',
name: s__('UsageQuota|LFS storage'),
description: s__('UsageQuota|Audio samples, videos, datasets, and graphics.'),
},
{
id: 'packagesSize',
name: s__('UsageQuota|Packages'),
description: s__('UsageQuota|Code packages and container images.'),
},
{
id: 'repositorySize',
name: s__('UsageQuota|Repository'),
description: s__('UsageQuota|Git repository.'),
},
{
id: 'snippetsSize',
name: s__('UsageQuota|Snippets'),
description: s__('UsageQuota|Shared bits of code and text.'),
},
{
id: 'uploadsSize',
name: s__('UsageQuota|Uploads'),
description: s__('UsageQuota|File attachments and smaller design graphics.'),
},
{
id: 'wikiSize',
name: s__('UsageQuota|Wiki'),
description: s__('UsageQuota|Wiki content.'),
},
];
export const PROJECT_TABLE_LABELS = {
STORAGE_TYPE: s__('UsageQuota|Storage type'),
VALUE: s__('UsageQuota|Usage'),
};
export const ERROR_MESSAGE = s__(
'UsageQuota|Something went wrong while fetching project storage statistics',
);
export const LEARN_MORE_LABEL = __('Learn more.');
export const USAGE_QUOTAS_LABEL = s__('UsageQuota|Usage Quotas');
export const HELP_LINK_ARIA_LABEL = s__('UsageQuota|%{linkTitle} help link');
export const TOTAL_USAGE_DEFAULT_TEXT = __('N/A');
export const TOTAL_USAGE_TITLE = s__('UsageQuota|Usage breakdown');
export const TOTAL_USAGE_SUBTITLE = s__(
'UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items.',
);

View File

@ -1,51 +0,0 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import StorageCounterApp from './components/app.vue';
Vue.use(VueApollo);
export default (containerId = 'js-project-storage-count-app') => {
const el = document.getElementById(containerId);
if (!el) {
return false;
}
const {
projectPath,
usageQuotasHelpPagePath,
buildArtifactsHelpPagePath,
lfsObjectsHelpPagePath,
packagesHelpPagePath,
repositoryHelpPagePath,
snippetsHelpPagePath,
uploadsHelpPagePath,
wikiHelpPagePath,
} = el.dataset;
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
return new Vue({
el,
apolloProvider,
provide: {
projectPath,
helpLinks: {
usageQuotasHelpPagePath,
buildArtifactsHelpPagePath,
lfsObjectsHelpPagePath,
packagesHelpPagePath,
repositoryHelpPagePath,
snippetsHelpPagePath,
uploadsHelpPagePath,
wikiHelpPagePath,
},
},
render(createElement) {
return createElement(StorageCounterApp);
},
});
};

View File

@ -1,16 +0,0 @@
query getProjectStorageCount($fullPath: ID!) {
project(fullPath: $fullPath) {
id
statistics {
buildArtifactsSize
pipelineArtifactsSize
lfsObjectsSize
packagesSize
repositorySize
snippetsSize
storageSize
uploadsSize
wikiSize
}
}
}

View File

@ -1,36 +0,0 @@
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { PROJECT_STORAGE_TYPES } from './constants';
/**
* This method parses the results from `getProjectStorageCount` call.
*
* @param {Object} data graphql result
* @returns {Object}
*/
export const parseGetProjectStorageResults = (data, helpLinks) => {
const projectStatistics = data?.project?.statistics;
if (!projectStatistics) {
return {};
}
const { storageSize, ...storageStatistics } = projectStatistics;
const storageTypes = PROJECT_STORAGE_TYPES.reduce((types, currentType) => {
const helpPathKey = currentType.id.replace(`Size`, `HelpPagePath`);
const helpPath = helpLinks[helpPathKey];
return types.concat({
storageType: {
...currentType,
helpPath,
},
value: storageStatistics[currentType.id],
});
}, []);
return {
storage: {
totalUsage: numberToHumanSize(storageSize, 1),
storageTypes,
},
statistics: projectStatistics,
};
};

View File

@ -1,8 +0,0 @@
---
name: linear_groups_template_finder_extended_group_search
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68936
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339439
milestone: '14.3'
type: development
group: group::access
default_enabled: false

View File

@ -50,7 +50,7 @@ Example of response
"iid": 12,
"project_id": 1,
"status": "pending",
"soure": "push",
"source": "push",
"ref": "new-pipeline",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"web_url": "https://example.com/foo/bar/pipelines/47",
@ -62,7 +62,7 @@ Example of response
"iid": 13,
"project_id": 1,
"status": "pending",
"soure": "web",
"source": "web",
"ref": "new-pipeline",
"sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a",
"web_url": "https://example.com/foo/bar/pipelines/48",

View File

@ -78,13 +78,16 @@ module API
name = params[:name] || params[:context] || 'default'
pipeline ||= user_project.ci_pipelines.create!(
pipeline ||= user_project.ci_pipelines.build(
source: :external,
sha: commit.sha,
ref: ref,
user: current_user,
protected: user_project.protected_for?(ref))
pipeline.ensure_project_iid!
pipeline.save!
authorize! :update_pipeline, pipeline
status = GenericCommitStatus.running_or_pending.find_or_initialize_by(

View File

@ -37424,9 +37424,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
msgid "Usage"
msgstr ""
msgid "Usage Trends"
msgstr ""
@ -37484,9 +37481,6 @@ msgstr ""
msgid "UsageQuota|LFS Objects"
msgstr ""
msgid "UsageQuota|LFS Storage"
msgstr ""
msgid "UsageQuota|LFS storage"
msgstr ""

View File

@ -278,7 +278,8 @@ RSpec.describe Admin::ClustersController do
end
allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |instance|
allow(instance).to receive(:projects_zones_clusters_create) do
OpenStruct.new(
double(
'instance',
self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
status: 'RUNNING'
)

View File

@ -49,7 +49,8 @@ RSpec.describe 'Gcp Cluster', :js do
before do
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
.to receive(:projects_zones_clusters_create) do
OpenStruct.new(
double(
'cluster',
self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
status: 'RUNNING'
)

View File

@ -20,7 +20,7 @@ import {
formatIssue,
getMoveData,
updateListPosition,
} from '~/boards/boards_util';
} from 'ee_else_ce/boards/boards_util';
import { gqlClient } from '~/boards/graphql';
import destroyBoardListMutation from '~/boards/graphql/board_list_destroy.mutation.graphql';
import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql';

View File

@ -65,31 +65,5 @@ RSpec.describe 'Projects (JavaScript fixtures)', type: :controller do
expect_graphql_errors_to_be_empty
end
end
context 'project storage count query' do
before do
project.statistics.update!(
repository_size: 3900000,
lfs_objects_size: 4800000,
build_artifacts_size: 400000,
pipeline_artifacts_size: 400000,
wiki_size: 300000,
packages_size: 3800000,
uploads_size: 900000
)
end
base_input_path = 'projects/storage_counter/queries/'
base_output_path = 'graphql/projects/storage_counter/'
query_name = 'project_storage.query.graphql'
it "#{base_output_path}#{query_name}.json" do
query = get_graphql_query_as_string("#{base_input_path}#{query_name}")
post_graphql(query, current_user: user, variables: { fullPath: project.full_path })
expect_graphql_errors_to_be_empty
end
end
end
end

View File

@ -1,150 +0,0 @@
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import StorageCounterApp from '~/projects/storage_counter/components/app.vue';
import { TOTAL_USAGE_DEFAULT_TEXT } from '~/projects/storage_counter/constants';
import getProjectStorageCount from '~/projects/storage_counter/queries/project_storage.query.graphql';
import UsageGraph from '~/vue_shared/components/storage_counter/usage_graph.vue';
import {
mockGetProjectStorageCountGraphQLResponse,
mockEmptyResponse,
projectData,
defaultProvideValues,
} from '../mock_data';
const localVue = createLocalVue();
localVue.use(VueApollo);
describe('Storage counter app', () => {
let wrapper;
const createMockApolloProvider = ({ reject = false, mockedValue } = {}) => {
let response;
if (reject) {
response = jest.fn().mockRejectedValue(mockedValue || new Error('GraphQL error'));
} else {
response = jest.fn().mockResolvedValue(mockedValue);
}
const requestHandlers = [[getProjectStorageCount, response]];
return createMockApollo(requestHandlers);
};
const createComponent = ({ provide = {}, mockApollo } = {}) => {
wrapper = extendedWrapper(
shallowMount(StorageCounterApp, {
localVue,
apolloProvider: mockApollo,
provide: {
...defaultProvideValues,
...provide,
},
}),
);
};
const findAlert = () => wrapper.findComponent(GlAlert);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findUsagePercentage = () => wrapper.findByTestId('total-usage');
const findUsageQuotasHelpLink = () => wrapper.findByTestId('usage-quotas-help-link');
const findUsageGraph = () => wrapper.findComponent(UsageGraph);
afterEach(() => {
wrapper.destroy();
});
describe('with apollo fetching successful', () => {
let mockApollo;
beforeEach(async () => {
mockApollo = createMockApolloProvider({
mockedValue: mockGetProjectStorageCountGraphQLResponse,
});
createComponent({ mockApollo });
await waitForPromises();
});
it('renders correct total usage', () => {
expect(findUsagePercentage().text()).toBe(projectData.storage.totalUsage);
});
it('renders correct usage quotas help link', () => {
expect(findUsageQuotasHelpLink().attributes('href')).toBe(
defaultProvideValues.helpLinks.usageQuotasHelpPagePath,
);
});
});
describe('with apollo loading', () => {
let mockApollo;
beforeEach(() => {
mockApollo = createMockApolloProvider({
mockedValue: new Promise(() => {}),
});
createComponent({ mockApollo });
});
it('should show loading icon', () => {
expect(findLoadingIcon().exists()).toBe(true);
});
});
describe('with apollo returning empty data', () => {
let mockApollo;
beforeEach(async () => {
mockApollo = createMockApolloProvider({
mockedValue: mockEmptyResponse,
});
createComponent({ mockApollo });
await waitForPromises();
});
it('shows default text for total usage', () => {
expect(findUsagePercentage().text()).toBe(TOTAL_USAGE_DEFAULT_TEXT);
});
});
describe('with apollo fetching error', () => {
let mockApollo;
beforeEach(() => {
mockApollo = createMockApolloProvider();
createComponent({ mockApollo, reject: true });
});
it('renders gl-alert', () => {
expect(findAlert().exists()).toBe(true);
});
});
describe('rendering <usage-graph />', () => {
let mockApollo;
beforeEach(async () => {
mockApollo = createMockApolloProvider({
mockedValue: mockGetProjectStorageCountGraphQLResponse,
});
createComponent({ mockApollo });
await waitForPromises();
});
it('renders usage-graph component if project.statistics exists', () => {
expect(findUsageGraph().exists()).toBe(true);
});
it('passes project.statistics to usage-graph component', () => {
const {
__typename,
...statistics
} = mockGetProjectStorageCountGraphQLResponse.data.project.statistics;
expect(findUsageGraph().props('rootStorageStatistics')).toMatchObject(statistics);
});
});
});

View File

@ -1,63 +0,0 @@
import { GlTableLite } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import StorageTable from '~/projects/storage_counter/components/storage_table.vue';
import { projectData, defaultProvideValues } from '../mock_data';
describe('StorageTable', () => {
let wrapper;
const defaultProps = {
storageTypes: projectData.storage.storageTypes,
};
const createComponent = (props = {}) => {
wrapper = extendedWrapper(
mount(StorageTable, {
propsData: {
...defaultProps,
...props,
},
}),
);
};
const findTable = () => wrapper.findComponent(GlTableLite);
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
describe('with storage types', () => {
it.each(projectData.storage.storageTypes)(
'renders table row correctly %o',
({ storageType: { id, name, description } }) => {
expect(wrapper.findByTestId(`${id}-name`).text()).toBe(name);
expect(wrapper.findByTestId(`${id}-description`).text()).toBe(description);
expect(wrapper.findByTestId(`${id}-icon`).props('name')).toBe(id);
expect(wrapper.findByTestId(`${id}-help-link`).attributes('href')).toBe(
defaultProvideValues.helpLinks[id.replace(`Size`, `HelpPagePath`)]
.replace(`Size`, ``)
.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`),
);
},
);
});
describe('without storage types', () => {
beforeEach(() => {
createComponent({ storageTypes: [] });
});
it('should render the table header <th>', () => {
expect(findTable().find('th').exists()).toBe(true);
});
it('should not render any table data <td>', () => {
expect(findTable().find('td').exists()).toBe(false);
});
});
});

View File

@ -1,41 +0,0 @@
import { mount } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
import StorageTypeIcon from '~/projects/storage_counter/components/storage_type_icon.vue';
describe('StorageTypeIcon', () => {
let wrapper;
const createComponent = (props = {}) => {
wrapper = mount(StorageTypeIcon, {
propsData: {
...props,
},
});
};
const findGlIcon = () => wrapper.findComponent(GlIcon);
describe('rendering icon', () => {
afterEach(() => {
wrapper.destroy();
});
it.each`
expected | provided
${'doc-image'} | ${'lfsObjectsSize'}
${'snippet'} | ${'snippetsSize'}
${'infrastructure-registry'} | ${'repositorySize'}
${'package'} | ${'packagesSize'}
${'upload'} | ${'uploadsSize'}
${'disk'} | ${'wikiSize'}
${'disk'} | ${'anything-else'}
`(
'renders icon with name of $expected when name prop is $provided',
({ expected, provided }) => {
createComponent({ name: provided });
expect(findGlIcon().props('name')).toBe(expected);
},
);
});
});

View File

@ -1,92 +0,0 @@
import mockGetProjectStorageCountGraphQLResponse from 'test_fixtures/graphql/projects/storage_counter/project_storage.query.graphql.json';
export { mockGetProjectStorageCountGraphQLResponse };
export const mockEmptyResponse = { data: { project: null } };
export const defaultProvideValues = {
projectPath: '/project-path',
helpLinks: {
usageQuotasHelpPagePath: '/usage-quotas',
buildArtifactsHelpPagePath: '/build-artifacts',
lfsObjectsHelpPagePath: '/lsf-objects',
packagesHelpPagePath: '/packages',
repositoryHelpPagePath: '/repository',
snippetsHelpPagePath: '/snippets',
uploadsHelpPagePath: '/uploads',
wikiHelpPagePath: '/wiki',
},
};
export const projectData = {
storage: {
totalUsage: '13.8 MiB',
storageTypes: [
{
storageType: {
id: 'buildArtifactsSize',
name: 'Artifacts',
description: 'Pipeline artifacts and job artifacts, created with CI/CD.',
warningMessage:
'Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}.',
helpPath: '/build-artifacts',
},
value: 400000,
},
{
storageType: {
id: 'lfsObjectsSize',
name: 'LFS storage',
description: 'Audio samples, videos, datasets, and graphics.',
helpPath: '/lsf-objects',
},
value: 4800000,
},
{
storageType: {
id: 'packagesSize',
name: 'Packages',
description: 'Code packages and container images.',
helpPath: '/packages',
},
value: 3800000,
},
{
storageType: {
id: 'repositorySize',
name: 'Repository',
description: 'Git repository.',
helpPath: '/repository',
},
value: 3900000,
},
{
storageType: {
id: 'snippetsSize',
name: 'Snippets',
description: 'Shared bits of code and text.',
helpPath: '/snippets',
},
value: 0,
},
{
storageType: {
id: 'uploadsSize',
name: 'Uploads',
description: 'File attachments and smaller design graphics.',
helpPath: '/uploads',
},
value: 900000,
},
{
storageType: {
id: 'wikiSize',
name: 'Wiki',
description: 'Wiki content.',
helpPath: '/wiki',
},
value: 300000,
},
],
},
};

View File

@ -1,34 +0,0 @@
import { parseGetProjectStorageResults } from '~/projects/storage_counter/utils';
import {
mockGetProjectStorageCountGraphQLResponse,
projectData,
defaultProvideValues,
} from './mock_data';
describe('parseGetProjectStorageResults', () => {
it('parses project statistics correctly', () => {
expect(
parseGetProjectStorageResults(
mockGetProjectStorageCountGraphQLResponse.data,
defaultProvideValues.helpLinks,
),
).toMatchObject(projectData);
});
it('includes storage type with size of 0 in returned value', () => {
const mockedResponse = mockGetProjectStorageCountGraphQLResponse.data;
// ensuring a specific storage type item has size of 0
mockedResponse.project.statistics.repositorySize = 0;
const response = parseGetProjectStorageResults(mockedResponse, defaultProvideValues.helpLinks);
expect(response.storage.storageTypes).toEqual(
expect.arrayContaining([
{
storageType: expect.any(Object),
value: 0,
},
]),
);
});
});

View File

@ -97,6 +97,6 @@ RSpec.describe Gitlab::Cleanup::OrphanLfsFileReferences do
def stub_lfs_pointers(repo, *oids)
expect(repo.gitaly_blob_client)
.to receive(:get_all_lfs_pointers)
.and_return(oids.map { |oid| OpenStruct.new(lfs_oid: oid) })
.and_return(oids.map { |oid| double('pointers', lfs_oid: oid) })
end
end

View File

@ -131,7 +131,7 @@ RSpec.describe API::CommitStatuses do
%w[pending running success failed canceled].each do |status|
context "for #{status}" do
context 'when pipeline for sha does not exists' do
it 'creates commit status' do
it 'creates commit status and sets pipeline iid' do
post api(post_url, developer), params: { state: status }
expect(response).to have_gitlab_http_status(:created)
@ -145,6 +145,8 @@ RSpec.describe API::CommitStatuses do
if status == 'failed'
expect(CommitStatus.find(json_response['id'])).to be_api_failure
end
expect(::Ci::Pipeline.last.iid).not_to be_nil
end
end
end