diff --git a/app/assets/javascripts/pages/projects/usage_quotas/index.js b/ee/app/assets/javascripts/pages/projects/usage_quotas/index.js similarity index 77% rename from app/assets/javascripts/pages/projects/usage_quotas/index.js rename to ee/app/assets/javascripts/pages/projects/usage_quotas/index.js index 9cd80b85c8a042e1b40a79ff0f212fd86e5b9b87..40aa0b7627bffdcc6852eb6e28945733c1da8689 100644 --- a/app/assets/javascripts/pages/projects/usage_quotas/index.js +++ b/ee/app/assets/javascripts/pages/projects/usage_quotas/index.js @@ -1,5 +1,5 @@ import LinkedTabs from '~/lib/utils/bootstrap_linked_tabs'; -import storageCounter from '~/projects/storage_counter'; +import initProjectStorage from 'ee/usage_quotas/storage/init_project_storage'; import initSearchSettings from '~/search_settings'; const initLinkedTabs = () => { @@ -15,7 +15,7 @@ const initLinkedTabs = () => { }; const initVueApp = () => { - storageCounter('js-project-storage-count-app'); + initProjectStorage('js-project-storage-count-app'); }; initVueApp(); diff --git a/ee/app/assets/javascripts/storage_counter/components/app.vue b/ee/app/assets/javascripts/storage_counter/components/app.vue index ab851fdae40025a0bf34f1d0bd6d62e9ee0a36c4..1d8f6bbffd4163c5901cf7168799ab4a27c07655 100644 --- a/ee/app/assets/javascripts/storage_counter/components/app.vue +++ b/ee/app/assets/javascripts/storage_counter/components/app.vue @@ -10,10 +10,10 @@ import { import { parseBoolean } from '~/lib/utils/common_utils'; import UsageGraph from '~/vue_shared/components/storage_counter/usage_graph.vue'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import ProjectList from 'ee/usage_quotas/storage/components/project_list.vue'; import { PROJECTS_PER_PAGE } from '../constants'; import query from '../queries/storage.query.graphql'; import { formatUsageSize, parseGetStorageResults } from '../utils'; -import ProjectsTable from './projects_table.vue'; import StorageInlineAlert from './storage_inline_alert.vue'; import TemporaryStorageIncreaseModal from './temporary_storage_increase_modal.vue'; import UsageStatistics from './usage_statistics.vue'; @@ -26,7 +26,7 @@ export default { GlButton, GlSprintf, UsageGraph, - ProjectsTable, + ProjectList, UsageStatistics, StorageInlineAlert, GlKeysetPagination, @@ -230,7 +230,7 @@ export default { /> </div> </div> - <projects-table + <project-list :projects="namespaceProjects" :is-loading="isQueryLoading" :additional-purchased-storage-size="namespace.additionalPurchasedStorageSize || 0" diff --git a/ee/app/assets/javascripts/storage_counter/components/storage_row.vue b/ee/app/assets/javascripts/storage_counter/components/storage_row.vue deleted file mode 100644 index 80c4a5e7554f126f331fa51d75afb2850f14dc97..0000000000000000000000000000000000000000 --- a/ee/app/assets/javascripts/storage_counter/components/storage_row.vue +++ /dev/null @@ -1,34 +0,0 @@ -<script> -import { numberToHumanSize } from '~/lib/utils/number_utils'; - -export default { - props: { - name: { - type: String, - required: true, - }, - value: { - type: Number, - required: true, - }, - }, - computed: { - formattedValue() { - return numberToHumanSize(this.value); - }, - }, -}; -</script> -<template> - <div class="gl-responsive-table-row gl-line-height-normal" role="row"> - <div class="table-section section-wrap section-70 text-truncate pl-2 ml-3" role="gridcell"> - <div class="table-mobile-header" role="rowheader"></div> - <div class="table-mobile-content ml-1">{{ name }}</div> - </div> - - <div class="table-section section-wrap section-30 text-truncate" role="gridcell"> - <div class="table-mobile-header" role="rowheader"></div> - <div class="table-mobile-content">{{ formattedValue }}</div> - </div> - </div> -</template> diff --git a/ee/app/assets/javascripts/storage_counter/constants.js b/ee/app/assets/javascripts/storage_counter/constants.js index 6bff67659d4924e261c9228568d6076906fb34a1..30e50c5031738bd13cad790028fb2839f9dd3f31 100644 --- a/ee/app/assets/javascripts/storage_counter/constants.js +++ b/ee/app/assets/javascripts/storage_counter/constants.js @@ -13,5 +13,3 @@ export const STORAGE_USAGE_THRESHOLDS = { }; export const PROJECTS_PER_PAGE = 20; - -export const SKELETON_LOADER_ROWS = 5; diff --git a/ee/app/assets/javascripts/storage_counter/components/project.vue b/ee/app/assets/javascripts/usage_quotas/storage/components/collapsible_project_storage_detail.vue similarity index 51% rename from ee/app/assets/javascripts/storage_counter/components/project.vue rename to ee/app/assets/javascripts/usage_quotas/storage/components/collapsible_project_storage_detail.vue index 69c5b446eebf3fb6f92b3232f2bb76e63b689f03..9859985f1c0a949ae5fdd19c25f313ae24b77f6b 100644 --- a/ee/app/assets/javascripts/storage_counter/components/project.vue +++ b/ee/app/assets/javascripts/usage_quotas/storage/components/collapsible_project_storage_detail.vue @@ -1,17 +1,18 @@ <script> import { GlLink, GlIcon } from '@gitlab/ui'; -import { getIdFromGraphQLId } from '~/graphql_shared/utils'; -import { numberToHumanSize, isOdd } from '~/lib/utils/number_utils'; -import { s__ } from '~/locale'; -import ProjectAvatar from '~/vue_shared/components/deprecated_project_avatar/default.vue'; -import StorageRow from './storage_row.vue'; +import { numberToHumanSize } from '~/lib/utils/number_utils'; +import ProjectAvatar from '~/vue_shared/components/project_avatar.vue'; +import { getStorageTypesFromProjectStatistics } from '../utils'; +import { PROJECT_TABLE_LABEL_PROJECT, PROJECT_TABLE_LABEL_USAGE } from '../constants'; +import ProjectStorageDetail from './project_storage_detail.vue'; export default { + name: 'CollapsibleProjectStorageDetail', components: { GlIcon, GlLink, ProjectAvatar, - StorageRow, + ProjectStorageDetail, }, props: { project: { @@ -25,15 +26,6 @@ export default { }; }, computed: { - projectAvatar() { - const { name, id, avatarUrl, webUrl } = this.project; - return { - name, - id: Number(getIdFromGraphQLId(id)), - avatar_url: avatarUrl, - path: webUrl, - }; - }, name() { return this.project.nameWithNamespace; }, @@ -43,14 +35,8 @@ export default { iconName() { return this.isOpen ? 'angle-down' : 'angle-right'; }, - statistics() { - const statisticsCopy = { ...this.project.statistics }; - delete statisticsCopy.storageSize; - // eslint-disable-next-line no-underscore-dangle - delete statisticsCopy.__typename; - delete statisticsCopy.commitCount; - - return statisticsCopy; + projectStorageTypes() { + return getStorageTypesFromProjectStatistics(this.project.statistics); }, }, methods: { @@ -63,28 +49,10 @@ export default { } this.isOpen = !this.isOpen; }, - getFormattedName(name) { - return this.$options.i18nStatisticsMap[name]; - }, - isOdd(num) { - return isOdd(num); - }, - /** - * Some values can be `nil` - * for those, we send 0 instead - */ - getValue(val) { - return val || 0; - }, }, - i18nStatisticsMap: { - repositorySize: s__('UsageQuota|Repository'), - lfsObjectsSize: s__('UsageQuota|LFS Storage'), - buildArtifactsSize: s__('UsageQuota|Artifacts'), - packagesSize: s__('UsageQuota|Packages'), - wikiSize: s__('UsageQuota|Wiki'), - snippetsSize: s__('UsageQuota|Snippets'), - uploadsSize: s__('UsageQuota|Uploads'), + i18n: { + PROJECT_TABLE_LABEL_PROJECT, + PROJECT_TABLE_LABEL_USAGE, }, }; </script> @@ -101,16 +69,20 @@ export default { role="gridcell" > <div class="table-mobile-header gl-font-weight-bold" role="rowheader"> - {{ __('Project') }} + {{ $options.i18n.PROJECT_TABLE_LABEL_PROJECT }} </div> <div class="table-mobile-content gl-display-flex gl-align-items-center"> <div class="gl-display-flex gl-mr-3 gl-align-items-center"> - <gl-icon :size="12" :name="iconName" class="gl-mr-2" /> + <gl-icon :size="12" :name="iconName" /> <gl-icon name="bookmark" /> </div> - <div> - <project-avatar :project="projectAvatar" :size="32" /> - </div> + <project-avatar + :project-name="project.name" + :project-avatar-url="project.avatarUrl" + :size="32" + :alt="project.name" + class="gl-mr-3" + /> <gl-link :href="project.webUrl" class="js-project-link gl-font-weight-bold gl-text-gray-900!" @@ -123,20 +95,11 @@ export default { role="gridcell" > <div class="table-mobile-header gl-font-weight-bold" role="rowheader"> - {{ __('Usage') }} + {{ $options.i18n.PROJECT_TABLE_LABEL_USAGE }} </div> <div class="table-mobile-content gl-text-gray-900">{{ storageSize }}</div> </div> </div> - - <template v-if="isOpen"> - <storage-row - v-for="(value, statisticsName, index) in statistics" - :key="index" - :name="getFormattedName(statisticsName)" - :value="getValue(value)" - :class="{ 'gl-bg-gray-10': isOdd(index) }" - /> - </template> + <project-storage-detail v-if="isOpen" :storage-types="projectStorageTypes" /> </div> </template> diff --git a/ee/app/assets/javascripts/storage_counter/components/projects_table.vue b/ee/app/assets/javascripts/usage_quotas/storage/components/project_list.vue similarity index 58% rename from ee/app/assets/javascripts/storage_counter/components/projects_table.vue rename to ee/app/assets/javascripts/usage_quotas/storage/components/project_list.vue index dd5e158b5b290a013ba329b3ffdd415008f79eb0..f332dd3208e3e34ad03763f68453ece6a555578b 100644 --- a/ee/app/assets/javascripts/storage_counter/components/projects_table.vue +++ b/ee/app/assets/javascripts/usage_quotas/storage/components/project_list.vue @@ -1,15 +1,14 @@ <script> -import { SEARCH_DEBOUNCE_MS } from '~/ref/constants'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; -import Project from './project.vue'; +import { PROJECT_TABLE_LABEL_PROJECT, PROJECT_TABLE_LABEL_USAGE } from '../constants'; +import CollapsibleProjectStorageDetail from './collapsible_project_storage_detail.vue'; import ProjectsSkeletonLoader from './projects_skeleton_loader.vue'; export default { + name: 'ProjectList', components: { - Project, + CollapsibleProjectStorageDetail, ProjectsSkeletonLoader, }, - mixins: [glFeatureFlagsMixin()], props: { projects: { type: Array, @@ -25,7 +24,10 @@ export default { default: false, }, }, - searchDebounceValue: SEARCH_DEBOUNCE_MS, + i18n: { + PROJECT_TABLE_LABEL_PROJECT, + PROJECT_TABLE_LABEL_USAGE, + }, }; </script> @@ -36,20 +38,19 @@ export default { role="row" > <div class="table-section section-70 gl-font-weight-bold" role="columnheader"> - {{ __('Project') }} + {{ $options.i18n.PROJECT_TABLE_LABEL_PROJECT }} </div> <div class="table-section section-30 gl-font-weight-bold" role="columnheader"> - {{ __('Usage') }} + {{ $options.i18n.PROJECT_TABLE_LABEL_USAGE }} </div> </div> <projects-skeleton-loader v-if="isLoading" /> - <template v-else> - <project - v-for="project in projects" - :key="project.id" - :project="project" - :additional-purchased-storage-size="additionalPurchasedStorageSize" - /> - </template> + <collapsible-project-storage-detail + v-for="project in projects" + v-else + :key="project.id" + :project="project" + :additional-purchased-storage-size="additionalPurchasedStorageSize" + /> </div> </template> diff --git a/app/assets/javascripts/projects/storage_counter/components/app.vue b/ee/app/assets/javascripts/usage_quotas/storage/components/project_storage_app.vue similarity index 89% rename from app/assets/javascripts/projects/storage_counter/components/app.vue rename to ee/app/assets/javascripts/usage_quotas/storage/components/project_storage_app.vue index 1a911ea3d9b479ea6d5220d7948b0071640daa2f..c7c30bb87a090c1e36313834a8277a4a9d826cb4 100644 --- a/app/assets/javascripts/projects/storage_counter/components/app.vue +++ b/ee/app/assets/javascripts/usage_quotas/storage/components/project_storage_app.vue @@ -11,23 +11,23 @@ import { TOTAL_USAGE_DEFAULT_TEXT, HELP_LINK_ARIA_LABEL, } from '../constants'; -import getProjectStorageCount from '../queries/project_storage.query.graphql'; +import getProjectStorageStatistics from '../queries/project_storage.query.graphql'; import { parseGetProjectStorageResults } from '../utils'; -import StorageTable from './storage_table.vue'; +import ProjectStorageDetail from './project_storage_detail.vue'; export default { - name: 'StorageCounterApp', + name: 'ProjectStorageApp', components: { GlAlert, GlLink, GlLoadingIcon, - StorageTable, UsageGraph, + ProjectStorageDetail, }, inject: ['projectPath', 'helpLinks'], apollo: { project: { - query: getProjectStorageCount, + query: getProjectStorageStatistics, variables() { return { fullPath: this.projectPath, @@ -101,6 +101,6 @@ export default { <div v-if="project.statistics" class="gl-w-full"> <usage-graph :root-storage-statistics="project.statistics" :limit="0" /> </div> - <storage-table :storage-types="storageTypes" /> + <project-storage-detail :storage-types="storageTypes" /> </div> </template> diff --git a/app/assets/javascripts/projects/storage_counter/components/storage_table.vue b/ee/app/assets/javascripts/usage_quotas/storage/components/project_storage_detail.vue similarity index 92% rename from app/assets/javascripts/projects/storage_counter/components/storage_table.vue rename to ee/app/assets/javascripts/usage_quotas/storage/components/project_storage_detail.vue index a42a97115728b3de40521d7d11b77ab966aba80b..84a06c5a751643b0fbba227d2d9d90cfd3801627 100644 --- a/app/assets/javascripts/projects/storage_counter/components/storage_table.vue +++ b/ee/app/assets/javascripts/usage_quotas/storage/components/project_storage_detail.vue @@ -3,11 +3,15 @@ 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 { + PROJECT_TABLE_LABEL_STORAGE_TYPE, + PROJECT_TABLE_LABEL_USAGE, + HELP_LINK_ARIA_LABEL, +} from '../constants'; import StorageTypeIcon from './storage_type_icon.vue'; export default { - name: 'StorageTable', + name: 'ProjectStorageDetail', components: { GlLink, GlIcon, @@ -31,13 +35,13 @@ export default { projectTableFields: [ { key: 'storageType', - label: PROJECT_TABLE_LABELS.STORAGE_TYPE, + label: PROJECT_TABLE_LABEL_STORAGE_TYPE, thClass: thWidthClass(90), sortable: true, }, { key: 'value', - label: PROJECT_TABLE_LABELS.VALUE, + label: PROJECT_TABLE_LABEL_USAGE, thClass: thWidthClass(10), sortable: true, formatter: (value) => { diff --git a/ee/app/assets/javascripts/storage_counter/components/projects_skeleton_loader.vue b/ee/app/assets/javascripts/usage_quotas/storage/components/projects_skeleton_loader.vue similarity index 100% rename from ee/app/assets/javascripts/storage_counter/components/projects_skeleton_loader.vue rename to ee/app/assets/javascripts/usage_quotas/storage/components/projects_skeleton_loader.vue diff --git a/app/assets/javascripts/projects/storage_counter/components/storage_type_icon.vue b/ee/app/assets/javascripts/usage_quotas/storage/components/storage_type_icon.vue similarity index 100% rename from app/assets/javascripts/projects/storage_counter/components/storage_type_icon.vue rename to ee/app/assets/javascripts/usage_quotas/storage/components/storage_type_icon.vue diff --git a/app/assets/javascripts/projects/storage_counter/constants.js b/ee/app/assets/javascripts/usage_quotas/storage/constants.js similarity index 88% rename from app/assets/javascripts/projects/storage_counter/constants.js rename to ee/app/assets/javascripts/usage_quotas/storage/constants.js index df4b1800dff8922fd28fc237c0b2be7f53030562..c67e893215178357480a05ff96670058ee54ec6d 100644 --- a/app/assets/javascripts/projects/storage_counter/constants.js +++ b/ee/app/assets/javascripts/usage_quotas/storage/constants.js @@ -1,5 +1,18 @@ import { s__, __ } from '~/locale'; +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.', +); + export const PROJECT_STORAGE_TYPES = [ { id: 'buildArtifactsSize', @@ -42,20 +55,8 @@ export const PROJECT_STORAGE_TYPES = [ }, ]; -export const PROJECT_TABLE_LABELS = { - STORAGE_TYPE: s__('UsageQuota|Storage type'), - VALUE: s__('UsageQuota|Usage'), -}; +export const PROJECT_TABLE_LABEL_PROJECT = __('Project'); +export const PROJECT_TABLE_LABEL_STORAGE_TYPE = s__('UsageQuota|Storage type'); +export const PROJECT_TABLE_LABEL_USAGE = 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.', -); +export const SKELETON_LOADER_ROWS = 5; diff --git a/app/assets/javascripts/projects/storage_counter/index.js b/ee/app/assets/javascripts/usage_quotas/storage/init_project_storage.js similarity index 89% rename from app/assets/javascripts/projects/storage_counter/index.js rename to ee/app/assets/javascripts/usage_quotas/storage/init_project_storage.js index 15796bc187089e4dc760f37a4e0c9ad997c4bdaa..e151d40d441d51a214fdd1659afc45fdb41b0b09 100644 --- a/app/assets/javascripts/projects/storage_counter/index.js +++ b/ee/app/assets/javascripts/usage_quotas/storage/init_project_storage.js @@ -1,7 +1,7 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; -import StorageCounterApp from './components/app.vue'; +import ProjectStorageApp from './components/project_storage_app.vue'; Vue.use(VueApollo); @@ -45,7 +45,7 @@ export default (containerId = 'js-project-storage-count-app') => { }, }, render(createElement) { - return createElement(StorageCounterApp); + return createElement(ProjectStorageApp); }, }); }; diff --git a/app/assets/javascripts/projects/storage_counter/queries/project_storage.query.graphql b/ee/app/assets/javascripts/usage_quotas/storage/queries/project_storage.query.graphql similarity index 82% rename from app/assets/javascripts/projects/storage_counter/queries/project_storage.query.graphql rename to ee/app/assets/javascripts/usage_quotas/storage/queries/project_storage.query.graphql index a4f2c529522caad486b426bd60b07fc8ca76e449..340f7b73804571efecd2c1b7ea9bcd19ae191ad7 100644 --- a/app/assets/javascripts/projects/storage_counter/queries/project_storage.query.graphql +++ b/ee/app/assets/javascripts/usage_quotas/storage/queries/project_storage.query.graphql @@ -1,4 +1,4 @@ -query getProjectStorageCount($fullPath: ID!) { +query getProjectStorageStatistics($fullPath: ID!) { project(fullPath: $fullPath) { id statistics { diff --git a/app/assets/javascripts/projects/storage_counter/utils.js b/ee/app/assets/javascripts/usage_quotas/storage/utils.js similarity index 64% rename from app/assets/javascripts/projects/storage_counter/utils.js rename to ee/app/assets/javascripts/usage_quotas/storage/utils.js index 9fca9d88f46707874828bf67fb91f1a1ad98d84a..f3f475118fc40b996cac96e1e9730c71dcd1a7e8 100644 --- a/app/assets/javascripts/projects/storage_counter/utils.js +++ b/ee/app/assets/javascripts/usage_quotas/storage/utils.js @@ -1,19 +1,8 @@ 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) => { +export const getStorageTypesFromProjectStatistics = (projectStatistics, helpLinks = {}) => + PROJECT_STORAGE_TYPES.reduce((types, currentType) => { const helpPathKey = currentType.id.replace(`Size`, `HelpPagePath`); const helpPath = helpLinks[helpPathKey]; @@ -22,10 +11,24 @@ export const parseGetProjectStorageResults = (data, helpLinks) => { ...currentType, helpPath, }, - value: storageStatistics[currentType.id], + value: projectStatistics[currentType.id], }); }, []); +/** + * This method parses the results from `getProjectStorageStatistics` call. + * + * @param {Object} data graphql result + * @returns {Object} + */ +export const parseGetProjectStorageResults = (data, helpLinks) => { + const projectStatistics = data?.project?.statistics; + if (!projectStatistics) { + return {}; + } + const { storageSize } = projectStatistics; + const storageTypes = getStorageTypesFromProjectStatistics(projectStatistics, helpLinks); + return { storage: { totalUsage: numberToHumanSize(storageSize, 1), diff --git a/ee/spec/frontend/fixtures/projects.rb b/ee/spec/frontend/fixtures/projects.rb new file mode 100644 index 0000000000000000000000000000000000000000..cc53746ad4481043d40000ae3beb55706d478140 --- /dev/null +++ b/ee/spec/frontend/fixtures/projects.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Projects (JavaScript fixtures)', type: :controller do + include ApiHelpers + include JavaScriptFixturesHelpers + + runners_token = 'runnerstoken:intabulasreferre' + + let(:namespace) { create(:namespace, name: 'frontend-fixtures' )} + let(:project) { create(:project, namespace: namespace, path: 'builds-project', runners_token: runners_token, avatar: fixture_file_upload('spec/fixtures/dk.png', 'image/png')) } + let(:user) { project.owner } + + describe GraphQL::Query, type: :request do + include GraphqlHelpers + context 'project storage statistics 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 = 'usage_quotas/storage/queries/' + base_output_path = 'graphql/usage_quotas/storage/' + 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}", ee: true) + + post_graphql(query, current_user: user, variables: { fullPath: project.full_path }) + + expect_graphql_errors_to_be_empty + end + end + end +end diff --git a/ee/spec/frontend/storage_counter/components/app_spec.js b/ee/spec/frontend/storage_counter/components/app_spec.js index 1f572596e87734383d5bfde44d3cac61b50e2037..76960d7fc7a5965e260598fbb0116b2edf07d0fc 100644 --- a/ee/spec/frontend/storage_counter/components/app_spec.js +++ b/ee/spec/frontend/storage_counter/components/app_spec.js @@ -1,7 +1,7 @@ import { mount } from '@vue/test-utils'; import StorageApp from 'ee/storage_counter/components/app.vue'; -import Project from 'ee/storage_counter/components/project.vue'; -import ProjectsTable from 'ee/storage_counter/components/projects_table.vue'; +import CollapsibleProjectStorageDetail from 'ee/usage_quotas/storage/components/collapsible_project_storage_detail.vue'; +import ProjectList from 'ee/usage_quotas/storage/components/project_list.vue'; import StorageInlineAlert from 'ee/storage_counter/components/storage_inline_alert.vue'; import TemporaryStorageIncreaseModal from 'ee/storage_counter/components/temporary_storage_increase_modal.vue'; import UsageStatistics from 'ee/storage_counter/components/usage_statistics.vue'; @@ -22,7 +22,7 @@ describe('Storage counter app', () => { const findUsageGraph = () => wrapper.find(UsageGraph); const findUsageStatistics = () => wrapper.find(UsageStatistics); const findStorageInlineAlert = () => wrapper.find(StorageInlineAlert); - const findProjectsTable = () => wrapper.find(ProjectsTable); + const findProjectList = () => wrapper.find(ProjectList); const findPrevButton = () => wrapper.find('[data-testid="prevButton"]'); const findNextButton = () => wrapper.find('[data-testid="nextButton"]'); @@ -74,7 +74,7 @@ describe('Storage counter app', () => { await wrapper.vm.$nextTick(); - expect(wrapper.findAll(Project)).toHaveLength(3); + expect(wrapper.findAll(CollapsibleProjectStorageDetail)).toHaveLength(3); }); describe('limit', () => { @@ -232,21 +232,21 @@ describe('Storage counter app', () => { it('triggers search if user enters search input', () => { expect(wrapper.vm.searchTerm).toBe(''); - findProjectsTable().vm.$emit('search', sampleSearchTerm); + findProjectList().vm.$emit('search', sampleSearchTerm); expect(wrapper.vm.searchTerm).toBe(sampleSearchTerm); }); it('triggers search if user clears the entered search input', () => { - const projectsTable = findProjectsTable(); + const projectList = findProjectList(); expect(wrapper.vm.searchTerm).toBe(''); - projectsTable.vm.$emit('search', sampleSearchTerm); + projectList.vm.$emit('search', sampleSearchTerm); expect(wrapper.vm.searchTerm).toBe(sampleSearchTerm); - projectsTable.vm.$emit('search', ''); + projectList.vm.$emit('search', ''); expect(wrapper.vm.searchTerm).toBe(''); }); @@ -254,7 +254,7 @@ describe('Storage counter app', () => { it('does not trigger search if user enters short search input', () => { expect(wrapper.vm.searchTerm).toBe(''); - findProjectsTable().vm.$emit('search', sampleShortSearchTerm); + findProjectList().vm.$emit('search', sampleShortSearchTerm); expect(wrapper.vm.searchTerm).toBe(''); }); diff --git a/ee/spec/frontend/storage_counter/components/storage_row_spec.js b/ee/spec/frontend/storage_counter/components/storage_row_spec.js deleted file mode 100644 index 2ff8ba581faaccb2f7d62debdb508750824daa6a..0000000000000000000000000000000000000000 --- a/ee/spec/frontend/storage_counter/components/storage_row_spec.js +++ /dev/null @@ -1,32 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import StorageRow from 'ee/storage_counter/components/storage_row.vue'; -import { numberToHumanSize } from '~/lib/utils/number_utils'; - -let wrapper; -const data = { - name: 'LFS Package', - value: 1293346, -}; - -function factory({ name, value }) { - wrapper = shallowMount(StorageRow, { - propsData: { - name, - value, - }, - }); -} - -describe('Storage Counter row component', () => { - beforeEach(() => { - factory(data); - }); - - it('renders provided name', () => { - expect(wrapper.text()).toContain(data.name); - }); - - it('renders formatted value', () => { - expect(wrapper.text()).toContain(numberToHumanSize(data.value)); - }); -}); diff --git a/ee/spec/frontend/storage_counter/mock_data.js b/ee/spec/frontend/storage_counter/mock_data.js index 84c03a13d94fd825dcef3a1a0490cd6fc99656ed..6b697882c6ad39255714c61b744c3e1bb005b5c2 100644 --- a/ee/spec/frontend/storage_counter/mock_data.js +++ b/ee/spec/frontend/storage_counter/mock_data.js @@ -1,62 +1,4 @@ -export const projects = [ - { - id: '24', - fullPath: 'h5bp/dummy-project', - nameWithNamespace: 'H5bp / dummy project', - avatarUrl: null, - webUrl: 'http://localhost:3001/h5bp/dummy-project', - name: 'dummy project', - statistics: { - commitCount: 1, - storageSize: 41943, - repositorySize: 41943, - lfsObjectsSize: 0, - buildArtifactsSize: 0, - packagesSize: 0, - }, - actualRepositorySizeLimit: 100000, - totalCalculatedUsedStorage: 41943, - totalCalculatedStorageLimit: 41943000, - }, - { - id: '8', - fullPath: 'h5bp/html5-boilerplate', - nameWithNamespace: 'H5bp / Html5 Boilerplate', - avatarUrl: null, - webUrl: 'http://localhost:3001/h5bp/html5-boilerplate', - name: 'Html5 Boilerplate', - statistics: { - commitCount: 0, - storageSize: 99000, - repositorySize: 0, - lfsObjectsSize: 0, - buildArtifactsSize: 1272375, - packagesSize: 0, - }, - actualRepositorySizeLimit: 100000, - totalCalculatedUsedStorage: 89000, - totalCalculatedStorageLimit: 99430, - }, - { - id: '80', - fullPath: 'twit/twitter', - nameWithNamespace: 'Twitter', - avatarUrl: null, - webUrl: 'http://localhost:3001/twit/twitter', - name: 'Twitter', - statistics: { - commitCount: 0, - storageSize: 12933460, - repositorySize: 209710, - lfsObjectsSize: 209720, - buildArtifactsSize: 1272375, - packagesSize: 0, - }, - actualRepositorySizeLimit: 100000, - totalCalculatedUsedStorage: 13143170, - totalCalculatedStorageLimit: 12143170, - }, -]; +import { projects } from 'ee_jest/usage_quotas/storage/mock_data'; export const namespaceData = { totalUsage: 'N/A', diff --git a/ee/spec/frontend/storage_counter/utils_spec.js b/ee/spec/frontend/storage_counter/utils_spec.js index ff7d194ab23f5b75ecea3b15cca77b76c9d78dcf..bdffe62a88904e7bbfd4ed2d23482b2b639cd7a9 100644 --- a/ee/spec/frontend/storage_counter/utils_spec.js +++ b/ee/spec/frontend/storage_counter/utils_spec.js @@ -4,7 +4,8 @@ import { parseProjects, calculateUsedAndRemStorage, } from 'ee/storage_counter/utils'; -import { projects as mockProjectsData, mockGetStorageCounterGraphQLResponse } from './mock_data'; +import { projects as mockProjectsData } from 'ee_jest/usage_quotas/storage/mock_data'; +import { mockGetStorageCounterGraphQLResponse } from './mock_data'; describe('UsageThreshold', () => { it.each` diff --git a/ee/spec/frontend/storage_counter/components/project_spec.js b/ee/spec/frontend/usage_quotas/storage/components/collapsible_project_storage_detail_spec.js similarity index 61% rename from ee/spec/frontend/storage_counter/components/project_spec.js rename to ee/spec/frontend/usage_quotas/storage/components/collapsible_project_storage_detail_spec.js index 9f0ed5a376f0873af1bedcf1e09cb38bcab968c9..c7186b19e96730658d222903bdd0c5c009c1474a 100644 --- a/ee/spec/frontend/storage_counter/components/project_spec.js +++ b/ee/spec/frontend/usage_quotas/storage/components/collapsible_project_storage_detail_spec.js @@ -1,13 +1,13 @@ import { shallowMount } from '@vue/test-utils'; -import Project from 'ee/storage_counter/components/project.vue'; -import StorageRow from 'ee/storage_counter/components/storage_row.vue'; +import CollapsibleProjectStorageDetail from 'ee/usage_quotas/storage/components/collapsible_project_storage_detail.vue'; +import ProjectStorageDetail from 'ee/usage_quotas/storage/components/project_storage_detail.vue'; import { numberToHumanSize } from '~/lib/utils/number_utils'; -import ProjectAvatar from '~/vue_shared/components/deprecated_project_avatar/default.vue'; +import ProjectAvatar from '~/vue_shared/components/project_avatar.vue'; import { projects } from '../mock_data'; let wrapper; const createComponent = () => { - wrapper = shallowMount(Project, { + wrapper = shallowMount(CollapsibleProjectStorageDetail, { propsData: { project: projects[1], }, @@ -15,9 +15,9 @@ const createComponent = () => { }; const findTableRow = () => wrapper.find('[data-testid="projectTableRow"]'); -const findStorageRow = () => wrapper.find(StorageRow); +const findProjectStorageDetail = () => wrapper.find(ProjectStorageDetail); -describe('Storage Counter project component', () => { +describe('CollapsibleProjectStorageDetail', () => { beforeEach(() => { createComponent(); }); @@ -37,16 +37,16 @@ describe('Storage Counter project component', () => { describe('toggle row', () => { describe('on click', () => { it('toggles isOpen', () => { - expect(findStorageRow().exists()).toBe(false); + expect(findProjectStorageDetail().exists()).toBe(false); findTableRow().trigger('click'); wrapper.vm.$nextTick(() => { - expect(findStorageRow().exists()).toBe(true); + expect(findProjectStorageDetail().exists()).toBe(true); findTableRow().trigger('click'); wrapper.vm.$nextTick(() => { - expect(findStorageRow().exists()).toBe(false); + expect(findProjectStorageDetail().exists()).toBe(false); }); }); }); diff --git a/ee/spec/frontend/storage_counter/components/projects_table_spec.js b/ee/spec/frontend/usage_quotas/storage/components/project_list_spec.js similarity index 71% rename from ee/spec/frontend/storage_counter/components/projects_table_spec.js rename to ee/spec/frontend/usage_quotas/storage/components/project_list_spec.js index 65ae469d3e0c76161d74728b9b13285d9bbac2bd..4c4aee9c1a57b2fccc6d8478b291a27d1611d815 100644 --- a/ee/spec/frontend/storage_counter/components/projects_table_spec.js +++ b/ee/spec/frontend/usage_quotas/storage/components/project_list_spec.js @@ -1,12 +1,12 @@ import { shallowMount } from '@vue/test-utils'; -import Project from 'ee/storage_counter/components/project.vue'; -import ProjectsTable from 'ee/storage_counter/components/projects_table.vue'; +import CollapsibleProjectStorageDetail from 'ee/usage_quotas/storage/components/collapsible_project_storage_detail.vue'; +import ProjectList from 'ee/usage_quotas/storage/components/project_list.vue'; import { projects } from '../mock_data'; let wrapper; const createComponent = ({ additionalRepoStorageByNamespace = false } = {}) => { - wrapper = shallowMount(ProjectsTable, { + wrapper = shallowMount(ProjectList, { propsData: { projects, additionalPurchasedStorageSize: 0, @@ -19,9 +19,9 @@ const createComponent = ({ additionalRepoStorageByNamespace = false } = {}) => { }); }; -const findTableRows = () => wrapper.findAll(Project); +const findTableRows = () => wrapper.findAll(CollapsibleProjectStorageDetail); -describe('Usage Quotas project table component', () => { +describe('ProjectList', () => { beforeEach(() => { createComponent(); }); diff --git a/spec/frontend/projects/storage_counter/components/app_spec.js b/ee/spec/frontend/usage_quotas/storage/components/project_storage_app_spec.js similarity index 81% rename from spec/frontend/projects/storage_counter/components/app_spec.js rename to ee/spec/frontend/usage_quotas/storage/components/project_storage_app_spec.js index f3da01e0602613ba98eba49f63d149cd1c47e952..fdd317f46a71745976908d84049aa5f7cf13c609 100644 --- a/spec/frontend/projects/storage_counter/components/app_spec.js +++ b/ee/spec/frontend/usage_quotas/storage/components/project_storage_app_spec.js @@ -4,21 +4,21 @@ 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 ProjectStorageApp from 'ee/usage_quotas/storage/components/project_storage_app.vue'; +import { TOTAL_USAGE_DEFAULT_TEXT } from 'ee/usage_quotas/storage/constants'; +import getProjectStorageStatistics from 'ee/usage_quotas/storage/queries/project_storage.query.graphql'; import UsageGraph from '~/vue_shared/components/storage_counter/usage_graph.vue'; import { - mockGetProjectStorageCountGraphQLResponse, - mockEmptyResponse, projectData, - defaultProvideValues, + mockGetProjectStorageStatisticsGraphQLResponse, + mockEmptyResponse, + defaultProjectProvideValues, } from '../mock_data'; const localVue = createLocalVue(); localVue.use(VueApollo); -describe('Storage counter app', () => { +describe('ProjectStorageApp', () => { let wrapper; const createMockApolloProvider = ({ reject = false, mockedValue } = {}) => { @@ -30,18 +30,18 @@ describe('Storage counter app', () => { response = jest.fn().mockResolvedValue(mockedValue); } - const requestHandlers = [[getProjectStorageCount, response]]; + const requestHandlers = [[getProjectStorageStatistics, response]]; return createMockApollo(requestHandlers); }; const createComponent = ({ provide = {}, mockApollo } = {}) => { wrapper = extendedWrapper( - shallowMount(StorageCounterApp, { + shallowMount(ProjectStorageApp, { localVue, apolloProvider: mockApollo, provide: { - ...defaultProvideValues, + ...defaultProjectProvideValues, ...provide, }, }), @@ -63,7 +63,7 @@ describe('Storage counter app', () => { beforeEach(async () => { mockApollo = createMockApolloProvider({ - mockedValue: mockGetProjectStorageCountGraphQLResponse, + mockedValue: mockGetProjectStorageStatisticsGraphQLResponse, }); createComponent({ mockApollo }); await waitForPromises(); @@ -75,7 +75,7 @@ describe('Storage counter app', () => { it('renders correct usage quotas help link', () => { expect(findUsageQuotasHelpLink().attributes('href')).toBe( - defaultProvideValues.helpLinks.usageQuotasHelpPagePath, + defaultProjectProvideValues.helpLinks.usageQuotasHelpPagePath, ); }); }); @@ -129,7 +129,7 @@ describe('Storage counter app', () => { beforeEach(async () => { mockApollo = createMockApolloProvider({ - mockedValue: mockGetProjectStorageCountGraphQLResponse, + mockedValue: mockGetProjectStorageStatisticsGraphQLResponse, }); createComponent({ mockApollo }); await waitForPromises(); @@ -143,7 +143,7 @@ describe('Storage counter app', () => { const { __typename, ...statistics - } = mockGetProjectStorageCountGraphQLResponse.data.project.statistics; + } = mockGetProjectStorageStatisticsGraphQLResponse.data.project.statistics; expect(findUsageGraph().props('rootStorageStatistics')).toMatchObject(statistics); }); }); diff --git a/spec/frontend/projects/storage_counter/components/storage_table_spec.js b/ee/spec/frontend/usage_quotas/storage/components/project_storage_detail_spec.js similarity index 84% rename from spec/frontend/projects/storage_counter/components/storage_table_spec.js rename to ee/spec/frontend/usage_quotas/storage/components/project_storage_detail_spec.js index c9e56d8f0334bf08ec6040423ef8a31a62f6ac48..d76e97fdab622afc280625b73790753889fe0ba8 100644 --- a/spec/frontend/projects/storage_counter/components/storage_table_spec.js +++ b/ee/spec/frontend/usage_quotas/storage/components/project_storage_detail_spec.js @@ -1,10 +1,10 @@ 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'; +import ProjectStorageDetail from 'ee/usage_quotas/storage/components/project_storage_detail.vue'; +import { projectData, projectHelpLinks } from '../mock_data'; -describe('StorageTable', () => { +describe('ProjectStorageDetail', () => { let wrapper; const defaultProps = { @@ -13,7 +13,7 @@ describe('StorageTable', () => { const createComponent = (props = {}) => { wrapper = extendedWrapper( - mount(StorageTable, { + mount(ProjectStorageDetail, { propsData: { ...defaultProps, ...props, @@ -39,7 +39,7 @@ describe('StorageTable', () => { 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`)] + projectHelpLinks[id.replace(`Size`, `HelpPagePath`)] .replace(`Size`, ``) .replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`), ); diff --git a/ee/spec/frontend/storage_counter/components/projects_skeleton_loader_spec.js b/ee/spec/frontend/usage_quotas/storage/components/projects_skeleton_loader_spec.js similarity index 92% rename from ee/spec/frontend/storage_counter/components/projects_skeleton_loader_spec.js rename to ee/spec/frontend/usage_quotas/storage/components/projects_skeleton_loader_spec.js index daa9105ed5d98b7888801eca779b39700aadac73..2a185d3985163bdfac534d4ad190c833946d8453 100644 --- a/ee/spec/frontend/storage_counter/components/projects_skeleton_loader_spec.js +++ b/ee/spec/frontend/usage_quotas/storage/components/projects_skeleton_loader_spec.js @@ -1,5 +1,5 @@ import { mount } from '@vue/test-utils'; -import ProjectsSkeletonLoader from 'ee/storage_counter/components/projects_skeleton_loader.vue'; +import ProjectsSkeletonLoader from 'ee/usage_quotas/storage/components/projects_skeleton_loader.vue'; describe('ProjectsSkeletonLoader', () => { let wrapper; diff --git a/spec/frontend/projects/storage_counter/components/storage_type_icon_spec.js b/ee/spec/frontend/usage_quotas/storage/components/storage_type_icon_spec.js similarity index 92% rename from spec/frontend/projects/storage_counter/components/storage_type_icon_spec.js rename to ee/spec/frontend/usage_quotas/storage/components/storage_type_icon_spec.js index 01efd6f14bd1ccf5fa5f78c914f3269175a810a8..02e76ced43a197df5879633763a7ed499f9e5985 100644 --- a/spec/frontend/projects/storage_counter/components/storage_type_icon_spec.js +++ b/ee/spec/frontend/usage_quotas/storage/components/storage_type_icon_spec.js @@ -1,6 +1,6 @@ import { mount } from '@vue/test-utils'; import { GlIcon } from '@gitlab/ui'; -import StorageTypeIcon from '~/projects/storage_counter/components/storage_type_icon.vue'; +import StorageTypeIcon from 'ee/usage_quotas/storage/components/storage_type_icon.vue'; describe('StorageTypeIcon', () => { let wrapper; diff --git a/ee/spec/frontend/usage_quotas/storage/mock_data.js b/ee/spec/frontend/usage_quotas/storage/mock_data.js new file mode 100644 index 0000000000000000000000000000000000000000..e38a1b472645c319f6e240724c645ffdb622d047 --- /dev/null +++ b/ee/spec/frontend/usage_quotas/storage/mock_data.js @@ -0,0 +1,154 @@ +import mockGetProjectStorageStatisticsGraphQLResponse from 'test_fixtures/graphql/usage_quotas/storage/project_storage.query.graphql.json'; + +export { mockGetProjectStorageStatisticsGraphQLResponse }; + +export const mockEmptyResponse = { data: { project: null } }; + +export const projects = [ + { + id: '24', + fullPath: 'h5bp/dummy-project', + nameWithNamespace: 'H5bp / dummy project', + avatarUrl: null, + webUrl: 'http://localhost:3001/h5bp/dummy-project', + name: 'dummy project', + statistics: { + commitCount: 1, + storageSize: 41943, + repositorySize: 41943, + lfsObjectsSize: 0, + buildArtifactsSize: 0, + packagesSize: 0, + }, + actualRepositorySizeLimit: 100000, + totalCalculatedUsedStorage: 41943, + totalCalculatedStorageLimit: 41943000, + }, + { + id: '8', + fullPath: 'h5bp/html5-boilerplate', + nameWithNamespace: 'H5bp / Html5 Boilerplate', + avatarUrl: null, + webUrl: 'http://localhost:3001/h5bp/html5-boilerplate', + name: 'Html5 Boilerplate', + statistics: { + commitCount: 0, + storageSize: 99000, + repositorySize: 0, + lfsObjectsSize: 0, + buildArtifactsSize: 1272375, + packagesSize: 0, + }, + actualRepositorySizeLimit: 100000, + totalCalculatedUsedStorage: 89000, + totalCalculatedStorageLimit: 99430, + }, + { + id: '80', + fullPath: 'twit/twitter', + nameWithNamespace: 'Twitter', + avatarUrl: null, + webUrl: 'http://localhost:3001/twit/twitter', + name: 'Twitter', + statistics: { + commitCount: 0, + storageSize: 12933460, + repositorySize: 209710, + lfsObjectsSize: 209720, + buildArtifactsSize: 1272375, + packagesSize: 0, + }, + actualRepositorySizeLimit: 100000, + totalCalculatedUsedStorage: 13143170, + totalCalculatedStorageLimit: 12143170, + }, +]; + +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, + }, + ], + }, +}; + +export const projectHelpLinks = { + usageQuotasHelpPagePath: '/usage-quotas', + buildArtifactsHelpPagePath: '/build-artifacts', + lfsObjectsHelpPagePath: '/lsf-objects', + packagesHelpPagePath: '/packages', + repositoryHelpPagePath: '/repository', + snippetsHelpPagePath: '/snippets', + uploadsHelpPagePath: '/uploads', + wikiHelpPagePath: '/wiki', +}; + +export const defaultProjectProvideValues = { + projectPath: '/project-path', + helpLinks: projectHelpLinks, +}; diff --git a/spec/frontend/projects/storage_counter/utils_spec.js b/ee/spec/frontend/usage_quotas/storage/utils_spec.js similarity index 57% rename from spec/frontend/projects/storage_counter/utils_spec.js rename to ee/spec/frontend/usage_quotas/storage/utils_spec.js index fb91975a3cf9e3f3f0296e38bb6aa914ed2d5e65..79ff5a647cfacd491c2b207ade8415d695f7c274 100644 --- a/spec/frontend/projects/storage_counter/utils_spec.js +++ b/ee/spec/frontend/usage_quotas/storage/utils_spec.js @@ -1,26 +1,29 @@ -import { parseGetProjectStorageResults } from '~/projects/storage_counter/utils'; +import { parseGetProjectStorageResults } from 'ee/usage_quotas/storage/utils'; import { - mockGetProjectStorageCountGraphQLResponse, projectData, - defaultProvideValues, + mockGetProjectStorageStatisticsGraphQLResponse, + defaultProjectProvideValues, } from './mock_data'; describe('parseGetProjectStorageResults', () => { it('parses project statistics correctly', () => { expect( parseGetProjectStorageResults( - mockGetProjectStorageCountGraphQLResponse.data, - defaultProvideValues.helpLinks, + mockGetProjectStorageStatisticsGraphQLResponse.data, + defaultProjectProvideValues.helpLinks, ), ).toMatchObject(projectData); }); it('includes storage type with size of 0 in returned value', () => { - const mockedResponse = mockGetProjectStorageCountGraphQLResponse.data; + const mockedResponse = mockGetProjectStorageStatisticsGraphQLResponse.data; // ensuring a specific storage type item has size of 0 mockedResponse.project.statistics.repositorySize = 0; - const response = parseGetProjectStorageResults(mockedResponse, defaultProvideValues.helpLinks); + const response = parseGetProjectStorageResults( + mockedResponse, + defaultProjectProvideValues.helpLinks, + ); expect(response.storage.storageTypes).toEqual( expect.arrayContaining([ diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 7d3e4fedf92fecc0b663603fa0eed0e757572363..f5de4ae8bc2ccd1807c106f30a68f3b61f965919 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -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 "" diff --git a/spec/frontend/fixtures/projects.rb b/spec/frontend/fixtures/projects.rb index 23c18c97df20ac09acbaecfa3da81443021991cd..3c8964d398ad6401e6be5b0acbe1167d0262b142 100644 --- a/spec/frontend/fixtures/projects.rb +++ b/spec/frontend/fixtures/projects.rb @@ -65,31 +65,5 @@ 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 diff --git a/spec/frontend/projects/storage_counter/mock_data.js b/spec/frontend/projects/storage_counter/mock_data.js deleted file mode 100644 index 6b3e23ac386a98ecc97e205266144080ae8eb343..0000000000000000000000000000000000000000 --- a/spec/frontend/projects/storage_counter/mock_data.js +++ /dev/null @@ -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, - }, - ], - }, -};