summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.eslintrc.yml3
-rw-r--r--app/assets/javascripts/diffs/components/app.vue5
-rw-r--r--app/assets/javascripts/diffs/store/actions.js7
-rw-r--r--app/assets/javascripts/ide/stores/getters.js25
-rw-r--r--app/assets/javascripts/pages/projects/snippets/show/index.js15
-rw-r--r--app/assets/javascripts/repository/components/breadcrumbs.vue4
-rw-r--r--app/assets/javascripts/repository/components/table/parent_row.vue2
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue2
-rw-r--r--app/assets/javascripts/repository/router.js2
-rw-r--r--app/assets/javascripts/snippets/components/app.vue29
-rw-r--r--app/assets/javascripts/snippets/components/snippet_header.vue241
-rw-r--r--app/assets/javascripts/snippets/fragments/author.fragment.graphql8
-rw-r--r--app/assets/javascripts/snippets/fragments/project.fragment.graphql6
-rw-r--r--app/assets/javascripts/snippets/fragments/snippetBase.fragment.graphql13
-rw-r--r--app/assets/javascripts/snippets/mutations/deleteSnippet.mutation.graphql5
-rw-r--r--app/assets/javascripts/snippets/queries/getSnippet.query.graphql13
-rw-r--r--app/assets/javascripts/snippets/queries/projectPermissions.query.graphql7
-rw-r--r--app/assets/javascripts/snippets/queries/snippet.query.graphql15
-rw-r--r--app/assets/javascripts/snippets/queries/userPermissions.query.graphql7
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue4
-rw-r--r--app/assets/stylesheets/utilities.scss2
-rw-r--r--app/helpers/submodule_helper.rb2
-rw-r--r--app/helpers/tree_helper.rb4
-rw-r--r--app/models/clusters/applications/knative.rb2
-rw-r--r--app/views/admin/users/_access_levels.html.haml2
-rw-r--r--app/views/dashboard/_snippets_head.html.haml3
-rw-r--r--app/views/dashboard/snippets/index.html.haml3
-rw-r--r--app/views/profiles/accounts/_providers.html.haml2
-rw-r--r--app/views/projects/snippets/index.html.haml3
-rw-r--r--app/views/projects/snippets/show.html.haml17
-rw-r--r--app/views/shared/empty_states/_snippets.html.haml3
-rw-r--r--app/views/snippets/_snippets.html.haml2
-rw-r--r--babel.config.js1
-rw-r--r--changelogs/unreleased/39498-part-1.yml5
-rw-r--r--changelogs/unreleased/ap-14330-external-personal-snippets.yml5
-rw-r--r--changelogs/unreleased/dz-scope-repository-routes.yml5
-rw-r--r--changelogs/unreleased/knative-0-9-update.yml5
-rw-r--r--changelogs/unreleased/service-desk-name.yml5
-rw-r--r--config/prometheus/common_metrics.yml2
-rw-r--r--config/routes/project.rb3
-rw-r--r--config/routes/repository.rb2
-rw-r--r--db/migrate/20191213104838_add_service_desk_username.rb9
-rw-r--r--db/post_migrate/20191209215316_knative_0_9_prometheus_update.rb13
-rw-r--r--db/schema.rb3
-rw-r--r--doc/development/background_migrations.md10
-rw-r--r--doc/development/fe_guide/graphql.md50
-rw-r--r--doc/user/permissions.md2
-rw-r--r--lib/banzai/filter/relative_link_filter.rb9
-rw-r--r--lib/gitlab/dependency_linker/godeps_json_linker.rb6
-rw-r--r--lib/gitlab/import_export/import_export.yml2
-rw-r--r--lib/gitlab/middleware/go.rb2
-rw-r--r--lib/quality/test_level.rb9
-rw-r--r--locale/gitlab.pot21
-rw-r--r--package.json1
-rw-r--r--scripts/review_apps/base-config.yaml4
-rw-r--r--spec/controllers/concerns/metrics_dashboard_spec.rb2
-rw-r--r--spec/controllers/projects/blame_controller_spec.rb2
-rw-r--r--spec/controllers/projects/blob_controller_spec.rb4
-rw-r--r--spec/controllers/projects/branches_controller_spec.rb6
-rw-r--r--spec/controllers/projects/raw_controller_spec.rb2
-rw-r--r--spec/controllers/projects/serverless/functions_controller_spec.rb16
-rw-r--r--spec/controllers/projects/tree_controller_spec.rb10
-rw-r--r--spec/controllers/projects_controller_spec.rb2
-rw-r--r--spec/features/dashboard/snippets_spec.rb34
-rw-r--r--spec/features/discussion_comments/snippets_spec.rb1
-rw-r--r--spec/features/issues/move_spec.rb1
-rw-r--r--spec/features/issues/user_views_issues_spec.rb1
-rw-r--r--spec/features/merge_requests/user_sorts_merge_requests_spec.rb1
-rw-r--r--spec/features/merge_requests/user_views_open_merge_requests_spec.rb1
-rw-r--r--spec/features/oauth_login_spec.rb1
-rw-r--r--spec/features/participants_autocomplete_spec.rb2
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb1
-rw-r--r--spec/features/projects/files/user_edits_files_spec.rb1
-rw-r--r--spec/features/projects/snippets/create_snippet_spec.rb5
-rw-r--r--spec/features/projects/snippets/show_spec.rb1
-rw-r--r--spec/features/projects/snippets/user_comments_on_snippet_spec.rb1
-rw-r--r--spec/features/projects/snippets/user_deletes_snippet_spec.rb1
-rw-r--r--spec/features/projects/snippets/user_updates_snippet_spec.rb1
-rw-r--r--spec/features/reportable_note/snippets_spec.rb1
-rw-r--r--spec/features/security/group/internal_access_spec.rb1
-rw-r--r--spec/features/security/group/private_access_spec.rb1
-rw-r--r--spec/features/security/group/public_access_spec.rb1
-rw-r--r--spec/features/security/project/internal_access_spec.rb7
-rw-r--r--spec/features/security/project/private_access_spec.rb7
-rw-r--r--spec/features/security/project/public_access_spec.rb6
-rw-r--r--spec/features/snippets/explore_spec.rb63
-rw-r--r--spec/features/task_lists_spec.rb1
-rw-r--r--spec/features/users/login_spec.rb1
-rw-r--r--spec/finders/clusters_finder_spec.rb1
-rw-r--r--spec/finders/group_descendants_finder_spec.rb1
-rw-r--r--spec/finders/group_projects_finder_spec.rb2
-rw-r--r--spec/finders/groups_finder_spec.rb2
-rw-r--r--spec/finders/issues_finder_spec.rb1
-rw-r--r--spec/finders/merge_request_target_project_finder_spec.rb1
-rw-r--r--spec/finders/pipelines_finder_spec.rb1
-rw-r--r--spec/finders/projects_finder_spec.rb2
-rw-r--r--spec/finders/tags_finder_spec.rb1
-rw-r--r--spec/frontend/fixtures/static/projects.json9
-rw-r--r--spec/frontend/helpers/dom_shims/index.js1
-rw-r--r--spec/frontend/helpers/dom_shims/inner_text.js11
-rw-r--r--spec/frontend/ide/stores/getters_spec.js92
-rw-r--r--spec/frontend/monitoring/components/charts/column_spec.js (renamed from spec/javascripts/monitoring/charts/column_spec.js)4
-rw-r--r--spec/frontend/monitoring/components/charts/empty_chart_spec.js (renamed from spec/javascripts/monitoring/charts/empty_chart_spec.js)0
-rw-r--r--spec/frontend/monitoring/components/charts/heatmap_spec.js (renamed from spec/javascripts/monitoring/charts/heatmap_spec.js)2
-rw-r--r--spec/frontend/monitoring/components/charts/single_stat_spec.js (renamed from spec/javascripts/monitoring/charts/single_stat_spec.js)2
-rw-r--r--spec/frontend/monitoring/components/charts/time_series_spec.js (renamed from spec/frontend/monitoring/charts/time_series_spec.js)12
-rw-r--r--spec/frontend/repository/components/table/parent_row_spec.js8
-rw-r--r--spec/frontend/repository/components/table/row_spec.js2
-rw-r--r--spec/frontend/repository/router_spec.js10
-rw-r--r--spec/frontend/snippets/components/app_spec.js26
-rw-r--r--spec/frontend/snippets/components/snippet_header_spec.js171
-rw-r--r--spec/frontend/test_setup.js12
-rw-r--r--spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb1
-rw-r--r--spec/graphql/mutations/concerns/mutations/resolves_project_spec.rb1
-rw-r--r--spec/graphql/mutations/issues/set_confidential_spec.rb2
-rw-r--r--spec/graphql/mutations/issues/set_due_date_spec.rb2
-rw-r--r--spec/graphql/mutations/merge_requests/set_assignees_spec.rb2
-rw-r--r--spec/graphql/mutations/merge_requests/set_labels_spec.rb2
-rw-r--r--spec/graphql/mutations/merge_requests/set_locked_spec.rb2
-rw-r--r--spec/graphql/mutations/merge_requests/set_milestone_spec.rb2
-rw-r--r--spec/graphql/mutations/merge_requests/set_subscription_spec.rb2
-rw-r--r--spec/graphql/mutations/merge_requests/set_wip_spec.rb2
-rw-r--r--spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb1
-rw-r--r--spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb1
-rw-r--r--spec/graphql/types/permission_types/base_permission_type_spec.rb1
-rw-r--r--spec/helpers/avatars_helper_spec.rb1
-rw-r--r--spec/helpers/blob_helper_spec.rb4
-rw-r--r--spec/helpers/events_helper_spec.rb1
-rw-r--r--spec/helpers/groups_helper_spec.rb3
-rw-r--r--spec/helpers/issuables_helper_spec.rb1
-rw-r--r--spec/helpers/labels_helper_spec.rb1
-rw-r--r--spec/helpers/markup_helper_spec.rb4
-rw-r--r--spec/helpers/merge_requests_helper_spec.rb1
-rw-r--r--spec/helpers/projects_helper_spec.rb3
-rw-r--r--spec/helpers/submodule_helper_spec.rb4
-rw-r--r--spec/javascripts/diffs/components/app_spec.js8
-rw-r--r--spec/javascripts/diffs/store/actions_spec.js10
-rw-r--r--spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js4
-rw-r--r--spec/lib/banzai/filter/relative_link_filter_spec.rb36
-rw-r--r--spec/lib/gitlab/conflict/file_spec.rb2
-rw-r--r--spec/lib/gitlab/database_spec.rb1
-rw-r--r--spec/lib/gitlab/dependency_linker/godeps_json_linker_spec.rb4
-rw-r--r--spec/lib/gitlab/middleware/go_spec.rb2
-rw-r--r--spec/lib/gitlab/prometheus/queries/knative_invocation_query_spec.rb4
-rw-r--r--spec/lib/quality/test_level_spec.rb4
-rw-r--r--spec/mailers/notify_spec.rb12
-rw-r--r--spec/models/clusters/applications/knative_spec.rb2
-rw-r--r--spec/models/project_spec.rb2
-rw-r--r--spec/policies/project_policy_spec.rb2
-rw-r--r--spec/presenters/blob_presenter_spec.rb2
-rw-r--r--spec/presenters/label_presenter_spec.rb1
-rw-r--r--spec/presenters/merge_request_presenter_spec.rb8
-rw-r--r--spec/presenters/project_presenter_spec.rb1
-rw-r--r--spec/presenters/tree_entry_presenter_spec.rb2
-rw-r--r--spec/requests/api/award_emoji_spec.rb1
-rw-r--r--spec/requests/api/boards_spec.rb1
-rw-r--r--spec/requests/api/graphql/mutations/award_emojis/add_spec.rb1
-rw-r--r--spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb1
-rw-r--r--spec/requests/api/project_import_spec.rb1
-rw-r--r--spec/requests/api/projects_spec.rb3
-rw-r--r--spec/requests/api/settings_spec.rb1
-rw-r--r--spec/requests/api/snippets_spec.rb1
-rw-r--r--spec/requests/api/users_spec.rb1
-rw-r--r--spec/requests/git_http_spec.rb4
-rw-r--r--spec/routing/project_routing_spec.rb64
-rw-r--r--spec/serializers/blob_entity_spec.rb2
-rw-r--r--spec/serializers/cluster_application_entity_spec.rb1
-rw-r--r--spec/serializers/cluster_entity_spec.rb1
-rw-r--r--spec/serializers/environment_entity_spec.rb1
-rw-r--r--spec/serializers/group_child_entity_spec.rb1
-rw-r--r--spec/serializers/group_child_serializer_spec.rb1
-rw-r--r--spec/serializers/merge_request_poll_widget_entity_spec.rb2
-rw-r--r--spec/serializers/note_entity_spec.rb1
-rw-r--r--spec/serializers/project_note_entity_spec.rb1
-rw-r--r--spec/serializers/user_entity_spec.rb1
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb54
-rw-r--r--spec/support/shared_examples/policies/project_policy_shared_examples.rb1
-rw-r--r--spec/uploaders/file_mover_spec.rb1
-rw-r--r--spec/validators/addressable_url_validator_spec.rb1
-rw-r--r--spec/validators/devise_email_validator_spec.rb1
-rw-r--r--spec/views/help/index.html.haml_spec.rb2
-rw-r--r--spec/workers/expire_job_cache_worker_spec.rb1
-rw-r--r--spec/workers/expire_pipeline_cache_worker_spec.rb1
-rw-r--r--spec/workers/mail_scheduler/notification_service_worker_spec.rb1
-rw-r--r--spec/workers/repository_check/batch_worker_spec.rb1
-rw-r--r--yarn.lock15
186 files changed, 1247 insertions, 266 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml
index a55e65c2678..a8cbd9731a3 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -2,6 +2,7 @@ extends:
- '@gitlab'
- plugin:promise/recommended
- plugin:no-jquery/slim
+ - plugin:no-jquery/deprecated-3.4
globals:
__webpack_public_path__: true
gl: false
@@ -48,8 +49,10 @@ rules:
no-jquery/no-animate: off
# all offenses of no-jquery/no-animate-toggle are false positives ( $toast.show() )
no-jquery/no-animate-toggle: off
+ no-jquery/no-event-shorthand: off
no-jquery/no-fade: off
no-jquery/no-serialize: error
+ no-jquery/no-sizzle: off
promise/always-return: off
promise/no-callback-in-promise: off
overrides:
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 8fc8a8d0495..8ea443814e9 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -220,9 +220,6 @@ export default {
this.assignedDiscussions = false;
this.fetchData(false);
},
- isLatestVersion() {
- return window.location.search.indexOf('diff_id') === -1;
- },
startDiffRendering() {
requestIdleCallback(
() => {
@@ -232,7 +229,7 @@ export default {
);
},
fetchData(toggleTree = true) {
- if (this.isLatestVersion() && this.glFeatures.diffsBatchLoad) {
+ if (this.glFeatures.diffsBatchLoad) {
this.fetchDiffFilesMeta()
.then(() => {
if (toggleTree) this.hideTreeListIfJustOneFile();
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index 44672659f56..992b45c97ac 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -90,14 +90,13 @@ export const fetchDiffFiles = ({ state, commit }) => {
};
export const fetchDiffFilesBatch = ({ commit, state }) => {
- const baseUrl = `${state.endpointBatch}?per_page=${DIFFS_PER_PAGE}`;
- const url = page => (page ? `${baseUrl}&page=${page}` : baseUrl);
-
commit(types.SET_BATCH_LOADING, true);
const getBatch = page =>
axios
- .get(url(page))
+ .get(state.endpointBatch, {
+ params: { page, per_page: DIFFS_PER_PAGE, w: state.showWhitespace ? '0' : '1' },
+ })
.then(({ data: { pagination, diff_files } }) => {
commit(types.SET_DIFF_DATA_BATCH, { diff_files });
commit(types.SET_BATCH_LOADING, false);
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index a176fd0aca8..bb8374b4e78 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -115,5 +115,30 @@ export const isOnDefaultBranch = (_state, getters) =>
export const canPushToBranch = (_state, getters) =>
getters.currentBranch && getters.currentBranch.can_push;
+export const isFileDeletedAndReadded = (state, getters) => path => {
+ const stagedFile = getters.getStagedFile(path);
+ const file = state.entries[path];
+ return Boolean(stagedFile && stagedFile.deleted && file.tempFile);
+};
+
+// checks if any diff exists in the staged or unstaged changes for this path
+export const getDiffInfo = (state, getters) => path => {
+ const stagedFile = getters.getStagedFile(path);
+ const file = state.entries[path];
+ const renamed = file.prevPath ? file.path !== file.prevPath : false;
+ const deletedAndReadded = getters.isFileDeletedAndReadded(path);
+ const deleted = deletedAndReadded ? false : file.deleted;
+ const tempFile = deletedAndReadded ? false : file.tempFile;
+ const changed = file.content !== (deletedAndReadded ? stagedFile.raw : file.raw);
+
+ return {
+ exists: changed || renamed || deleted || tempFile,
+ changed,
+ renamed,
+ deleted,
+ tempFile,
+ };
+};
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/pages/projects/snippets/show/index.js b/app/assets/javascripts/pages/projects/snippets/show/index.js
index c35b9c30058..738bf08f1bf 100644
--- a/app/assets/javascripts/pages/projects/snippets/show/index.js
+++ b/app/assets/javascripts/pages/projects/snippets/show/index.js
@@ -3,11 +3,16 @@ import ZenMode from '~/zen_mode';
import LineHighlighter from '~/line_highlighter';
import BlobViewer from '~/blob/viewer';
import snippetEmbed from '~/snippet/snippet_embed';
+import initSnippetsApp from '~/snippets';
document.addEventListener('DOMContentLoaded', () => {
- new LineHighlighter(); // eslint-disable-line no-new
- new BlobViewer(); // eslint-disable-line no-new
- initNotes();
- new ZenMode(); // eslint-disable-line no-new
- snippetEmbed();
+ if (!gon.features.snippetsVue) {
+ new LineHighlighter(); // eslint-disable-line no-new
+ new BlobViewer(); // eslint-disable-line no-new
+ initNotes();
+ new ZenMode(); // eslint-disable-line no-new
+ snippetEmbed();
+ } else {
+ initSnippetsApp();
+ }
});
diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue
index f6b9ea5d30d..e1382aa86d9 100644
--- a/app/assets/javascripts/repository/components/breadcrumbs.vue
+++ b/app/assets/javascripts/repository/components/breadcrumbs.vue
@@ -104,10 +104,10 @@ export default {
return acc.concat({
name,
path,
- to: `/tree/${this.ref}${path}`,
+ to: `/-/tree/${this.ref}${path}`,
});
},
- [{ name: this.projectShortPath, path: '/', to: `/tree/${this.ref}/` }],
+ [{ name: this.projectShortPath, path: '/', to: `/-/tree/${this.ref}/` }],
);
},
canCreateMrFromFork() {
diff --git a/app/assets/javascripts/repository/components/table/parent_row.vue b/app/assets/javascripts/repository/components/table/parent_row.vue
index 3c39f404226..38aa672bc1c 100644
--- a/app/assets/javascripts/repository/components/table/parent_row.vue
+++ b/app/assets/javascripts/repository/components/table/parent_row.vue
@@ -15,7 +15,7 @@ export default {
const splitArray = this.path.split('/');
splitArray.pop();
- return { path: `/tree/${this.commitRef}/${splitArray.join('/')}` };
+ return { path: `/-/tree/${this.commitRef}/${splitArray.join('/')}` };
},
},
methods: {
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index cf0457a2abf..57dd08c2142 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -84,7 +84,7 @@ export default {
},
computed: {
routerLinkTo() {
- return this.isFolder ? { path: `/tree/${this.ref}/${this.path}` } : null;
+ return this.isFolder ? { path: `/-/tree/${this.ref}/${this.path}` } : null;
},
iconName() {
return `fa-${getIconName(this.type, this.path)}`;
diff --git a/app/assets/javascripts/repository/router.js b/app/assets/javascripts/repository/router.js
index ebf0a7091ea..fa544444be8 100644
--- a/app/assets/javascripts/repository/router.js
+++ b/app/assets/javascripts/repository/router.js
@@ -12,7 +12,7 @@ export default function createRouter(base, baseRef) {
base: joinPaths(gon.relative_url_root || '', base),
routes: [
{
- path: `/tree/${baseRef}(/.*)?`,
+ path: `/-/tree/${baseRef}(/.*)?`,
name: 'treePath',
component: TreePage,
props: route => ({
diff --git a/app/assets/javascripts/snippets/components/app.vue b/app/assets/javascripts/snippets/components/app.vue
index e3d6cdd4606..bd2cb8e4595 100644
--- a/app/assets/javascripts/snippets/components/app.vue
+++ b/app/assets/javascripts/snippets/components/app.vue
@@ -1,10 +1,16 @@
<script>
-import getSnippet from '../queries/getSnippet.query.graphql';
+import GetSnippetQuery from '../queries/snippet.query.graphql';
+import SnippetHeader from './snippet_header.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
+ components: {
+ SnippetHeader,
+ GlLoadingIcon,
+ },
apollo: {
- snippetData: {
- query: getSnippet,
+ snippet: {
+ query: GetSnippetQuery,
variables() {
return {
ids: this.snippetGid,
@@ -21,11 +27,24 @@ export default {
},
data() {
return {
- snippetData: {},
+ snippet: {},
};
},
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.snippet.loading;
+ },
+ },
};
</script>
<template>
- <div class="js-snippet-view"></div>
+ <div class="js-snippet-view">
+ <gl-loading-icon
+ v-if="isLoading"
+ :label="__('Loading snippet')"
+ :size="2"
+ class="loading-animation prepend-top-20 append-bottom-20"
+ />
+ <snippet-header v-else :snippet="snippet" />
+ </div>
</template>
diff --git a/app/assets/javascripts/snippets/components/snippet_header.vue b/app/assets/javascripts/snippets/components/snippet_header.vue
new file mode 100644
index 00000000000..e8f1bfeaf43
--- /dev/null
+++ b/app/assets/javascripts/snippets/components/snippet_header.vue
@@ -0,0 +1,241 @@
+<script>
+import { __ } from '~/locale';
+import {
+ GlAvatar,
+ GlIcon,
+ GlSprintf,
+ GlButton,
+ GlModal,
+ GlAlert,
+ GlLoadingIcon,
+ GlDropdown,
+ GlDropdownItem,
+} from '@gitlab/ui';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+
+import DeleteSnippetMutation from '../mutations/deleteSnippet.mutation.graphql';
+import CanCreatePersonalSnippet from '../queries/userPermissions.query.graphql';
+import CanCreateProjectSnippet from '../queries/projectPermissions.query.graphql';
+
+export default {
+ components: {
+ GlAvatar,
+ GlIcon,
+ GlSprintf,
+ GlButton,
+ GlModal,
+ GlAlert,
+ GlLoadingIcon,
+ GlDropdown,
+ GlDropdownItem,
+ TimeAgoTooltip,
+ },
+ apollo: {
+ canCreateSnippet: {
+ query() {
+ return this.snippet.project ? CanCreateProjectSnippet : CanCreatePersonalSnippet;
+ },
+ variables() {
+ return {
+ fullPath: this.snippet.project ? this.snippet.project.fullPath : undefined,
+ };
+ },
+ update(data) {
+ return this.snippet.project
+ ? data.project.userPermissions.createSnippet
+ : data.currentUser.userPermissions.createSnippet;
+ },
+ },
+ },
+ props: {
+ snippet: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isDeleting: false,
+ errorMessage: '',
+ canCreateSnippet: false,
+ };
+ },
+ computed: {
+ personalSnippetActions() {
+ return [
+ {
+ condition: this.snippet.userPermissions.updateSnippet,
+ text: __('Edit'),
+ href: this.editLink,
+ click: undefined,
+ variant: 'outline-info',
+ cssClass: undefined,
+ },
+ {
+ condition: this.snippet.userPermissions.adminSnippet,
+ text: __('Delete'),
+ href: undefined,
+ click: this.showDeleteModal,
+ variant: 'outline-danger',
+ cssClass: 'btn-inverted btn-danger ml-2',
+ },
+ {
+ condition: this.canCreateSnippet,
+ text: __('New snippet'),
+ href: this.snippet.project
+ ? `${this.snippet.project.webUrl}/snippets/new`
+ : '/snippets/new',
+ click: undefined,
+ variant: 'outline-success',
+ cssClass: 'btn-inverted btn-success ml-2',
+ },
+ ];
+ },
+ editLink() {
+ return `${this.snippet.webUrl}/edit`;
+ },
+ visibility() {
+ return this.snippet.visibilityLevel;
+ },
+ snippetVisibilityLevelDescription() {
+ switch (this.visibility) {
+ case 'private':
+ return this.snippet.project !== null
+ ? __('The snippet is visible only to project members.')
+ : __('The snippet is visible only to me.');
+ case 'internal':
+ return __('The snippet is visible to any logged in user.');
+ default:
+ return __('The snippet can be accessed without any authentication.');
+ }
+ },
+ visibilityLevelIcon() {
+ switch (this.visibility) {
+ case 'private':
+ return 'lock';
+ case 'internal':
+ return 'shield';
+ default:
+ return 'earth';
+ }
+ },
+ },
+ methods: {
+ redirectToSnippets() {
+ window.location.pathname = 'dashboard/snippets';
+ },
+ closeDeleteModal() {
+ this.$refs.deleteModal.hide();
+ },
+ showDeleteModal() {
+ this.$refs.deleteModal.show();
+ },
+ deleteSnippet() {
+ this.isDeleting = true;
+ this.$apollo
+ .mutate({
+ mutation: DeleteSnippetMutation,
+ variables: { id: this.snippet.id },
+ })
+ .then(() => {
+ this.isDeleting = false;
+ this.errorMessage = undefined;
+ this.closeDeleteModal();
+ this.redirectToSnippets();
+ })
+ .catch(err => {
+ this.isDeleting = false;
+ this.errorMessage = err.message;
+ });
+ },
+ },
+};
+</script>
+<template>
+ <div class="detail-page-header">
+ <div class="detail-page-header-body">
+ <div
+ class="snippet-box qa-snippet-box has-tooltip d-flex align-items-center append-right-5 mb-1"
+ :title="snippetVisibilityLevelDescription"
+ data-container="body"
+ >
+ <span class="sr-only">
+ {{ s__(`VisibilityLevel|${visibility}`) }}
+ </span>
+ <gl-icon :name="visibilityLevelIcon" :size="14" />
+ </div>
+ <div class="creator">
+ <gl-sprintf message="Authored %{timeago} by %{author}">
+ <template #timeago>
+ <time-ago-tooltip
+ :time="snippet.createdAt"
+ tooltip-placement="bottom"
+ css-class="snippet_updated_ago"
+ />
+ </template>
+ <template #author>
+ <a :href="snippet.author.webUrl" class="d-inline">
+ <gl-avatar :size="24" :src="snippet.author.avatarUrl" />
+ <span class="bold">{{ snippet.author.name }}</span>
+ </a>
+ </template>
+ </gl-sprintf>
+ </div>
+ </div>
+
+ <div class="detail-page-header-actions">
+ <div class="d-none d-sm-block">
+ <template v-for="(action, index) in personalSnippetActions">
+ <gl-button
+ v-if="action.condition"
+ :key="index"
+ :variant="action.variant"
+ :class="action.cssClass"
+ :href="action.href || undefined"
+ @click="action.click ? action.click() : undefined"
+ >
+ {{ action.text }}
+ </gl-button>
+ </template>
+ </div>
+ <div class="d-block d-sm-none dropdown">
+ <gl-dropdown :text="__('Options')" class="w-100" toggle-class="text-center">
+ <gl-dropdown-item
+ v-for="(action, index) in personalSnippetActions"
+ :key="index"
+ :href="action.href || undefined"
+ @click="action.click ? action.click() : undefined"
+ >{{ action.text }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+ </div>
+ </div>
+
+ <gl-modal ref="deleteModal" modal-id="delete-modal" title="Example title">
+ <template #modal-title>{{ __('Delete snippet?') }}</template>
+
+ <gl-alert v-if="errorMessage" variant="danger" class="mb-2" @dismiss="errorMessage = ''">{{
+ errorMessage
+ }}</gl-alert>
+
+ <gl-sprintf message="Are you sure you want to delete %{name}?">
+ <template #name
+ ><strong>{{ snippet.title }}</strong></template
+ >
+ </gl-sprintf>
+
+ <template #modal-footer>
+ <gl-button @click="closeDeleteModal">{{ __('Cancel') }}</gl-button>
+ <gl-button
+ variant="danger"
+ :disabled="isDeleting"
+ data-qa-selector="delete_snippet_button"
+ @click="deleteSnippet"
+ >
+ <gl-loading-icon v-if="isDeleting" inline />
+ {{ __('Delete snippet') }}
+ </gl-button>
+ </template>
+ </gl-modal>
+ </div>
+</template>
diff --git a/app/assets/javascripts/snippets/fragments/author.fragment.graphql b/app/assets/javascripts/snippets/fragments/author.fragment.graphql
new file mode 100644
index 00000000000..2684bd0fa37
--- /dev/null
+++ b/app/assets/javascripts/snippets/fragments/author.fragment.graphql
@@ -0,0 +1,8 @@
+fragment Author on Snippet {
+ author {
+ name,
+ avatarUrl,
+ username,
+ webUrl
+ }
+} \ No newline at end of file
diff --git a/app/assets/javascripts/snippets/fragments/project.fragment.graphql b/app/assets/javascripts/snippets/fragments/project.fragment.graphql
new file mode 100644
index 00000000000..7d65789c67b
--- /dev/null
+++ b/app/assets/javascripts/snippets/fragments/project.fragment.graphql
@@ -0,0 +1,6 @@
+fragment Project on Snippet {
+ project {
+ fullPath
+ webUrl
+ }
+} \ No newline at end of file
diff --git a/app/assets/javascripts/snippets/fragments/snippetBase.fragment.graphql b/app/assets/javascripts/snippets/fragments/snippetBase.fragment.graphql
new file mode 100644
index 00000000000..57348a422ec
--- /dev/null
+++ b/app/assets/javascripts/snippets/fragments/snippetBase.fragment.graphql
@@ -0,0 +1,13 @@
+fragment SnippetBase on Snippet {
+ id
+ title
+ description
+ createdAt
+ updatedAt
+ visibilityLevel
+ webUrl
+ userPermissions {
+ adminSnippet
+ updateSnippet
+ }
+} \ No newline at end of file
diff --git a/app/assets/javascripts/snippets/mutations/deleteSnippet.mutation.graphql b/app/assets/javascripts/snippets/mutations/deleteSnippet.mutation.graphql
new file mode 100644
index 00000000000..0c829cbdee6
--- /dev/null
+++ b/app/assets/javascripts/snippets/mutations/deleteSnippet.mutation.graphql
@@ -0,0 +1,5 @@
+mutation DeleteSnippet($id: ID!) {
+ destroySnippet(input: {id: $id}) {
+ errors
+ }
+} \ No newline at end of file
diff --git a/app/assets/javascripts/snippets/queries/getSnippet.query.graphql b/app/assets/javascripts/snippets/queries/getSnippet.query.graphql
deleted file mode 100644
index 5a5f0d05c5b..00000000000
--- a/app/assets/javascripts/snippets/queries/getSnippet.query.graphql
+++ /dev/null
@@ -1,13 +0,0 @@
-query getSnippet($ids: [ID!]) {
- snippets(ids: $ids) {
- edges {
- node {
- title
- description
- createdAt
- updatedAt
- visibility
- }
- }
- }
-}
diff --git a/app/assets/javascripts/snippets/queries/projectPermissions.query.graphql b/app/assets/javascripts/snippets/queries/projectPermissions.query.graphql
new file mode 100644
index 00000000000..288bd0889bf
--- /dev/null
+++ b/app/assets/javascripts/snippets/queries/projectPermissions.query.graphql
@@ -0,0 +1,7 @@
+query CanCreateProjectSnippet($fullPath: ID!) {
+ project(fullPath: $fullPath) {
+ userPermissions {
+ createSnippet
+ }
+ }
+} \ No newline at end of file
diff --git a/app/assets/javascripts/snippets/queries/snippet.query.graphql b/app/assets/javascripts/snippets/queries/snippet.query.graphql
new file mode 100644
index 00000000000..1cb2c86c4d8
--- /dev/null
+++ b/app/assets/javascripts/snippets/queries/snippet.query.graphql
@@ -0,0 +1,15 @@
+#import '../fragments/snippetBase.fragment.graphql'
+#import '../fragments/project.fragment.graphql'
+#import '../fragments/author.fragment.graphql'
+
+query GetSnippetQuery($ids: [ID!]) {
+ snippets(ids: $ids) {
+ edges {
+ node {
+ ...SnippetBase
+ ...Project
+ ...Author
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/snippets/queries/userPermissions.query.graphql b/app/assets/javascripts/snippets/queries/userPermissions.query.graphql
new file mode 100644
index 00000000000..f5b97b3d0f0
--- /dev/null
+++ b/app/assets/javascripts/snippets/queries/userPermissions.query.graphql
@@ -0,0 +1,7 @@
+query CanCreatePersonalSnippet {
+ currentUser {
+ userPermissions {
+ createSnippet
+ }
+ }
+} \ No newline at end of file
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue
index b874bedab36..bf3c3666300 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue
@@ -79,10 +79,10 @@ export default {
return this.projectPath.indexOf('/') === 0 ? '' : `${gon.relative_url_root}/`;
},
fullOldPath() {
- return `${this.basePath}${this.projectPath}/raw/${this.oldSha}/${this.oldPath}`;
+ return `${this.basePath}${this.projectPath}/-/raw/${this.oldSha}/${this.oldPath}`;
},
fullNewPath() {
- return `${this.basePath}${this.projectPath}/raw/${this.newSha}/${this.newPath}`;
+ return `${this.basePath}${this.projectPath}/-/raw/${this.newSha}/${this.newPath}`;
},
},
};
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index 7d25b6927f9..1f4bba5fc33 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -40,12 +40,12 @@
// Classes using mixins coming from @gitlab-ui
// can be removed once https://gitlab.com/gitlab-org/gitlab/merge_requests/19021 has been merged
-.gl-bg-blue-500 { @include gl-bg-blue-500; }
.gl-bg-red-100 { @include gl-bg-red-100; }
.gl-bg-orange-100 { @include gl-bg-orange-100; }
.gl-bg-gray-100 { @include gl-bg-gray-100; }
.gl-bg-green-100 { @include gl-bg-green-100;}
+.gl-text-blue-500 { @include gl-text-blue-500; }
.gl-text-gray-900 { @include gl-text-gray-900; }
.gl-text-red-700 { @include gl-text-red-700; }
.gl-text-orange-700 { @include gl-text-orange-700; }
diff --git a/app/helpers/submodule_helper.rb b/app/helpers/submodule_helper.rb
index 4b83988e8bb..e5400652458 100644
--- a/app/helpers/submodule_helper.rb
+++ b/app/helpers/submodule_helper.rb
@@ -43,6 +43,8 @@ module SubmoduleHelper
elsif github_dot_com_url?(url)
standard_links('github.com', namespace, project, submodule_item_id)
elsif gitlab_dot_com_url?(url)
+ # This need to be replaced with /-/tree routing once one is landed on
+ # GitLab.com. Issue https://gitlab.com/gitlab-org/gitlab/issues/42764
standard_links('gitlab.com', namespace, project, submodule_item_id)
else
[sanitize_submodule_url(url), nil]
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index af1919eeb40..0b50b8b1130 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -38,13 +38,13 @@ module TreeHelper
# many paths, as with a repository tree that has thousands of items.
def fast_project_blob_path(project, blob_path)
ActionDispatch::Journey::Router::Utils.escape_path(
- File.join(relative_url_root, project.path_with_namespace, 'blob', blob_path)
+ File.join(relative_url_root, project.path_with_namespace, '-', 'blob', blob_path)
)
end
def fast_project_tree_path(project, tree_path)
ActionDispatch::Journey::Router::Utils.escape_path(
- File.join(relative_url_root, project.path_with_namespace, 'tree', tree_path)
+ File.join(relative_url_root, project.path_with_namespace, '-', 'tree', tree_path)
)
end
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index 89ffb72a22f..387503bee54 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Knative < ApplicationRecord
- VERSION = '0.7.0'
+ VERSION = '0.9.0'
REPOSITORY = 'https://storage.googleapis.com/triggermesh-charts'
METRICS_CONFIG = 'https://storage.googleapis.com/triggermesh-charts/istio-metrics.yaml'
FETCH_IP_ADDRESS_DELAY = 30.seconds
diff --git a/app/views/admin/users/_access_levels.html.haml b/app/views/admin/users/_access_levels.html.haml
index bb1e22cc610..e3ab2e4f9bd 100644
--- a/app/views/admin/users/_access_levels.html.haml
+++ b/app/views/admin/users/_access_levels.html.haml
@@ -43,7 +43,7 @@
= f.check_box :external do
External
%p.light
- External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects or groups.
+ External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects, groups, or personal snippets.
%row.hidden#warning_external_automatically_set.hidden
.badge.badge-warning.text-white
= _('Automatically marked as default internal user')
diff --git a/app/views/dashboard/_snippets_head.html.haml b/app/views/dashboard/_snippets_head.html.haml
index 34aca40d0d1..4958cdc3745 100644
--- a/app/views/dashboard/_snippets_head.html.haml
+++ b/app/views/dashboard/_snippets_head.html.haml
@@ -3,7 +3,8 @@
- if current_user && current_user.snippets.any? || @snippets.any?
.page-title-controls
- = link_to _("New snippet"), new_snippet_path, class: "btn btn-success", title: _("New snippet")
+ - if can?(current_user, :create_personal_snippet)
+ = link_to _("New snippet"), new_snippet_path, class: "btn btn-success", title: _("New snippet")
.top-area
%ul.nav-links.nav.nav-tabs
diff --git a/app/views/dashboard/snippets/index.html.haml b/app/views/dashboard/snippets/index.html.haml
index 2caa8e0cac4..44a9270971a 100644
--- a/app/views/dashboard/snippets/index.html.haml
+++ b/app/views/dashboard/snippets/index.html.haml
@@ -1,6 +1,7 @@
- @hide_top_links = true
- page_title "Snippets"
- header_title "Snippets", dashboard_snippets_path
+- button_path = new_snippet_path if can?(current_user, :create_personal_snippet)
= render 'dashboard/snippets_head'
- if current_user.snippets.exists?
@@ -9,4 +10,4 @@
- if current_user.snippets.exists?
= render partial: 'shared/snippets/list', locals: { link_project: true }
- else
- = render 'shared/empty_states/snippets', button_path: new_snippet_path
+ = render 'shared/empty_states/snippets', button_path: button_path
diff --git a/app/views/profiles/accounts/_providers.html.haml b/app/views/profiles/accounts/_providers.html.haml
index dc17de1b220..a87191d0fa4 100644
--- a/app/views/profiles/accounts/_providers.html.haml
+++ b/app/views/profiles/accounts/_providers.html.haml
@@ -16,6 +16,6 @@
%a.provider-btn
= s_('Profiles|Active')
- elsif link_allowed
- = link_to omniauth_authorize_path(:user, provider), method: :post, class: 'provider-btn gl-bg-blue-500' do
+ = link_to omniauth_authorize_path(:user, provider), method: :post, class: 'provider-btn gl-text-blue-500' do
= s_('Profiles|Connect')
= render_if_exists 'profiles/accounts/group_saml_unlink_buttons', group_saml_identities: group_saml_identities
diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml
index 7682d01a5a1..0ce18d83d57 100644
--- a/app/views/projects/snippets/index.html.haml
+++ b/app/views/projects/snippets/index.html.haml
@@ -8,8 +8,7 @@
- if can?(current_user, :create_project_snippet, @project)
.nav-controls
- - if can?(current_user, :create_project_snippet, @project)
- = link_to _("New snippet"), new_project_snippet_path(@project), class: "btn btn-success", title: _("New snippet")
+ = link_to _("New snippet"), new_project_snippet_path(@project), class: "btn btn-success", title: _("New snippet")
= render 'shared/snippets/list'
- else
diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml
index f495b4eaf30..768e4422206 100644
--- a/app/views/projects/snippets/show.html.haml
+++ b/app/views/projects/snippets/show.html.haml
@@ -3,13 +3,16 @@
- breadcrumb_title @snippet.to_reference
- page_title "#{@snippet.title} (#{@snippet.to_reference})", _("Snippets")
-= render 'shared/snippets/header'
+- if Feature.enabled?(:snippets_vue)
+ #js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id} }
+- else
+ = render 'shared/snippets/header'
-.project-snippets
- %article.file-holder.snippet-file-content
- = render 'shared/snippets/blob'
+ .project-snippets
+ %article.file-holder.snippet-file-content
+ = render 'shared/snippets/blob'
- .row-content-block.top-block.content-component-block
- = render 'award_emoji/awards_block', awardable: @snippet, inline: true
+ .row-content-block.top-block.content-component-block
+ = render 'award_emoji/awards_block', awardable: @snippet, inline: true
- #notes.limited-width-notes= render "shared/notes/notes_with_form", :autocomplete => true
+ #notes.limited-width-notes= render "shared/notes/notes_with_form", :autocomplete => true
diff --git a/app/views/shared/empty_states/_snippets.html.haml b/app/views/shared/empty_states/_snippets.html.haml
index a1a16b9d067..889a470d6ec 100644
--- a/app/views/shared/empty_states/_snippets.html.haml
+++ b/app/views/shared/empty_states/_snippets.html.haml
@@ -11,7 +11,8 @@
%p
= s_('SnippetsEmptyState|They can be either public or private.')
.text-center
- = link_to s_('SnippetsEmptyState|New snippet'), button_path, class: 'btn btn-success', title: s_('SnippetsEmptyState|New snippet'), id: 'new_snippet_link'
+ - if button_path
+ = link_to s_('SnippetsEmptyState|New snippet'), button_path, class: 'btn btn-success', title: s_('SnippetsEmptyState|New snippet'), id: 'new_snippet_link'
- unless current_page?(dashboard_snippets_path)
= link_to s_('SnippetsEmptyState|Explore public snippets'), explore_snippets_path, class: 'btn btn-default', title: s_('SnippetsEmptyState|Explore public snippets')
- else
diff --git a/app/views/snippets/_snippets.html.haml b/app/views/snippets/_snippets.html.haml
index dab247da251..69b19c0def9 100644
--- a/app/views/snippets/_snippets.html.haml
+++ b/app/views/snippets/_snippets.html.haml
@@ -3,7 +3,7 @@
- current_user_empty_message_header = s_('UserProfile|You haven\'t created any snippets.')
- current_user_empty_message_description = s_('UserProfile|Snippets in GitLab can either be private, internal, or public.')
- primary_button_label = _('New snippet')
-- primary_button_link = new_snippet_path
+- primary_button_link = new_snippet_path if can?(current_user, :create_personal_snippet)
- visitor_empty_message = s_('UserProfile|No snippets found.')
.snippets-list-holder
diff --git a/babel.config.js b/babel.config.js
index 79c401ed975..91c58cf46bf 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -21,6 +21,7 @@ const plugins = [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-json-strings',
'@babel/plugin-proposal-private-methods',
+ '@babel/plugin-proposal-optional-chaining',
];
// add code coverage tooling if necessary
diff --git a/changelogs/unreleased/39498-part-1.yml b/changelogs/unreleased/39498-part-1.yml
new file mode 100644
index 00000000000..fb410993424
--- /dev/null
+++ b/changelogs/unreleased/39498-part-1.yml
@@ -0,0 +1,5 @@
+---
+title: "!21542 Part 1: Add new utils for Web IDE store"
+merge_request: 21673
+author:
+type: fixed
diff --git a/changelogs/unreleased/ap-14330-external-personal-snippets.yml b/changelogs/unreleased/ap-14330-external-personal-snippets.yml
new file mode 100644
index 00000000000..86cd3f0ab75
--- /dev/null
+++ b/changelogs/unreleased/ap-14330-external-personal-snippets.yml
@@ -0,0 +1,5 @@
+---
+title: Match external user new snippet button visibility to permissions
+merge_request: 21718
+author:
+type: fixed
diff --git a/changelogs/unreleased/dz-scope-repository-routes.yml b/changelogs/unreleased/dz-scope-repository-routes.yml
new file mode 100644
index 00000000000..302227dde57
--- /dev/null
+++ b/changelogs/unreleased/dz-scope-repository-routes.yml
@@ -0,0 +1,5 @@
+---
+title: Move repository routes under - scope
+merge_request: 20455
+author:
+type: deprecated
diff --git a/changelogs/unreleased/knative-0-9-update.yml b/changelogs/unreleased/knative-0-9-update.yml
new file mode 100644
index 00000000000..d25e9e90efe
--- /dev/null
+++ b/changelogs/unreleased/knative-0-9-update.yml
@@ -0,0 +1,5 @@
+---
+title: Update Knative to 0.9.0
+merge_request: 21361
+author: cab105
+type: added
diff --git a/changelogs/unreleased/service-desk-name.yml b/changelogs/unreleased/service-desk-name.yml
new file mode 100644
index 00000000000..f3d32e6c6cd
--- /dev/null
+++ b/changelogs/unreleased/service-desk-name.yml
@@ -0,0 +1,5 @@
+---
+title: Added migration which adds service desk username column
+merge_request: 21733
+author:
+type: added
diff --git a/config/prometheus/common_metrics.yml b/config/prometheus/common_metrics.yml
index 795243fab49..314ee44ed71 100644
--- a/config/prometheus/common_metrics.yml
+++ b/config/prometheus/common_metrics.yml
@@ -209,6 +209,6 @@ panel_groups:
weight: 1
metrics:
- id: system_metrics_knative_function_invocation_count
- query_range: 'sum(ceil(rate(istio_requests_total{destination_service_namespace="%{kube_namespace}", destination_app=~"%{function_name}.*"}[1m])*60))'
+ query_range: 'sum(ceil(rate(istio_requests_total{destination_service_namespace="%{kube_namespace}", destination_service=~"%{function_name}.*"}[1m])*60))'
label: invocations / minute
unit: requests
diff --git a/config/routes/project.rb b/config/routes/project.rb
index d2abc73f7cc..6c2dcafd1ab 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -554,7 +554,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
:forks, :group_links, :import, :avatar, :mirror,
:cycle_analytics, :mattermost, :variables, :triggers,
:environments, :protected_environments, :error_tracking,
- :serverless, :clusters, :audit_events, :wikis, :merge_requests)
+ :serverless, :clusters, :audit_events, :wikis, :merge_requests,
+ :blob, :tree, :raw, :blame, :commits, :create_dir, :find_file, :files)
end
# rubocop: disable Cop/PutProjectRoutesUnderScope
diff --git a/config/routes/repository.rb b/config/routes/repository.rb
index 4815575ba9f..e59168c6af4 100644
--- a/config/routes/repository.rb
+++ b/config/routes/repository.rb
@@ -65,7 +65,7 @@ scope format: false do
resources :protected_tags, only: [:index, :show, :create, :update, :destroy]
end
- scope constraints: { id: /[^\0]+/ } do
+ scope path: '-', constraints: { id: /[^\0]+/ } do
scope controller: :blob do
get '/new/*id', action: :new, as: :new_blob
post '/create/*id', action: :create, as: :create_blob
diff --git a/db/migrate/20191213104838_add_service_desk_username.rb b/db/migrate/20191213104838_add_service_desk_username.rb
new file mode 100644
index 00000000000..945bdb67fa1
--- /dev/null
+++ b/db/migrate/20191213104838_add_service_desk_username.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddServiceDeskUsername < ActiveRecord::Migration[5.2]
+ DOWNTIME = false
+
+ def change
+ add_column :service_desk_settings, :outgoing_name, :string, limit: 255
+ end
+end
diff --git a/db/post_migrate/20191209215316_knative_0_9_prometheus_update.rb b/db/post_migrate/20191209215316_knative_0_9_prometheus_update.rb
new file mode 100644
index 00000000000..52127f71cd0
--- /dev/null
+++ b/db/post_migrate/20191209215316_knative_0_9_prometheus_update.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class Knative09PrometheusUpdate < ActiveRecord::Migration[5.2]
+ DOWNTIME = false
+
+ def up
+ ::Gitlab::DatabaseImporters::CommonMetrics::Importer.new.execute
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index d3e9f66c388..67d305a3505 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2019_12_16_183532) do
+ActiveRecord::Schema.define(version: 2019_12_17_160632) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm"
@@ -3663,6 +3663,7 @@ ActiveRecord::Schema.define(version: 2019_12_16_183532) do
create_table "service_desk_settings", primary_key: "project_id", id: :bigint, default: nil, force: :cascade do |t|
t.string "issue_template_key", limit: 255
+ t.string "outgoing_name", limit: 255
end
create_table "services", id: :serial, force: :cascade do |t|
diff --git a/doc/development/background_migrations.md b/doc/development/background_migrations.md
index 5e16f83b63c..8a1db615022 100644
--- a/doc/development/background_migrations.md
+++ b/doc/development/background_migrations.md
@@ -10,11 +10,6 @@ migrations automatically reschedule themselves for a later point in time.
## When To Use Background Migrations
-> **Note:**
-> When adding background migrations _you must_ make sure they are announced in the
-> monthly release post along with an estimate of how long it will take to complete
-> the migrations.
-
In the vast majority of cases you will want to use a regular Rails migration
instead. Background migrations should be used when migrating _data_ in
tables that have so many rows this process would take hours when performed in a
@@ -34,6 +29,11 @@ Some examples where background migrations can be useful:
- Populating one column based on JSON stored in another column.
- Migrating data that depends on the output of external services (e.g. an API).
+> **Note:**
+> If the background migration is part of an important upgrade, make sure it's announced
+> in the release post. Discuss with your Project Manager if you're not sure the migration falls
+> into this category.
+
## Isolation
Background migrations must be isolated and can not use application code (e.g.
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index 40df5f3265a..40b9fdef76e 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -39,43 +39,31 @@ To distinguish queries from mutations and fragments, the following naming conven
- `addUser.mutation.graphql` for mutations;
- `basicUser.fragment.graphql` for fragments.
-GraphQL:
-
-- Queries are stored in `(ee/)app/assets/javascripts/` under the feature. For example, `respository/queries`. Frontend components can use these stored queries.
-- Mutations are stored in
- `(ee/)app/assets/javascripts/<subfolders>/<name of mutation>.mutation.graphql`.
-
### Fragments
-Fragments are a way to make your complex GraphQL queries more readable and re-usable.
-They can be stored in a separate file and imported.
+Fragments are a way to make your complex GraphQL queries more readable and re-usable. Here is an example of GraphQL fragment:
-For example, a fragment that references another fragment:
-
-```ruby
-fragment BaseEpic on Epic {
+```javascript
+fragment DesignListItem on Design {
id
- iid
- title
- webPath
- relativePosition
- userPermissions {
- adminEpic
- createEpic
- }
+ image
+ event
+ filename
+ notesCount
}
+```
-fragment EpicNode on Epic {
- ...BaseEpic
- state
- reference(full: true)
- relationPath
- createdAt
- closedAt
- hasChildren
- hasIssues
- group {
- fullPath
+Fragments can be stored in separate files, imported and used in queries, mutations or other fragments.
+
+```javascript
+#import "./designList.fragment.graphql"
+#import "./diffRefs.fragment.graphql"
+
+fragment DesignItem on Design {
+ ...DesignListItem
+ fullPath
+ diffRefs {
+ ...DesignDiffRefs
}
}
```
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index ed58c23a22f..9cbf4fd6192 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -253,7 +253,7 @@ project and should only have access to that project.
External users:
-- Cannot create groups or projects.
+- Cannot create groups, projects, or personal snippets.
- Can only access projects to which they are explicitly granted access,
thus hiding all other internal or private ones from them (like being
logged out).
diff --git a/lib/banzai/filter/relative_link_filter.rb b/lib/banzai/filter/relative_link_filter.rb
index 583b0081319..2581a179c79 100644
--- a/lib/banzai/filter/relative_link_filter.rb
+++ b/lib/banzai/filter/relative_link_filter.rb
@@ -152,11 +152,18 @@ module Banzai
def rebuild_relative_uri(uri)
file_path = nested_file_path_if_exists(uri)
+ resource_type = uri_type(file_path)
+
+ # Repository routes are under /-/ scope now.
+ # Since we craft a path without using route helpers we must
+ # ensure - is added here.
+ prefix = '-' if %w(tree blob raw commits).include?(resource_type.to_s)
uri.path = [
relative_url_root,
project.full_path,
- uri_type(file_path),
+ prefix,
+ resource_type,
Addressable::URI.escape(ref).gsub('#', '%23'),
Addressable::URI.escape(file_path)
].compact.join('/').squeeze('/').chomp('/')
diff --git a/lib/gitlab/dependency_linker/godeps_json_linker.rb b/lib/gitlab/dependency_linker/godeps_json_linker.rb
index d24c137793e..9166e9091ac 100644
--- a/lib/gitlab/dependency_linker/godeps_json_linker.rb
+++ b/lib/gitlab/dependency_linker/godeps_json_linker.rb
@@ -12,10 +12,12 @@ module Gitlab
def link_dependencies
link_json('ImportPath') do |path|
case path
+ when %r{\A(?<repo>github\.com/#{REPO_REGEX})/(?<path>.+)\z}
+ "https://#{$~[:repo]}/tree/master/#{$~[:path]}"
when %r{\A(?<repo>gitlab\.com/#{NESTED_REPO_REGEX})\.git/(?<path>.+)\z},
- %r{\A(?<repo>git(lab|hub)\.com/#{REPO_REGEX})/(?<path>.+)\z}
+ %r{\A(?<repo>gitlab\.com/#{REPO_REGEX})/(?<path>.+)\z}
- "https://#{$~[:repo]}/tree/master/#{$~[:path]}"
+ "https://#{$~[:repo]}/-/tree/master/#{$~[:path]}"
when /\Agolang\.org/
"https://godoc.org/#{path}"
else
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index bf92de73b48..ba1ccd77604 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -220,6 +220,8 @@ excluded_attributes:
- :encrypted_token
- :encrypted_token_iv
- :enabled
+ service_desk_setting:
+ - :outgoing_name
methods:
notes:
diff --git a/lib/gitlab/middleware/go.rb b/lib/gitlab/middleware/go.rb
index f207d91235f..53508938c49 100644
--- a/lib/gitlab/middleware/go.rb
+++ b/lib/gitlab/middleware/go.rb
@@ -60,7 +60,7 @@ module Gitlab
end
meta_import_tag = tag :meta, name: 'go-import', content: "#{import_prefix} git #{repository_url}"
- meta_source_tag = tag :meta, name: 'go-source', content: "#{import_prefix} #{project_url} #{project_url}/tree/#{branch}{/dir} #{project_url}/blob/#{branch}{/dir}/{file}#L{line}"
+ meta_source_tag = tag :meta, name: 'go-source', content: "#{import_prefix} #{project_url} #{project_url}/-/tree/#{branch}{/dir} #{project_url}/-/blob/#{branch}{/dir}/{file}#L{line}"
head_tag = content_tag :head, meta_import_tag + meta_source_tag
html_tag = content_tag :html, head_tag + body_tag
[html_tag, 200]
diff --git a/lib/quality/test_level.rb b/lib/quality/test_level.rb
index 90a8096cc2b..84470a73b1b 100644
--- a/lib/quality/test_level.rb
+++ b/lib/quality/test_level.rb
@@ -5,6 +5,10 @@ module Quality
UnknownTestLevelError = Class.new(StandardError)
TEST_LEVEL_FOLDERS = {
+ migration: %w[
+ migrations
+ lib/gitlab/background_migration
+ ],
unit: %w[
bin
config
@@ -19,7 +23,6 @@ module Quality
initializers
javascripts
lib
- migrations
models
policies
presenters
@@ -36,10 +39,6 @@ module Quality
workers
elastic_integration
],
- migration: %w[
- migrations
- lib/gitlab/background_migration
- ],
integration: %w[
controllers
mailers
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 6301a72f48a..be2ba9d22fb 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -4994,12 +4994,18 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not fetch projects"
+msgstr ""
+
msgid "Could not remove the trigger."
msgstr ""
@@ -5644,6 +5650,12 @@ msgstr ""
msgid "Delete list"
msgstr ""
+msgid "Delete snippet"
+msgstr ""
+
+msgid "Delete snippet?"
+msgstr ""
+
msgid "Delete source branch"
msgstr ""
@@ -10001,6 +10013,9 @@ msgstr ""
msgid "IssuesAnalytics|Total:"
msgstr ""
+msgid "Issue|Title"
+msgstr ""
+
msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
msgstr ""
@@ -10709,6 +10724,9 @@ msgstr ""
msgid "Loading issues"
msgstr ""
+msgid "Loading snippet"
+msgstr ""
+
msgid "Loading the GitLab IDE..."
msgstr ""
@@ -11724,6 +11742,9 @@ msgstr ""
msgid "New issue"
msgstr ""
+msgid "New issue title"
+msgstr ""
+
msgid "New label"
msgstr ""
diff --git a/package.json b/package.json
index aa11e35d3e6..098cdd534a0 100644
--- a/package.json
+++ b/package.json
@@ -34,6 +34,7 @@
"@babel/core": "^7.6.2",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-proposal-json-strings": "^7.2.0",
+ "@babel/plugin-proposal-optional-chaining": "^7.7.5",
"@babel/plugin-proposal-private-methods": "^7.6.0",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-syntax-import-meta": "^7.2.0",
diff --git a/scripts/review_apps/base-config.yaml b/scripts/review_apps/base-config.yaml
index e8a21451e02..999f730efc5 100644
--- a/scripts/review_apps/base-config.yaml
+++ b/scripts/review_apps/base-config.yaml
@@ -44,7 +44,7 @@ gitlab:
memory: 37.5M
maxReplicas: 3
hpa:
- targetAverageValue: 130m
+ targetAverageValue: 500m
deployment:
livenessProbe:
timeoutSeconds: 5
@@ -56,6 +56,8 @@ gitlab:
limits:
cpu: 975m
memory: 1450M
+ hpa:
+ targetAverageValue: 650m
task-runner:
resources:
requests:
diff --git a/spec/controllers/concerns/metrics_dashboard_spec.rb b/spec/controllers/concerns/metrics_dashboard_spec.rb
index ff2b6fbb8ec..662fb386208 100644
--- a/spec/controllers/concerns/metrics_dashboard_spec.rb
+++ b/spec/controllers/concerns/metrics_dashboard_spec.rb
@@ -72,7 +72,7 @@ describe MetricsDashboard do
it 'includes project_blob_path only for project dashboards' do
expect(system_dashboard['project_blob_path']).to be_nil
- expect(project_dashboard['project_blob_path']).to eq("/#{project.namespace.path}/#{project.name}/blob/master/.gitlab/dashboards/test.yml")
+ expect(project_dashboard['project_blob_path']).to eq("/#{project.namespace.path}/#{project.name}/-/blob/master/.gitlab/dashboards/test.yml")
end
describe 'project permissions' do
diff --git a/spec/controllers/projects/blame_controller_spec.rb b/spec/controllers/projects/blame_controller_spec.rb
index dd7c0f45dc2..ac8394e3cd4 100644
--- a/spec/controllers/projects/blame_controller_spec.rb
+++ b/spec/controllers/projects/blame_controller_spec.rb
@@ -36,7 +36,7 @@ describe Projects::BlameController do
it 'redirects' do
expect(subject)
- .to redirect_to("/#{project.full_path}/tree/master")
+ .to redirect_to("/#{project.full_path}/-/tree/master")
end
end
diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb
index 78599935910..aa1dcdd9f1d 100644
--- a/spec/controllers/projects/blob_controller_spec.rb
+++ b/spec/controllers/projects/blob_controller_spec.rb
@@ -33,7 +33,7 @@ describe Projects::BlobController do
it 'redirects' do
expect(subject)
- .to redirect_to("/#{project.full_path}/tree/master")
+ .to redirect_to("/#{project.full_path}/-/tree/master")
end
end
@@ -115,7 +115,7 @@ describe Projects::BlobController do
it 'redirects' do
expect(subject)
- .to redirect_to("/#{project.full_path}/tree/markdown/doc")
+ .to redirect_to("/#{project.full_path}/-/tree/markdown/doc")
end
end
end
diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb
index 4f8ab6a5def..bf7ef9dab0c 100644
--- a/spec/controllers/projects/branches_controller_spec.rb
+++ b/spec/controllers/projects/branches_controller_spec.rb
@@ -37,7 +37,7 @@ describe Projects::BranchesController do
let(:ref) { "master" }
it 'redirects' do
expect(subject)
- .to redirect_to("/#{project.full_path}/tree/merge_branch")
+ .to redirect_to("/#{project.full_path}/-/tree/merge_branch")
end
end
@@ -46,7 +46,7 @@ describe Projects::BranchesController do
let(:ref) { "master" }
it 'redirects' do
expect(subject)
- .to redirect_to("/#{project.full_path}/tree/alert('merge');")
+ .to redirect_to("/#{project.full_path}/-/tree/alert('merge');")
end
end
@@ -88,7 +88,7 @@ describe Projects::BranchesController do
}
expect(subject)
- .to redirect_to("/#{project.full_path}/tree/1-feature-branch")
+ .to redirect_to("/#{project.full_path}/-/tree/1-feature-branch")
end
it 'posts a system note' do
diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb
index bdf1c1a84d3..391b7ad1648 100644
--- a/spec/controllers/projects/raw_controller_spec.rb
+++ b/spec/controllers/projects/raw_controller_spec.rb
@@ -69,7 +69,7 @@ describe Projects::RawController do
env: :raw_blob_request_limit,
remote_ip: '0.0.0.0',
request_method: 'GET',
- path: "/#{project.full_path}/raw/#{file_path}"
+ path: "/#{project.full_path}/-/raw/#{file_path}"
}
expect(Gitlab::AuthLogger).to receive(:error).with(attributes).once
diff --git a/spec/controllers/projects/serverless/functions_controller_spec.rb b/spec/controllers/projects/serverless/functions_controller_spec.rb
index 73fb0fad646..33d66f4ac5a 100644
--- a/spec/controllers/projects/serverless/functions_controller_spec.rb
+++ b/spec/controllers/projects/serverless/functions_controller_spec.rb
@@ -149,6 +149,14 @@ describe Projects::Serverless::FunctionsController do
include_examples 'GET #show with valid data'
end
+
+ context 'on Knative 0.9.0' do
+ before do
+ prepare_knative_stubs(knative_09_service(knative_stub_options))
+ end
+
+ include_examples 'GET #show with valid data'
+ end
end
end
@@ -210,6 +218,14 @@ describe Projects::Serverless::FunctionsController do
include_examples 'GET #index with data'
end
+
+ context 'on Knative 0.9.0' do
+ before do
+ prepare_knative_stubs(knative_09_service(knative_stub_options))
+ end
+
+ include_examples 'GET #index with data'
+ end
end
def prepare_knative_stubs(knative_service)
diff --git a/spec/controllers/projects/tree_controller_spec.rb b/spec/controllers/projects/tree_controller_spec.rb
index c0c11db5dd6..f89881af5e2 100644
--- a/spec/controllers/projects/tree_controller_spec.rb
+++ b/spec/controllers/projects/tree_controller_spec.rb
@@ -45,7 +45,7 @@ describe Projects::TreeController do
it 'redirects' do
expect(subject)
- .to redirect_to("/#{project.full_path}/tree/master")
+ .to redirect_to("/#{project.full_path}/-/tree/master")
end
end
@@ -60,7 +60,7 @@ describe Projects::TreeController do
it 'redirects' do
expect(subject)
- .to redirect_to("/#{project.full_path}/tree/empty-branch")
+ .to redirect_to("/#{project.full_path}/-/tree/empty-branch")
end
end
@@ -125,7 +125,7 @@ describe Projects::TreeController do
let(:id) { 'master/README.md' }
it 'redirects' do
- redirect_url = "/#{project.full_path}/blob/master/README.md"
+ redirect_url = "/#{project.full_path}/-/blob/master/README.md"
expect(subject)
.to redirect_to(redirect_url)
end
@@ -153,7 +153,7 @@ describe Projects::TreeController do
it 'redirects to the new directory' do
expect(subject)
- .to redirect_to("/#{project.full_path}/tree/#{branch_name}/#{path}")
+ .to redirect_to("/#{project.full_path}/-/tree/#{branch_name}/#{path}")
expect(flash[:notice]).to eq('The directory has been successfully created.')
end
end
@@ -164,7 +164,7 @@ describe Projects::TreeController do
it 'does not allow overwriting of existing files' do
expect(subject)
- .to redirect_to("/#{project.full_path}/tree/master")
+ .to redirect_to("/#{project.full_path}/-/tree/master")
expect(flash[:alert]).to eq('A file with this name already exists')
end
end
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 5259c612bbd..a1dff0881b6 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -943,7 +943,7 @@ describe ProjectsController do
end
it 'renders JSON body with image links expanded' do
- expanded_path = "/#{project_with_repo.full_path}/raw/master/files/images/logo-white.png"
+ expanded_path = "/#{project_with_repo.full_path}/-/raw/master/files/images/logo-white.png"
post :preview_markdown, params: preview_markdown_params
diff --git a/spec/features/dashboard/snippets_spec.rb b/spec/features/dashboard/snippets_spec.rb
index 4fb01995cb0..ff3eb58931d 100644
--- a/spec/features/dashboard/snippets_spec.rb
+++ b/spec/features/dashboard/snippets_spec.rb
@@ -6,6 +6,7 @@ describe 'Dashboard snippets' do
context 'when the project has snippets' do
let(:project) { create(:project, :public) }
let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.owner, project: project) }
+
before do
allow(Snippet).to receive(:default_per_page).and_return(1)
sign_in(project.owner)
@@ -13,10 +14,16 @@ describe 'Dashboard snippets' do
end
it_behaves_like 'paginated snippets'
+
+ it 'shows new snippet button in header' do
+ parent_element = page.find('.page-title-controls')
+ expect(parent_element).to have_link('New snippet')
+ end
end
context 'when there are no project snippets', :js do
let(:project) { create(:project, :public) }
+
before do
sign_in(project.owner)
visit dashboard_snippets_path
@@ -28,6 +35,11 @@ describe 'Dashboard snippets' do
expect(element).to have_content("Snippets are small pieces of code or notes that you want to keep.")
expect(element.find('.svg-content img')['src']).to have_content('illustrations/snippets_empty')
end
+
+ it 'shows new snippet button in main content area' do
+ parent_element = page.find('.row.empty-state')
+ expect(parent_element).to have_link('New snippet')
+ end
end
context 'filtering by visibility' do
@@ -76,4 +88,26 @@ describe 'Dashboard snippets' do
expect(page).to have_content(snippets[0].title)
end
end
+
+ context 'as an external user' do
+ let(:user) { create(:user, :external) }
+ before do
+ sign_in(user)
+ visit dashboard_snippets_path
+ end
+
+ context 'without snippets' do
+ it 'hides new snippet button' do
+ expect(page).not_to have_link('New snippet')
+ end
+ end
+
+ context 'with snippets' do
+ let!(:snippets) { create(:personal_snippet, author: user) }
+
+ it 'hides new snippet button' do
+ expect(page).not_to have_link('New snippet')
+ end
+ end
+ end
end
diff --git a/spec/features/discussion_comments/snippets_spec.rb b/spec/features/discussion_comments/snippets_spec.rb
index 082f35050c0..0dccb7f5bb3 100644
--- a/spec/features/discussion_comments/snippets_spec.rb
+++ b/spec/features/discussion_comments/snippets_spec.rb
@@ -8,6 +8,7 @@ describe 'Thread Comments Snippet', :js do
let(:snippet) { create(:project_snippet, :private, project: project, author: user) }
before do
+ stub_feature_flags(snippets_vue: false)
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/issues/move_spec.rb b/spec/features/issues/move_spec.rb
index 1122504248f..7126707affd 100644
--- a/spec/features/issues/move_spec.rb
+++ b/spec/features/issues/move_spec.rb
@@ -70,6 +70,7 @@ describe 'issue move to another project' do
context 'user does not have permission to move the issue to a project', :js do
let!(:private_project) { create(:project, :private) }
let(:another_project) { create(:project) }
+
before do
another_project.add_guest(user)
end
diff --git a/spec/features/issues/user_views_issues_spec.rb b/spec/features/issues/user_views_issues_spec.rb
index b986991f38f..8f174472f49 100644
--- a/spec/features/issues/user_views_issues_spec.rb
+++ b/spec/features/issues/user_views_issues_spec.rb
@@ -6,6 +6,7 @@ describe "User views issues" do
let!(:closed_issue) { create(:closed_issue, project: project) }
let!(:open_issue1) { create(:issue, project: project) }
let!(:open_issue2) { create(:issue, project: project) }
+
set(:user) { create(:user) }
shared_examples "opens issue from list" do
diff --git a/spec/features/merge_requests/user_sorts_merge_requests_spec.rb b/spec/features/merge_requests/user_sorts_merge_requests_spec.rb
index ca3e24d7036..3c217786d43 100644
--- a/spec/features/merge_requests/user_sorts_merge_requests_spec.rb
+++ b/spec/features/merge_requests/user_sorts_merge_requests_spec.rb
@@ -9,6 +9,7 @@ describe 'User sorts merge requests' do
let!(:merge_request2) do
create(:merge_request_with_diffs, source_project: project, target_project: project, source_branch: 'merge-test')
end
+
set(:user) { create(:user) }
set(:group) { create(:group) }
set(:group_member) { create(:group_member, :maintainer, user: user, group: group) }
diff --git a/spec/features/merge_requests/user_views_open_merge_requests_spec.rb b/spec/features/merge_requests/user_views_open_merge_requests_spec.rb
index cefac9690ce..932090bdbce 100644
--- a/spec/features/merge_requests/user_views_open_merge_requests_spec.rb
+++ b/spec/features/merge_requests/user_views_open_merge_requests_spec.rb
@@ -113,6 +113,7 @@ describe 'User views open merge requests' do
context 'when project is internal' do
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+
set(:project) { create(:project, :internal, :repository) }
context 'when signed in' do
diff --git a/spec/features/oauth_login_spec.rb b/spec/features/oauth_login_spec.rb
index 4a1e8598131..29e9b0c313a 100644
--- a/spec/features/oauth_login_spec.rb
+++ b/spec/features/oauth_login_spec.rb
@@ -33,6 +33,7 @@ describe 'OAuth Login', :js, :allow_forgery_protection do
let(:remember_me) { false }
let(:user) { create(:omniauth_user, extern_uid: uid, provider: provider.to_s) }
let(:two_factor_user) { create(:omniauth_user, :two_factor, extern_uid: uid, provider: provider.to_s) }
+
provider == :salesforce ? let(:additional_info) { { extra: { email_verified: true } } } : let(:additional_info) { {} }
before do
diff --git a/spec/features/participants_autocomplete_spec.rb b/spec/features/participants_autocomplete_spec.rb
index a7bba124716..fdedd319116 100644
--- a/spec/features/participants_autocomplete_spec.rb
+++ b/spec/features/participants_autocomplete_spec.rb
@@ -34,6 +34,7 @@ describe 'Member autocomplete', :js do
context 'adding a new note on a Issue' do
let(:noteable) { create(:issue, author: author, project: project) }
+
before do
visit project_issue_path(project, noteable)
end
@@ -47,6 +48,7 @@ describe 'Member autocomplete', :js do
create(:merge_request, source_project: project,
target_project: project, author: author)
end
+
before do
visit project_merge_request_path(project, noteable)
end
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index 7c8b2640e89..142aaaffb7d 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -194,6 +194,7 @@ describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do
context 'when third party offers are disabled' do
let(:admin) { create(:admin) }
+
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
diff --git a/spec/features/projects/files/user_edits_files_spec.rb b/spec/features/projects/files/user_edits_files_spec.rb
index 374a7fb7936..cc428dce2a8 100644
--- a/spec/features/projects/files/user_edits_files_spec.rb
+++ b/spec/features/projects/files/user_edits_files_spec.rb
@@ -193,6 +193,7 @@ describe 'Projects > Files > User edits files', :js do
context 'when the user already had a fork of the project', :js do
let!(:forked_project) { fork_project(project2, user, namespace: user.namespace, repository: true) }
+
before do
visit(project2_tree_path_root_ref)
wait_for_requests
diff --git a/spec/features/projects/snippets/create_snippet_spec.rb b/spec/features/projects/snippets/create_snippet_spec.rb
index 684793ce116..ad65e04473c 100644
--- a/spec/features/projects/snippets/create_snippet_spec.rb
+++ b/spec/features/projects/snippets/create_snippet_spec.rb
@@ -18,6 +18,7 @@ describe 'Projects > Snippets > Create Snippet', :js do
context 'when a user is authenticated' do
before do
+ stub_feature_flags(snippets_vue: false)
project.add_maintainer(user)
sign_in(user)
@@ -76,6 +77,10 @@ describe 'Projects > Snippets > Create Snippet', :js do
end
context 'when a user is not authenticated' do
+ before do
+ stub_feature_flags(snippets_vue: false)
+ end
+
it 'shows a public snippet on the index page but not the New snippet button' do
snippet = create(:project_snippet, :public, project: project)
diff --git a/spec/features/projects/snippets/show_spec.rb b/spec/features/projects/snippets/show_spec.rb
index e448309356d..9be226c017f 100644
--- a/spec/features/projects/snippets/show_spec.rb
+++ b/spec/features/projects/snippets/show_spec.rb
@@ -8,6 +8,7 @@ describe 'Projects > Snippets > Project snippet', :js do
let(:snippet) { create(:project_snippet, project: project, file_name: file_name, content: content) }
before do
+ stub_feature_flags(snippets_vue: false)
project.add_maintainer(user)
sign_in(user)
end
diff --git a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
index 239d19d35d1..11707378996 100644
--- a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
+++ b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
@@ -8,6 +8,7 @@ describe 'Projects > Snippets > User comments on a snippet', :js do
let(:user) { create(:user) }
before do
+ stub_feature_flags(snippets_vue: false)
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/projects/snippets/user_deletes_snippet_spec.rb b/spec/features/projects/snippets/user_deletes_snippet_spec.rb
index 1b56d7bf26d..7e337710e19 100644
--- a/spec/features/projects/snippets/user_deletes_snippet_spec.rb
+++ b/spec/features/projects/snippets/user_deletes_snippet_spec.rb
@@ -8,6 +8,7 @@ describe 'Projects > Snippets > User deletes a snippet' do
let(:user) { create(:user) }
before do
+ stub_feature_flags(snippets_vue: false)
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/projects/snippets/user_updates_snippet_spec.rb b/spec/features/projects/snippets/user_updates_snippet_spec.rb
index c7ff4f89fd6..93a5b4a7262 100644
--- a/spec/features/projects/snippets/user_updates_snippet_spec.rb
+++ b/spec/features/projects/snippets/user_updates_snippet_spec.rb
@@ -8,6 +8,7 @@ describe 'Projects > Snippets > User updates a snippet' do
let(:user) { create(:user) }
before do
+ stub_feature_flags(snippets_vue: false)
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/reportable_note/snippets_spec.rb b/spec/features/reportable_note/snippets_spec.rb
index c2c853cdb05..bd37675315f 100644
--- a/spec/features/reportable_note/snippets_spec.rb
+++ b/spec/features/reportable_note/snippets_spec.rb
@@ -7,6 +7,7 @@ describe 'Reportable note on snippets', :js do
let(:project) { create(:project) }
before do
+ stub_feature_flags(snippets_vue: false)
project.add_maintainer(user)
sign_in(user)
end
diff --git a/spec/features/security/group/internal_access_spec.rb b/spec/features/security/group/internal_access_spec.rb
index a182b6b9d57..8dd15789cd1 100644
--- a/spec/features/security/group/internal_access_spec.rb
+++ b/spec/features/security/group/internal_access_spec.rb
@@ -53,6 +53,7 @@ describe 'Internal Group access' do
describe 'GET /groups/:path/merge_requests' do
let(:project) { create(:project, :internal, :repository, group: group) }
+
subject { merge_requests_group_path(group) }
it { is_expected.to be_allowed_for(:admin) }
diff --git a/spec/features/security/group/private_access_spec.rb b/spec/features/security/group/private_access_spec.rb
index 5e3e9824aaa..0720302b03b 100644
--- a/spec/features/security/group/private_access_spec.rb
+++ b/spec/features/security/group/private_access_spec.rb
@@ -53,6 +53,7 @@ describe 'Private Group access' do
describe 'GET /groups/:path/merge_requests' do
let(:project) { create(:project, :private, :repository, group: group) }
+
subject { merge_requests_group_path(group) }
it { is_expected.to be_allowed_for(:admin) }
diff --git a/spec/features/security/group/public_access_spec.rb b/spec/features/security/group/public_access_spec.rb
index efc84205980..0a18a0ff812 100644
--- a/spec/features/security/group/public_access_spec.rb
+++ b/spec/features/security/group/public_access_spec.rb
@@ -53,6 +53,7 @@ describe 'Public Group access' do
describe 'GET /groups/:path/merge_requests' do
let(:project) { create(:project, :public, :repository, group: group) }
+
subject { merge_requests_group_path(group) }
it { is_expected.to be_allowed_for(:admin) }
diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb
index 20a320e5b92..5c74b566ef0 100644
--- a/spec/features/security/project/internal_access_spec.rb
+++ b/spec/features/security/project/internal_access_spec.rb
@@ -129,6 +129,7 @@ describe "Internal Project Access" do
describe "GET /:project_path/blob" do
let(:commit) { project.repository.commit }
+
subject { project_blob_path(project, File.join(commit.id, '.gitignore')) }
it { is_expected.to be_allowed_for(:admin) }
@@ -186,6 +187,7 @@ describe "Internal Project Access" do
describe "GET /:project_path/issues/:id/edit" do
let(:issue) { create(:issue, project: project) }
+
subject { edit_project_issue_path(project, issue) }
it { is_expected.to be_allowed_for(:admin) }
@@ -327,6 +329,7 @@ describe "Internal Project Access" do
describe "GET /:project_path/pipelines/:id" do
let(:pipeline) { create(:ci_pipeline, project: project) }
+
subject { project_pipeline_path(project, pipeline) }
it { is_expected.to be_allowed_for(:admin) }
@@ -379,6 +382,7 @@ describe "Internal Project Access" do
describe "GET /:project_path/builds/:id" do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
+
subject { project_job_path(project, build.id) }
context "when allowed for public and internal" do
@@ -417,6 +421,7 @@ describe "Internal Project Access" do
describe 'GET /:project_path/builds/:id/trace' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
+
subject { trace_project_job_path(project, build.id) }
context 'when allowed for public and internal' do
@@ -482,6 +487,7 @@ describe "Internal Project Access" do
describe "GET /:project_path/-/environments/:id" do
let(:environment) { create(:environment, project: project) }
+
subject { project_environment_path(project, environment) }
it { is_expected.to be_allowed_for(:admin) }
@@ -497,6 +503,7 @@ describe "Internal Project Access" do
describe "GET /:project_path/-/environments/:id/deployments" do
let(:environment) { create(:environment, project: project) }
+
subject { project_environment_deployments_path(project, environment) }
it { is_expected.to be_allowed_for(:admin) }
diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb
index 62f9a96305d..2404b7cc69d 100644
--- a/spec/features/security/project/private_access_spec.rb
+++ b/spec/features/security/project/private_access_spec.rb
@@ -129,6 +129,7 @@ describe "Private Project Access" do
describe "GET /:project_path/blob" do
let(:commit) { project.repository.commit }
+
subject { project_blob_path(project, File.join(commit.id, '.gitignore')) }
it { is_expected.to be_allowed_for(:admin) }
@@ -186,6 +187,7 @@ describe "Private Project Access" do
describe "GET /:project_path/issues/:id/edit" do
let(:issue) { create(:issue, project: project) }
+
subject { edit_project_issue_path(project, issue) }
it { is_expected.to be_allowed_for(:admin) }
@@ -311,6 +313,7 @@ describe "Private Project Access" do
describe "GET /:project_path/pipelines/:id" do
let(:pipeline) { create(:ci_pipeline, project: project) }
+
subject { project_pipeline_path(project, pipeline) }
it { is_expected.to be_allowed_for(:admin) }
@@ -365,6 +368,7 @@ describe "Private Project Access" do
describe "GET /:project_path/builds/:id" do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
+
subject { project_job_path(project, build.id) }
it { is_expected.to be_allowed_for(:admin) }
@@ -398,6 +402,7 @@ describe "Private Project Access" do
describe 'GET /:project_path/builds/:id/trace' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
+
subject { trace_project_job_path(project, build.id) }
it { is_expected.to be_allowed_for(:admin) }
@@ -443,6 +448,7 @@ describe "Private Project Access" do
describe "GET /:project_path/-/environments/:id" do
let(:environment) { create(:environment, project: project) }
+
subject { project_environment_path(project, environment) }
it { is_expected.to be_allowed_for(:admin) }
@@ -458,6 +464,7 @@ describe "Private Project Access" do
describe "GET /:project_path/-/environments/:id/deployments" do
let(:environment) { create(:environment, project: project) }
+
subject { project_environment_deployments_path(project, environment) }
it { is_expected.to be_allowed_for(:admin) }
diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb
index 317c7bae084..8e07af61c8b 100644
--- a/spec/features/security/project/public_access_spec.rb
+++ b/spec/features/security/project/public_access_spec.rb
@@ -143,6 +143,7 @@ describe "Public Project Access" do
describe "GET /:project_path/pipelines/:id" do
let(:pipeline) { create(:ci_pipeline, project: project) }
+
subject { project_pipeline_path(project, pipeline) }
it { is_expected.to be_allowed_for(:admin) }
@@ -195,6 +196,7 @@ describe "Public Project Access" do
describe "GET /:project_path/builds/:id" do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
+
subject { project_job_path(project, build.id) }
context "when allowed for public" do
@@ -233,6 +235,7 @@ describe "Public Project Access" do
describe 'GET /:project_path/builds/:id/trace' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
+
subject { trace_project_job_path(project, build.id) }
context 'when allowed for public' do
@@ -298,6 +301,7 @@ describe "Public Project Access" do
describe "GET /:project_path/-/environments/:id" do
let(:environment) { create(:environment, project: project) }
+
subject { project_environment_path(project, environment) }
it { is_expected.to be_allowed_for(:admin) }
@@ -313,6 +317,7 @@ describe "Public Project Access" do
describe "GET /:project_path/-/environments/:id/deployments" do
let(:environment) { create(:environment, project: project) }
+
subject { project_environment_deployments_path(project, environment) }
it { is_expected.to be_allowed_for(:admin) }
@@ -399,6 +404,7 @@ describe "Public Project Access" do
describe "GET /:project_path/issues/:id/edit" do
let(:issue) { create(:issue, project: project) }
+
subject { edit_project_issue_path(project, issue) }
it { is_expected.to be_allowed_for(:admin) }
diff --git a/spec/features/snippets/explore_spec.rb b/spec/features/snippets/explore_spec.rb
index 57e91fea709..2075742eafb 100644
--- a/spec/features/snippets/explore_spec.rb
+++ b/spec/features/snippets/explore_spec.rb
@@ -6,30 +6,59 @@ describe 'Explore Snippets' do
let!(:public_snippet) { create(:personal_snippet, :public) }
let!(:internal_snippet) { create(:personal_snippet, :internal) }
let!(:private_snippet) { create(:personal_snippet, :private) }
+ let(:user) { nil }
- it 'User should see snippets that are not private' do
- sign_in create(:user)
+ before do
+ sign_in(user) if user
visit explore_snippets_path
-
- expect(page).to have_content(public_snippet.title)
- expect(page).to have_content(internal_snippet.title)
- expect(page).not_to have_content(private_snippet.title)
end
- it 'External user should see only public snippets' do
- sign_in create(:user, :external)
- visit explore_snippets_path
+ context 'User' do
+ let(:user) { create(:user) }
+
+ it 'see snippets that are not private' do
+ expect(page).to have_content(public_snippet.title)
+ expect(page).to have_content(internal_snippet.title)
+ expect(page).not_to have_content(private_snippet.title)
+ end
- expect(page).to have_content(public_snippet.title)
- expect(page).not_to have_content(internal_snippet.title)
- expect(page).not_to have_content(private_snippet.title)
+ it 'shows new snippet button in header' do
+ parent_element = page.find('.page-title-controls')
+ expect(parent_element).to have_link('New snippet')
+ end
end
- it 'Not authenticated user should see only public snippets' do
- visit explore_snippets_path
+ context 'External user' do
+ let(:user) { create(:user, :external) }
+
+ it 'see only public snippets' do
+ expect(page).to have_content(public_snippet.title)
+ expect(page).not_to have_content(internal_snippet.title)
+ expect(page).not_to have_content(private_snippet.title)
+ end
+
+ context 'without snippets' do
+ before do
+ Snippet.delete_all
+ end
+
+ it 'hides new snippet button' do
+ expect(page).not_to have_link('New snippet')
+ end
+ end
+
+ context 'with snippets' do
+ it 'hides new snippet button' do
+ expect(page).not_to have_link('New snippet')
+ end
+ end
+ end
- expect(page).to have_content(public_snippet.title)
- expect(page).not_to have_content(internal_snippet.title)
- expect(page).not_to have_content(private_snippet.title)
+ context 'Not authenticated user' do
+ it 'see only public snippets' do
+ expect(page).to have_content(public_snippet.title)
+ expect(page).not_to have_content(internal_snippet.title)
+ expect(page).not_to have_content(private_snippet.title)
+ end
end
end
diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb
index acffc4ce580..11429f16f42 100644
--- a/spec/features/task_lists_spec.rb
+++ b/spec/features/task_lists_spec.rb
@@ -146,6 +146,7 @@ describe 'Task Lists' do
describe 'for Notes' do
let!(:issue) { create(:issue, author: user, project: project) }
+
describe 'multiple tasks' do
let!(:note) do
create(:note, note: markdown, noteable: issue,
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index b7c54bb6de8..5f4f92e547c 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -406,6 +406,7 @@ describe 'Login' do
describe 'with required two-factor authentication enabled' do
let(:user) { create(:user) }
+
# TODO: otp_grace_period_started_at
context 'global setting' do
diff --git a/spec/finders/clusters_finder_spec.rb b/spec/finders/clusters_finder_spec.rb
index f6ea8347f67..5dde616f679 100644
--- a/spec/finders/clusters_finder_spec.rb
+++ b/spec/finders/clusters_finder_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe ClustersFinder do
let(:project) { create(:project) }
+
set(:user) { create(:user) }
describe '#execute' do
diff --git a/spec/finders/group_descendants_finder_spec.rb b/spec/finders/group_descendants_finder_spec.rb
index 17875a9b9ab..ee8606e474e 100644
--- a/spec/finders/group_descendants_finder_spec.rb
+++ b/spec/finders/group_descendants_finder_spec.rb
@@ -6,6 +6,7 @@ describe GroupDescendantsFinder do
let(:user) { create(:user) }
let(:group) { create(:group) }
let(:params) { {} }
+
subject(:finder) do
described_class.new(current_user: user, parent_group: group, params: params)
end
diff --git a/spec/finders/group_projects_finder_spec.rb b/spec/finders/group_projects_finder_spec.rb
index 0a7ca5211e1..89fc1e380dc 100644
--- a/spec/finders/group_projects_finder_spec.rb
+++ b/spec/finders/group_projects_finder_spec.rb
@@ -132,11 +132,13 @@ describe GroupProjectsFinder do
context "only shared" do
let(:options) { { only_shared: true } }
+
it { is_expected.to eq([shared_project_3, shared_project_2, shared_project_1]) }
end
context "only owned" do
let(:options) { { only_owned: true } }
+
it { is_expected.to eq([private_project, public_project]) }
end
diff --git a/spec/finders/groups_finder_spec.rb b/spec/finders/groups_finder_spec.rb
index 741a89a270b..939b818f165 100644
--- a/spec/finders/groups_finder_spec.rb
+++ b/spec/finders/groups_finder_spec.rb
@@ -111,6 +111,7 @@ describe GroupsFinder do
context 'authorized to private project' do
context 'project one level deep' do
let!(:subproject) { create(:project, :private, namespace: private_subgroup) }
+
before do
subproject.add_guest(user)
end
@@ -129,6 +130,7 @@ describe GroupsFinder do
context 'project two levels deep' do
let!(:private_subsubgroup) { create(:group, :private, parent: private_subgroup) }
let!(:subsubproject) { create(:project, :private, namespace: private_subsubgroup) }
+
before do
subsubproject.add_guest(user)
end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 6c10a617279..c52ee89006b 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -786,6 +786,7 @@ describe IssuesFinder do
describe '#with_confidentiality_access_check' do
let(:guest) { create(:user) }
+
set(:authorized_user) { create(:user) }
set(:project) { create(:project, namespace: authorized_user.namespace) }
set(:public_issue) { create(:issue, project: project) }
diff --git a/spec/finders/merge_request_target_project_finder_spec.rb b/spec/finders/merge_request_target_project_finder_spec.rb
index 7fef16d1040..4d2e4c5318c 100644
--- a/spec/finders/merge_request_target_project_finder_spec.rb
+++ b/spec/finders/merge_request_target_project_finder_spec.rb
@@ -6,6 +6,7 @@ describe MergeRequestTargetProjectFinder do
include ProjectForksHelper
let(:user) { create(:user) }
+
subject(:finder) { described_class.new(current_user: user, source_project: forked_project) }
shared_examples 'finding related projects' do
diff --git a/spec/finders/pipelines_finder_spec.rb b/spec/finders/pipelines_finder_spec.rb
index 116088f5141..c8a4ea799c3 100644
--- a/spec/finders/pipelines_finder_spec.rb
+++ b/spec/finders/pipelines_finder_spec.rb
@@ -6,6 +6,7 @@ describe PipelinesFinder do
let(:project) { create(:project, :public, :repository) }
let(:current_user) { nil }
let(:params) { {} }
+
subject { described_class.new(project, current_user, params).execute }
describe "#execute" do
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index a9344cd593a..bf97e3cf7db 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -181,6 +181,7 @@ describe ProjectsFinder, :do_not_mock_admin_mode do
describe 'filter by non_public' do
let(:params) { { non_public: true } }
+
before do
private_project.add_developer(current_user)
end
@@ -190,6 +191,7 @@ describe ProjectsFinder, :do_not_mock_admin_mode do
describe 'filter by starred' do
let(:params) { { starred: true } }
+
before do
current_user.toggle_star(public_project)
end
diff --git a/spec/finders/tags_finder_spec.rb b/spec/finders/tags_finder_spec.rb
index 582d82bbf79..b9de2d29895 100644
--- a/spec/finders/tags_finder_spec.rb
+++ b/spec/finders/tags_finder_spec.rb
@@ -96,6 +96,7 @@ describe TagsFinder do
context 'filter and sort' do
let(:tags_to_compare) { %w[v1.0.0 v1.1.0] }
+
subject { described_class.new(repository, params).execute.select { |tag| tags_to_compare.include?(tag.name) } }
context 'when sort by updated_desc' do
diff --git a/spec/frontend/fixtures/static/projects.json b/spec/frontend/fixtures/static/projects.json
index d92d3acdea0..f28d9899099 100644
--- a/spec/frontend/fixtures/static/projects.json
+++ b/spec/frontend/fixtures/static/projects.json
@@ -99,6 +99,15 @@
"access_level": 50,
"notification_level": 3
}
+ },
+ "_links": {
+ "self": "https://gitlab.com/api/v4/projects/278964",
+ "issues": "https://gitlab.com/api/v4/projects/278964/issues",
+ "merge_requests": "https://gitlab.com/api/v4/projects/278964/merge_requests",
+ "repo_branches": "https://gitlab.com/api/v4/projects/278964/repository/branches",
+ "labels": "https://gitlab.com/api/v4/projects/278964/labels",
+ "events": "https://gitlab.com/api/v4/projects/278964/events",
+ "members": "https://gitlab.com/api/v4/projects/278964/members"
}
}, {
"id": 7,
diff --git a/spec/frontend/helpers/dom_shims/index.js b/spec/frontend/helpers/dom_shims/index.js
index 40256398e6d..1fc5130cefc 100644
--- a/spec/frontend/helpers/dom_shims/index.js
+++ b/spec/frontend/helpers/dom_shims/index.js
@@ -1 +1,2 @@
import './get_client_rects';
+import './inner_text';
diff --git a/spec/frontend/helpers/dom_shims/inner_text.js b/spec/frontend/helpers/dom_shims/inner_text.js
new file mode 100644
index 00000000000..2b8201eed31
--- /dev/null
+++ b/spec/frontend/helpers/dom_shims/inner_text.js
@@ -0,0 +1,11 @@
+// workaround for JSDOM not supporting innerText
+// see https://github.com/jsdom/jsdom/issues/1245
+Object.defineProperty(global.Element.prototype, 'innerText', {
+ get() {
+ return this.textContent;
+ },
+ set(value) {
+ this.textContext = value;
+ },
+ configurable: true, // make it so that it doesn't blow chunks on re-running tests with things like --watch
+});
diff --git a/spec/frontend/ide/stores/getters_spec.js b/spec/frontend/ide/stores/getters_spec.js
index d196f6f79d5..21c5e886738 100644
--- a/spec/frontend/ide/stores/getters_spec.js
+++ b/spec/frontend/ide/stores/getters_spec.js
@@ -1,12 +1,14 @@
import * as getters from '~/ide/stores/getters';
-import state from '~/ide/stores/state';
+import { createStore } from '~/ide/stores';
import { file } from '../helpers';
describe('IDE store getters', () => {
let localState;
+ let localStore;
beforeEach(() => {
- localState = state();
+ localStore = createStore();
+ localState = localStore.state;
});
describe('activeFile', () => {
@@ -310,4 +312,90 @@ describe('IDE store getters', () => {
expect(getters.canPushToBranch({}, localGetters)).toBeFalsy();
});
});
+
+ describe('isFileDeletedAndReadded', () => {
+ const f = { ...file('sample'), content: 'sample', raw: 'sample' };
+
+ it.each([
+ {
+ entry: { ...f, tempFile: true },
+ staged: { ...f, deleted: true },
+ output: true,
+ },
+ {
+ entry: { ...f, content: 'changed' },
+ staged: { ...f, content: 'changed' },
+ output: false,
+ },
+ {
+ entry: { ...f, content: 'changed' },
+ output: false,
+ },
+ ])(
+ 'checks staged and unstaged files to see if a file was deleted and readded (case %#)',
+ ({ entry, staged, output }) => {
+ Object.assign(localState, {
+ entries: {
+ [entry.path]: entry,
+ },
+ stagedFiles: [],
+ });
+
+ if (staged) localState.stagedFiles.push(staged);
+
+ expect(localStore.getters.isFileDeletedAndReadded(entry.path)).toBe(output);
+ },
+ );
+ });
+
+ describe('getDiffInfo', () => {
+ const f = { ...file('sample'), content: 'sample', raw: 'sample' };
+ it.each([
+ {
+ entry: { ...f, tempFile: true },
+ staged: { ...f, deleted: true },
+ output: { deleted: false, changed: false, tempFile: false },
+ },
+ {
+ entry: { ...f, tempFile: true, content: 'changed', raw: '' },
+ staged: { ...f, deleted: true },
+ output: { deleted: false, changed: true, tempFile: false },
+ },
+ {
+ entry: { ...f, content: 'changed' },
+ output: { changed: true },
+ },
+ {
+ entry: { ...f, content: 'sample' },
+ staged: { ...f, content: 'changed' },
+ output: { changed: false },
+ },
+ {
+ entry: { ...f, deleted: true },
+ output: { deleted: true, changed: false },
+ },
+ {
+ entry: { ...f, prevPath: 'old_path' },
+ output: { renamed: true, changed: false },
+ },
+ {
+ entry: { ...f, prevPath: 'old_path', content: 'changed' },
+ output: { renamed: true, changed: true },
+ },
+ ])(
+ 'compares changes in a file entry and returns a resulting diff info (case %#)',
+ ({ entry, staged, output }) => {
+ Object.assign(localState, {
+ entries: {
+ [entry.path]: entry,
+ },
+ stagedFiles: [],
+ });
+
+ if (staged) localState.stagedFiles.push(staged);
+
+ expect(localStore.getters.getDiffInfo(entry.path)).toEqual(expect.objectContaining(output));
+ },
+ );
+ });
});
diff --git a/spec/javascripts/monitoring/charts/column_spec.js b/spec/frontend/monitoring/components/charts/column_spec.js
index 9676617e8e1..b4539801e0f 100644
--- a/spec/javascripts/monitoring/charts/column_spec.js
+++ b/spec/frontend/monitoring/components/charts/column_spec.js
@@ -4,6 +4,10 @@ import ColumnChart from '~/monitoring/components/charts/column.vue';
const localVue = createLocalVue();
+jest.mock('~/lib/utils/icon_utils', () => ({
+ getSvgIconPathContent: jest.fn().mockResolvedValue('mockSvgPathContent'),
+}));
+
describe('Column component', () => {
let columnChart;
diff --git a/spec/javascripts/monitoring/charts/empty_chart_spec.js b/spec/frontend/monitoring/components/charts/empty_chart_spec.js
index 06822126b59..06822126b59 100644
--- a/spec/javascripts/monitoring/charts/empty_chart_spec.js
+++ b/spec/frontend/monitoring/components/charts/empty_chart_spec.js
diff --git a/spec/javascripts/monitoring/charts/heatmap_spec.js b/spec/frontend/monitoring/components/charts/heatmap_spec.js
index 9a98fc6fb05..5e2c1932e9e 100644
--- a/spec/javascripts/monitoring/charts/heatmap_spec.js
+++ b/spec/frontend/monitoring/components/charts/heatmap_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { GlHeatmap } from '@gitlab/ui/dist/charts';
import Heatmap from '~/monitoring/components/charts/heatmap.vue';
-import { graphDataPrometheusQueryRangeMultiTrack } from '../mock_data';
+import { graphDataPrometheusQueryRangeMultiTrack } from '../../mock_data';
describe('Heatmap component', () => {
let heatmapChart;
diff --git a/spec/javascripts/monitoring/charts/single_stat_spec.js b/spec/frontend/monitoring/components/charts/single_stat_spec.js
index 6adca0b0eed..78bcc400787 100644
--- a/spec/javascripts/monitoring/charts/single_stat_spec.js
+++ b/spec/frontend/monitoring/components/charts/single_stat_spec.js
@@ -1,6 +1,6 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import SingleStatChart from '~/monitoring/components/charts/single_stat.vue';
-import { graphDataPrometheusQuery } from '../mock_data';
+import { graphDataPrometheusQuery } from '../../mock_data';
const localVue = createLocalVue();
diff --git a/spec/frontend/monitoring/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js
index 128c4bc49f1..098b3408e67 100644
--- a/spec/frontend/monitoring/charts/time_series_spec.js
+++ b/spec/frontend/monitoring/components/charts/time_series_spec.js
@@ -12,20 +12,14 @@ import {
mockedQueryResultPayload,
mockProjectDir,
mockHost,
-} from '../mock_data';
-
+} from '../../mock_data';
import * as iconUtils from '~/lib/utils/icon_utils';
-const mockSvgPathContent = 'mockSvgPathContent';
const mockWidgets = 'mockWidgets';
+const mockSvgPathContent = 'mockSvgPathContent';
jest.mock('~/lib/utils/icon_utils', () => ({
- getSvgIconPathContent: jest.fn().mockImplementation(
- () =>
- new Promise(resolve => {
- resolve(mockSvgPathContent);
- }),
- ),
+ getSvgIconPathContent: jest.fn().mockImplementation(() => Promise.resolve(mockSvgPathContent)),
}));
describe('Time series component', () => {
diff --git a/spec/frontend/repository/components/table/parent_row_spec.js b/spec/frontend/repository/components/table/parent_row_spec.js
index 7020055271f..63f84b2597b 100644
--- a/spec/frontend/repository/components/table/parent_row_spec.js
+++ b/spec/frontend/repository/components/table/parent_row_spec.js
@@ -30,8 +30,8 @@ describe('Repository parent row component', () => {
it.each`
path | to
- ${'app'} | ${'/tree/master/'}
- ${'app/assets'} | ${'/tree/master/app'}
+ ${'app'} | ${'/-/tree/master/'}
+ ${'app/assets'} | ${'/-/tree/master/app'}
`('renders link in $path to $to', ({ path, to }) => {
factory(path);
@@ -46,7 +46,7 @@ describe('Repository parent row component', () => {
vm.find('td').trigger('click');
expect($router.push).toHaveBeenCalledWith({
- path: '/tree/master/app',
+ path: '/-/tree/master/app',
});
});
@@ -58,7 +58,7 @@ describe('Repository parent row component', () => {
vm.find('a').trigger('click');
expect($router.push).not.toHaveBeenCalledWith({
- path: '/tree/master/app',
+ path: '/-/tree/master/app',
});
});
});
diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js
index 94fa8b1e363..3114b6a2eaa 100644
--- a/spec/frontend/repository/components/table/row_spec.js
+++ b/spec/frontend/repository/components/table/row_spec.js
@@ -83,7 +83,7 @@ describe('Repository table row component', () => {
vm.trigger('click');
if (pushes) {
- expect($router.push).toHaveBeenCalledWith({ path: '/tree/master/test' });
+ expect($router.push).toHaveBeenCalledWith({ path: '/-/tree/master/test' });
} else {
expect($router.push).not.toHaveBeenCalled();
}
diff --git a/spec/frontend/repository/router_spec.js b/spec/frontend/repository/router_spec.js
index f61a0ccd1e6..1efd74a30c2 100644
--- a/spec/frontend/repository/router_spec.js
+++ b/spec/frontend/repository/router_spec.js
@@ -4,11 +4,11 @@ import createRouter from '~/repository/router';
describe('Repository router spec', () => {
it.each`
- path | component | componentName
- ${'/'} | ${IndexPage} | ${'IndexPage'}
- ${'/tree/master'} | ${TreePage} | ${'TreePage'}
- ${'/tree/master/app/assets'} | ${TreePage} | ${'TreePage'}
- ${'/tree/123/app/assets'} | ${null} | ${'null'}
+ path | component | componentName
+ ${'/'} | ${IndexPage} | ${'IndexPage'}
+ ${'/-/tree/master'} | ${TreePage} | ${'TreePage'}
+ ${'/-/tree/master/app/assets'} | ${TreePage} | ${'TreePage'}
+ ${'/-/tree/123/app/assets'} | ${null} | ${'null'}
`('sets component as $componentName for path "$path"', ({ path, component }) => {
const router = createRouter('', 'master');
diff --git a/spec/frontend/snippets/components/app_spec.js b/spec/frontend/snippets/components/app_spec.js
index 535e71b6da7..f2800f9e6af 100644
--- a/spec/frontend/snippets/components/app_spec.js
+++ b/spec/frontend/snippets/components/app_spec.js
@@ -1,19 +1,22 @@
import SnippetApp from '~/snippets/components/app.vue';
+import SnippetHeader from '~/snippets/components/snippet_header.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
+
import { createLocalVue, shallowMount } from '@vue/test-utils';
describe('Snippet view app', () => {
let wrapper;
- let snippetDataMock;
const localVue = createLocalVue();
const defaultProps = {
- snippetGid: 'gid://gitlab/PersonalSnippet/35',
+ snippetGid: 'gid://gitlab/PersonalSnippet/42',
};
- function createComponent({ props = defaultProps, snippetData = {} } = {}) {
- snippetDataMock = jest.fn();
+ function createComponent({ props = defaultProps, loading = false } = {}) {
const $apollo = {
queries: {
- snippetData: snippetDataMock,
+ snippet: {
+ loading,
+ },
},
};
@@ -25,17 +28,18 @@ describe('Snippet view app', () => {
...props,
},
});
-
- wrapper.setData({
- snippetData,
- });
}
afterEach(() => {
wrapper.destroy();
});
- it('renders itself', () => {
+ it('renders loader while the query is in flight', () => {
+ createComponent({ loading: true });
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+
+ it('renders SnippetHeader component after the query is finished', () => {
createComponent();
- expect(wrapper.find('.js-snippet-view').exists()).toBe(true);
+ expect(wrapper.find(SnippetHeader).exists()).toBe(true);
});
});
diff --git a/spec/frontend/snippets/components/snippet_header_spec.js b/spec/frontend/snippets/components/snippet_header_spec.js
new file mode 100644
index 00000000000..8847a3a6938
--- /dev/null
+++ b/spec/frontend/snippets/components/snippet_header_spec.js
@@ -0,0 +1,171 @@
+import SnippetHeader from '~/snippets/components/snippet_header.vue';
+import DeleteSnippetMutation from '~/snippets/mutations/deleteSnippet.mutation.graphql';
+import { ApolloMutation } from 'vue-apollo';
+import { GlButton, GlModal } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+
+describe('Snippet header component', () => {
+ let wrapper;
+ const localVue = createLocalVue();
+ const snippet = {
+ snippet: {
+ id: 'gid://gitlab/PersonalSnippet/50',
+ title: 'The property of Thor',
+ visibilityLevel: 'private',
+ webUrl: 'http://personal.dev.null/42',
+ userPermissions: {
+ adminSnippet: true,
+ updateSnippet: true,
+ reportSnippet: false,
+ },
+ project: null,
+ author: {
+ name: 'Thor Odinson',
+ },
+ },
+ };
+ const mutationVariables = {
+ mutation: DeleteSnippetMutation,
+ variables: {
+ id: snippet.snippet.id,
+ },
+ };
+ const errorMsg = 'Foo bar';
+ const err = { message: errorMsg };
+
+ const resolveMutate = jest.fn(() => Promise.resolve());
+ const rejectMutation = jest.fn(() => Promise.reject(err));
+
+ const mutationTypes = {
+ RESOLVE: resolveMutate,
+ REJECT: rejectMutation,
+ };
+
+ function createComponent({
+ loading = false,
+ permissions = {},
+ mutationRes = mutationTypes.RESOLVE,
+ } = {}) {
+ const defaultProps = Object.assign({}, snippet);
+ if (permissions) {
+ Object.assign(defaultProps.snippet.userPermissions, {
+ ...permissions,
+ });
+ }
+ const $apollo = {
+ queries: {
+ canCreateSnippet: {
+ loading,
+ },
+ },
+ mutate: mutationRes,
+ };
+
+ wrapper = shallowMount(SnippetHeader, {
+ sync: false,
+ mocks: { $apollo },
+ localVue,
+ propsData: {
+ ...defaultProps,
+ },
+ stubs: {
+ ApolloMutation,
+ },
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders itself', () => {
+ createComponent();
+ expect(wrapper.find('.detail-page-header').exists()).toBe(true);
+ });
+
+ it('renders action buttons based on permissions', () => {
+ createComponent({
+ permissions: {
+ adminSnippet: false,
+ updateSnippet: false,
+ },
+ });
+ expect(wrapper.findAll(GlButton).length).toEqual(0);
+
+ createComponent({
+ permissions: {
+ adminSnippet: true,
+ updateSnippet: false,
+ },
+ });
+ expect(wrapper.findAll(GlButton).length).toEqual(1);
+
+ createComponent({
+ permissions: {
+ adminSnippet: true,
+ updateSnippet: true,
+ },
+ });
+ expect(wrapper.findAll(GlButton).length).toEqual(2);
+
+ createComponent({
+ permissions: {
+ adminSnippet: true,
+ updateSnippet: true,
+ },
+ });
+ wrapper.setData({
+ canCreateSnippet: true,
+ });
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.findAll(GlButton).length).toEqual(3);
+ });
+ });
+
+ it('renders modal for deletion of a snippet', () => {
+ createComponent();
+ expect(wrapper.find(GlModal).exists()).toBe(true);
+ });
+
+ describe('Delete mutation', () => {
+ const { location } = window;
+
+ beforeEach(() => {
+ delete window.location;
+ window.location = {
+ pathname: '',
+ };
+ });
+
+ afterEach(() => {
+ window.location = location;
+ });
+
+ it('dispatches a mutation to delete the snippet with correct variables', () => {
+ createComponent();
+ wrapper.vm.deleteSnippet();
+ expect(mutationTypes.RESOLVE).toHaveBeenCalledWith(mutationVariables);
+ });
+
+ it('sets error message if mutation fails', () => {
+ createComponent({ mutationRes: mutationTypes.REJECT });
+ expect(Boolean(wrapper.vm.errorMessage)).toBe(false);
+
+ wrapper.vm.deleteSnippet();
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.errorMessage).toEqual(errorMsg);
+ });
+ });
+
+ it('closes modal and redirects to snippets listing in case of successful mutation', () => {
+ createComponent();
+ wrapper.vm.closeDeleteModal = jest.fn();
+
+ wrapper.vm.deleteSnippet();
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled();
+ expect(window.location.pathname).toEqual('dashboard/snippets');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index 4636de6b8b6..ab42dbe7cd1 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -34,18 +34,6 @@ Vue.config.productionTip = false;
Vue.use(Translate);
-// workaround for JSDOM not supporting innerText
-// see https://github.com/jsdom/jsdom/issues/1245
-Object.defineProperty(global.Element.prototype, 'innerText', {
- get() {
- return this.textContent;
- },
- set(value) {
- this.textContext = value;
- },
- configurable: true, // make it so that it doesn't blow chunks on re-running tests with things like --watch
-});
-
// convenience wrapper for migration from Karma
Object.assign(global, {
getJSONFixture,
diff --git a/spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb b/spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb
index 897b8f4e9ef..fcc717f83a2 100644
--- a/spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb
+++ b/spec/graphql/mutations/concerns/mutations/resolves_group_spec.rb
@@ -10,6 +10,7 @@ describe Mutations::ResolvesGroup do
end
let(:context) { double }
+
subject(:mutation) { mutation_class.new(object: nil, context: context) }
it 'uses the GroupsResolver to resolve groups by path' do
diff --git a/spec/graphql/mutations/concerns/mutations/resolves_project_spec.rb b/spec/graphql/mutations/concerns/mutations/resolves_project_spec.rb
index 09d1f66a2c7..918e5fb016e 100644
--- a/spec/graphql/mutations/concerns/mutations/resolves_project_spec.rb
+++ b/spec/graphql/mutations/concerns/mutations/resolves_project_spec.rb
@@ -10,6 +10,7 @@ describe Mutations::ResolvesProject do
end
let(:context) { double }
+
subject(:mutation) { mutation_class.new(object: nil, context: context) }
it 'uses the ProjectsResolver to resolve projects by path' do
diff --git a/spec/graphql/mutations/issues/set_confidential_spec.rb b/spec/graphql/mutations/issues/set_confidential_spec.rb
index 05b787eb5ca..a8f1fcdf7f1 100644
--- a/spec/graphql/mutations/issues/set_confidential_spec.rb
+++ b/spec/graphql/mutations/issues/set_confidential_spec.rb
@@ -5,11 +5,13 @@ require 'spec_helper'
describe Mutations::Issues::SetConfidential do
let(:issue) { create(:issue) }
let(:user) { create(:user) }
+
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }) }
describe '#resolve' do
let(:confidential) { true }
let(:mutated_issue) { subject[:issue] }
+
subject { mutation.resolve(project_path: issue.project.full_path, iid: issue.iid, confidential: confidential) }
it 'raises an error if the resource is not accessible to the user' do
diff --git a/spec/graphql/mutations/issues/set_due_date_spec.rb b/spec/graphql/mutations/issues/set_due_date_spec.rb
index 9a1f0925fe3..b45a7b460cd 100644
--- a/spec/graphql/mutations/issues/set_due_date_spec.rb
+++ b/spec/graphql/mutations/issues/set_due_date_spec.rb
@@ -5,11 +5,13 @@ require 'spec_helper'
describe Mutations::Issues::SetDueDate do
let(:issue) { create(:issue) }
let(:user) { create(:user) }
+
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }) }
describe '#resolve' do
let(:due_date) { 2.days.since }
let(:mutated_issue) { subject[:issue] }
+
subject { mutation.resolve(project_path: issue.project.full_path, iid: issue.iid, due_date: due_date) }
it 'raises an error if the resource is not accessible to the user' do
diff --git a/spec/graphql/mutations/merge_requests/set_assignees_spec.rb b/spec/graphql/mutations/merge_requests/set_assignees_spec.rb
index e8da0e25b7d..2033ab57a0d 100644
--- a/spec/graphql/mutations/merge_requests/set_assignees_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_assignees_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
describe Mutations::MergeRequests::SetAssignees do
let(:merge_request) { create(:merge_request) }
let(:user) { create(:user) }
+
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }) }
describe '#resolve' do
@@ -12,6 +13,7 @@ describe Mutations::MergeRequests::SetAssignees do
let(:assignee2) { create(:user) }
let(:assignee_usernames) { [assignee.username] }
let(:mutated_merge_request) { subject[:merge_request] }
+
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, assignee_usernames: assignee_usernames) }
before do
diff --git a/spec/graphql/mutations/merge_requests/set_labels_spec.rb b/spec/graphql/mutations/merge_requests/set_labels_spec.rb
index 3729251bab7..f7c04a57f68 100644
--- a/spec/graphql/mutations/merge_requests/set_labels_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_labels_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
describe Mutations::MergeRequests::SetLabels do
let(:merge_request) { create(:merge_request) }
let(:user) { create(:user) }
+
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }) }
describe '#resolve' do
@@ -12,6 +13,7 @@ describe Mutations::MergeRequests::SetLabels do
let(:label2) { create(:label, project: merge_request.project) }
let(:label_ids) { [label.to_global_id] }
let(:mutated_merge_request) { subject[:merge_request] }
+
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, label_ids: label_ids) }
it 'raises an error if the resource is not accessible to the user' do
diff --git a/spec/graphql/mutations/merge_requests/set_locked_spec.rb b/spec/graphql/mutations/merge_requests/set_locked_spec.rb
index 51249854378..d35430abff1 100644
--- a/spec/graphql/mutations/merge_requests/set_locked_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_locked_spec.rb
@@ -5,11 +5,13 @@ require 'spec_helper'
describe Mutations::MergeRequests::SetLocked do
let(:merge_request) { create(:merge_request) }
let(:user) { create(:user) }
+
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }) }
describe '#resolve' do
let(:locked) { true }
let(:mutated_merge_request) { subject[:merge_request] }
+
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, locked: locked) }
it 'raises an error if the resource is not accessible to the user' do
diff --git a/spec/graphql/mutations/merge_requests/set_milestone_spec.rb b/spec/graphql/mutations/merge_requests/set_milestone_spec.rb
index c2792a4bc25..d79b0a995d7 100644
--- a/spec/graphql/mutations/merge_requests/set_milestone_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_milestone_spec.rb
@@ -5,11 +5,13 @@ require 'spec_helper'
describe Mutations::MergeRequests::SetMilestone do
let(:merge_request) { create(:merge_request) }
let(:user) { create(:user) }
+
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }) }
describe '#resolve' do
let(:milestone) { create(:milestone, project: merge_request.project) }
let(:mutated_merge_request) { subject[:merge_request] }
+
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, milestone: milestone) }
it 'raises an error if the resource is not accessible to the user' do
diff --git a/spec/graphql/mutations/merge_requests/set_subscription_spec.rb b/spec/graphql/mutations/merge_requests/set_subscription_spec.rb
index 116a77abcc0..286de6c0c97 100644
--- a/spec/graphql/mutations/merge_requests/set_subscription_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_subscription_spec.rb
@@ -6,11 +6,13 @@ describe Mutations::MergeRequests::SetSubscription do
let(:merge_request) { create(:merge_request) }
let(:project) { merge_request.project }
let(:user) { create(:user) }
+
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }) }
describe '#resolve' do
let(:subscribe) { true }
let(:mutated_merge_request) { subject[:merge_request] }
+
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, subscribed_state: subscribe) }
it 'raises an error if the resource is not accessible to the user' do
diff --git a/spec/graphql/mutations/merge_requests/set_wip_spec.rb b/spec/graphql/mutations/merge_requests/set_wip_spec.rb
index c4accab9e46..490994c4577 100644
--- a/spec/graphql/mutations/merge_requests/set_wip_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_wip_spec.rb
@@ -5,11 +5,13 @@ require 'spec_helper'
describe Mutations::MergeRequests::SetWip do
let(:merge_request) { create(:merge_request) }
let(:user) { create(:user) }
+
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }) }
describe '#resolve' do
let(:wip) { true }
let(:mutated_merge_request) { subject[:merge_request] }
+
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, wip: wip) }
it 'raises an error if the resource is not accessible to the user' do
diff --git a/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb b/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb
index fa031af4013..b59561ebdd4 100644
--- a/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb
+++ b/spec/graphql/resolvers/concerns/resolves_pipelines_spec.rb
@@ -16,6 +16,7 @@ describe ResolvesPipelines do
end
let(:current_user) { create(:user) }
+
set(:project) { create(:project, :private) }
set(:pipeline) { create(:ci_pipeline, project: project) }
set(:failed_pipeline) { create(:ci_pipeline, :failed, project: project) }
diff --git a/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb b/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb
index 5e7f18636ec..4490b54d1f7 100644
--- a/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb
+++ b/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb
@@ -20,6 +20,7 @@ describe Resolvers::ErrorTracking::SentryDetailedErrorResolver do
describe '#resolve' do
let(:args) { { id: issue_global_id(1234) } }
+
it 'fetches the data via the sentry API' do
resolve_error(args)
diff --git a/spec/graphql/types/permission_types/base_permission_type_spec.rb b/spec/graphql/types/permission_types/base_permission_type_spec.rb
index a45102e5b50..aa6b4320006 100644
--- a/spec/graphql/types/permission_types/base_permission_type_spec.rb
+++ b/spec/graphql/types/permission_types/base_permission_type_spec.rb
@@ -6,6 +6,7 @@ describe Types::PermissionTypes::BasePermissionType do
let(:permitable) { double('permittable') }
let(:current_user) { build(:user) }
let(:context) { { current_user: current_user } }
+
subject(:test_type) do
Class.new(described_class) do
graphql_name 'TestClass'
diff --git a/spec/helpers/avatars_helper_spec.rb b/spec/helpers/avatars_helper_spec.rb
index 77182a59c1c..8b6817efcc4 100644
--- a/spec/helpers/avatars_helper_spec.rb
+++ b/spec/helpers/avatars_helper_spec.rb
@@ -193,6 +193,7 @@ describe AvatarsHelper do
describe '#user_avatar_without_link' do
let(:options) { { user: user } }
+
subject { helper.user_avatar_without_link(options) }
it 'displays user avatar' do
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index 4996e27c2e6..2d0c4723648 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -56,7 +56,7 @@ describe BlobHelper do
stub_feature_flags(web_ide_default: false)
link = helper.edit_blob_button(project, 'master', 'README.md')
- expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/#{project.full_path}/edit/master/README.md")
+ expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/#{project.full_path}/-/edit/master/README.md")
end
it 'returns a link with a Web IDE route' do
@@ -69,7 +69,7 @@ describe BlobHelper do
stub_feature_flags(web_ide_default: false)
link = helper.edit_blob_button(project, 'master', 'README.md', link_opts: { mr_id: 10 })
- expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/#{project.full_path}/edit/master/README.md?mr_id=10")
+ expect(Capybara.string(link).find_link('Edit')[:href]).to eq("/#{project.full_path}/-/edit/master/README.md?mr_id=10")
end
end
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index 63a37a1f113..fa553710274 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
describe EventsHelper do
describe '#event_commit_title' do
let(:message) { 'foo & bar ' + 'A' * 70 + '\n' + 'B' * 80 }
+
subject { helper.event_commit_title(message) }
it 'returns the first line, truncated to 70 chars' do
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index 8b33277ea18..ac2f028f937 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -127,6 +127,7 @@ describe GroupsHelper do
sub_sub_owner: sub_sub_owner
}
end
+
subject { helper.share_with_group_lock_help_text(sub_subgroup) }
where(:root_share_with_group_locked, :subgroup_share_with_group_locked, :sub_subgroup_share_with_group_locked, :current_user, :help_text, :linked_ancestor) do
@@ -194,6 +195,7 @@ describe GroupsHelper do
describe '#group_container_registry_nav' do
let(:group) { create(:group, :public) }
let(:user) { create(:user) }
+
before do
stub_container_registry_config(enabled: true)
allow(helper).to receive(:current_user) { user }
@@ -229,6 +231,7 @@ describe GroupsHelper do
describe '#group_sidebar_links' do
let(:group) { create(:group, :public) }
let(:user) { create(:user) }
+
before do
group.add_owner(user)
allow(helper).to receive(:current_user) { user }
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index 9249c625135..a39110d0aa7 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -278,6 +278,7 @@ describe IssuablesHelper do
describe '#assignee_sidebar_data' do
let(:user) { create(:user) }
let(:merge_request) { nil }
+
subject { helper.assignee_sidebar_data(user, merge_request: merge_request) }
it 'returns hash of assignee data' do
diff --git a/spec/helpers/labels_helper_spec.rb b/spec/helpers/labels_helper_spec.rb
index e2dff05cfaa..7ad554fd618 100644
--- a/spec/helpers/labels_helper_spec.rb
+++ b/spec/helpers/labels_helper_spec.rb
@@ -274,6 +274,7 @@ describe LabelsHelper do
describe '#label_status_tooltip' do
let(:status) { 'unsubscribed'.inquiry }
+
subject { label_status_tooltip(label.present(issuable_subject: nil), status) }
context 'with a project label' do
diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb
index 5ca5f5703cf..6227a5f5662 100644
--- a/spec/helpers/markup_helper_spec.rb
+++ b/spec/helpers/markup_helper_spec.rb
@@ -44,6 +44,7 @@ describe MarkupHelper do
describe "override default project" do
let(:actual) { issue.to_reference }
+
set(:second_project) { create(:project, :public) }
set(:second_issue) { create(:issue, project: second_project) }
@@ -55,6 +56,7 @@ describe MarkupHelper do
describe 'uploads' do
let(:text) { "![ImageTest](/uploads/test.png)" }
+
set(:group) { create(:group) }
subject { helper.markdown(text) }
@@ -101,7 +103,7 @@ describe MarkupHelper do
let(:requested_path) { 'files/images/README.md' }
it 'returns the correct HTML for the image' do
- expanded_path = "/#{project.full_path}/raw/master/files/images/#{image_file}"
+ expanded_path = "/#{project.full_path}/-/raw/master/files/images/#{image_file}"
expect(subject.css('a')[0].attr('href')).to eq(expanded_path)
expect(subject.css('img')[0].attr('data-src')).to eq(expanded_path)
diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb
index 6bd567eab57..8db8c37038e 100644
--- a/spec/helpers/merge_requests_helper_spec.rb
+++ b/spec/helpers/merge_requests_helper_spec.rb
@@ -54,6 +54,7 @@ describe MergeRequestsHelper do
describe '#format_mr_branch_names' do
describe 'within the same project' do
let(:merge_request) { create(:merge_request) }
+
subject { format_mr_branch_names(merge_request) }
it { is_expected.to eq([merge_request.source_branch, merge_request.target_branch]) }
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 0db54599ede..46228d0d1c2 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -313,6 +313,7 @@ describe ProjectsHelper do
describe '#link_to_project' do
let(:group) { create(:group, name: 'group name with space') }
let(:project) { create(:project, group: group, name: 'project name with space') }
+
subject { link_to_project(project) }
it 'returns an HTML link to the project' do
@@ -544,6 +545,7 @@ describe ProjectsHelper do
describe '#git_user_name' do
let(:user) { double(:user, name: 'John "A" Doe53') }
+
before do
allow(helper).to receive(:current_user).and_return(user)
end
@@ -566,6 +568,7 @@ describe ProjectsHelper do
context 'user logged in' do
let(:user) { create(:user) }
+
before do
allow(helper).to receive(:current_user).and_return(user)
end
diff --git a/spec/helpers/submodule_helper_spec.rb b/spec/helpers/submodule_helper_spec.rb
index fcfce0eaf31..9046c1e9fb4 100644
--- a/spec/helpers/submodule_helper_spec.rb
+++ b/spec/helpers/submodule_helper_spec.rb
@@ -95,7 +95,7 @@ describe SubmoduleHelper do
allow(repo).to receive(:project).and_return(project)
stub_url('./')
- expect(subject).to eq(["/master-project/#{project.path}", "/master-project/#{project.path}/tree/hash"])
+ expect(subject).to eq(["/master-project/#{project.path}", "/master-project/#{project.path}/-/tree/hash"])
end
end
@@ -166,7 +166,7 @@ describe SubmoduleHelper do
allow(repo).to receive(:submodule_url_for).and_return(relative_path)
result = subject
- expect(result).to eq([expected_path, "#{expected_path}/tree/#{submodule_item.id}"])
+ expect(result).to eq([expected_path, "#{expected_path}/-/tree/#{submodule_item.id}"])
end
it 'handles project under same group' do
diff --git a/spec/javascripts/diffs/components/app_spec.js b/spec/javascripts/diffs/components/app_spec.js
index b21cab58b4e..48e1ed18a2f 100644
--- a/spec/javascripts/diffs/components/app_spec.js
+++ b/spec/javascripts/diffs/components/app_spec.js
@@ -92,16 +92,16 @@ describe('diffs/components/app', () => {
});
});
- it('calls fetchDiffFiles if diffsBatchLoad is enabled, and not latest version', () => {
+ it('calls batch methods if diffsBatchLoad is enabled, and not latest version', () => {
wrapper.vm.glFeatures.diffsBatchLoad = true;
wrapper.vm.isLatestVersion = () => false;
wrapper.vm.fetchData(false);
- expect(wrapper.vm.fetchDiffFiles).toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
wrapper.vm.$nextTick(() => {
expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
- expect(wrapper.vm.fetchDiffFilesMeta).not.toHaveBeenCalled();
- expect(wrapper.vm.fetchDiffFilesBatch).not.toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
+ expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
});
});
diff --git a/spec/javascripts/diffs/store/actions_spec.js b/spec/javascripts/diffs/store/actions_spec.js
index 589bd0e649a..b23334d38dc 100644
--- a/spec/javascripts/diffs/store/actions_spec.js
+++ b/spec/javascripts/diffs/store/actions_spec.js
@@ -147,13 +147,15 @@ describe('DiffsStoreActions', () => {
describe('fetchDiffFilesBatch', () => {
it('should fetch batch diff files', done => {
const endpointBatch = '/fetch/diffs_batch';
- const batch1 = `${endpointBatch}?per_page=${DIFFS_PER_PAGE}`;
- const batch2 = `${endpointBatch}?per_page=${DIFFS_PER_PAGE}&page=2`;
const mock = new MockAdapter(axios);
const res1 = { diff_files: [], pagination: { next_page: 2 } };
const res2 = { diff_files: [], pagination: {} };
- mock.onGet(batch1).reply(200, res1);
- mock.onGet(batch2).reply(200, res2);
+ mock
+ .onGet(endpointBatch, { params: { page: undefined, per_page: DIFFS_PER_PAGE, w: '1' } })
+ .reply(200, res1);
+ mock
+ .onGet(endpointBatch, { params: { page: 2, per_page: DIFFS_PER_PAGE, w: '1' } })
+ .reply(200, res2);
testAction(
fetchDiffFilesBatch,
diff --git a/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js b/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
index c743f1f6ad7..6a83790093a 100644
--- a/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
+++ b/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
@@ -38,11 +38,11 @@ describe('DiffViewer', () => {
setTimeout(() => {
expect(vm.$el.querySelector('.deleted img').getAttribute('src')).toBe(
- `//raw/DEF/${RED_BOX_IMAGE_URL}`,
+ `//-/raw/DEF/${RED_BOX_IMAGE_URL}`,
);
expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(
- `//raw/ABC/${GREEN_BOX_IMAGE_URL}`,
+ `//-/raw/ABC/${GREEN_BOX_IMAGE_URL}`,
);
done();
diff --git a/spec/lib/banzai/filter/relative_link_filter_spec.rb b/spec/lib/banzai/filter/relative_link_filter_spec.rb
index 1efca647b8b..500df24ece8 100644
--- a/spec/lib/banzai/filter/relative_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/relative_link_filter_spec.rb
@@ -153,7 +153,7 @@ describe Banzai::Filter::RelativeLinkFilter do
it 'rebuilds absolute URL for a file in the repo' do
doc = filter(link('/doc/api/README.md'))
expect(doc.at_css('a')['href'])
- .to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
+ .to eq "/#{project_path}/-/blob/#{ref}/doc/api/README.md"
end
it 'does not modify relative URLs in system notes' do
@@ -171,13 +171,13 @@ describe Banzai::Filter::RelativeLinkFilter do
it 'rebuilds relative URL for a file in the repo' do
doc = filter(link('doc/api/README.md'))
expect(doc.at_css('a')['href'])
- .to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
+ .to eq "/#{project_path}/-/blob/#{ref}/doc/api/README.md"
end
it 'rebuilds relative URL for a file in the repo with leading ./' do
doc = filter(link('./doc/api/README.md'))
expect(doc.at_css('a')['href'])
- .to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
+ .to eq "/#{project_path}/-/blob/#{ref}/doc/api/README.md"
end
it 'rebuilds relative URL for a file in the repo up one directory' do
@@ -185,7 +185,7 @@ describe Banzai::Filter::RelativeLinkFilter do
doc = filter(relative_link, requested_path: 'doc/update/7.14-to-8.0.md')
expect(doc.at_css('a')['href'])
- .to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
+ .to eq "/#{project_path}/-/blob/#{ref}/doc/api/README.md"
end
it 'rebuilds relative URL for a file in the repo up multiple directories' do
@@ -193,7 +193,7 @@ describe Banzai::Filter::RelativeLinkFilter do
doc = filter(relative_link, requested_path: 'doc/foo/bar/baz/README.md')
expect(doc.at_css('a')['href'])
- .to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
+ .to eq "/#{project_path}/-/blob/#{ref}/doc/api/README.md"
end
it 'rebuilds relative URL for a file in the repository root' do
@@ -201,47 +201,47 @@ describe Banzai::Filter::RelativeLinkFilter do
doc = filter(relative_link, requested_path: 'doc/some-file.md')
expect(doc.at_css('a')['href'])
- .to eq "/#{project_path}/blob/#{ref}/README.md"
+ .to eq "/#{project_path}/-/blob/#{ref}/README.md"
end
it 'rebuilds relative URL for a file in the repo with an anchor' do
doc = filter(link('README.md#section'))
expect(doc.at_css('a')['href'])
- .to eq "/#{project_path}/blob/#{ref}/README.md#section"
+ .to eq "/#{project_path}/-/blob/#{ref}/README.md#section"
end
it 'rebuilds relative URL for a directory in the repo' do
doc = filter(link('doc/api/'))
expect(doc.at_css('a')['href'])
- .to eq "/#{project_path}/tree/#{ref}/doc/api"
+ .to eq "/#{project_path}/-/tree/#{ref}/doc/api"
end
it 'rebuilds relative URL for an image in the repo' do
doc = filter(image('files/images/logo-black.png'))
expect(doc.at_css('img')['src'])
- .to eq "/#{project_path}/raw/#{ref}/files/images/logo-black.png"
+ .to eq "/#{project_path}/-/raw/#{ref}/files/images/logo-black.png"
end
it 'rebuilds relative URL for link to an image in the repo' do
doc = filter(link('files/images/logo-black.png'))
expect(doc.at_css('a')['href'])
- .to eq "/#{project_path}/raw/#{ref}/files/images/logo-black.png"
+ .to eq "/#{project_path}/-/raw/#{ref}/files/images/logo-black.png"
end
it 'rebuilds relative URL for a video in the repo' do
doc = filter(video('files/videos/intro.mp4'), commit: project.commit('video'), ref: 'video')
expect(doc.at_css('video')['src'])
- .to eq "/#{project_path}/raw/video/files/videos/intro.mp4"
+ .to eq "/#{project_path}/-/raw/video/files/videos/intro.mp4"
end
it 'rebuilds relative URL for audio in the repo' do
doc = filter(audio('files/audio/sample.wav'), commit: project.commit('audio'), ref: 'audio')
expect(doc.at_css('audio')['src'])
- .to eq "/#{project_path}/raw/audio/files/audio/sample.wav"
+ .to eq "/#{project_path}/-/raw/audio/files/audio/sample.wav"
end
it 'does not modify relative URL with an anchor only' do
@@ -268,7 +268,7 @@ describe Banzai::Filter::RelativeLinkFilter do
allow_any_instance_of(described_class).to receive(:uri_type).and_return(:raw)
doc = filter(image(escaped))
- expect(doc.at_css('img')['src']).to eq "/#{project_path}/raw/#{Addressable::URI.escape(ref)}/#{escaped}"
+ expect(doc.at_css('img')['src']).to eq "/#{project_path}/-/raw/#{Addressable::URI.escape(ref)}/#{escaped}"
end
context 'when requested path is a file in the repo' do
@@ -276,7 +276,7 @@ describe Banzai::Filter::RelativeLinkFilter do
it 'rebuilds URL relative to the containing directory' do
doc = filter(link('users.md'))
- expect(doc.at_css('a')['href']).to eq "/#{project_path}/blob/#{Addressable::URI.escape(ref)}/doc/api/users.md"
+ expect(doc.at_css('a')['href']).to eq "/#{project_path}/-/blob/#{Addressable::URI.escape(ref)}/doc/api/users.md"
end
end
@@ -285,7 +285,7 @@ describe Banzai::Filter::RelativeLinkFilter do
it 'rebuilds URL relative to the directory' do
doc = filter(link('users.md'))
- expect(doc.at_css('a')['href']).to eq "/#{project_path}/blob/#{Addressable::URI.escape(ref)}/doc/api/users.md"
+ expect(doc.at_css('a')['href']).to eq "/#{project_path}/-/blob/#{Addressable::URI.escape(ref)}/doc/api/users.md"
end
end
@@ -296,7 +296,7 @@ describe Banzai::Filter::RelativeLinkFilter do
it 'correctly escapes the ref' do
doc = filter(link('.gitkeep'))
- expect(doc.at_css('a')['href']).to eq "/#{project_path}/blob/#{Addressable::URI.escape(ref)}/foo/bar/.gitkeep"
+ expect(doc.at_css('a')['href']).to eq "/#{project_path}/-/blob/#{Addressable::URI.escape(ref)}/foo/bar/.gitkeep"
end
end
@@ -315,7 +315,7 @@ describe Banzai::Filter::RelativeLinkFilter do
doc = filter(link(path))
expect(doc.at_css('a')['href'])
- .to eq "/#{project_path}/raw/#{ref_escaped}/files/images/logo-black.png"
+ .to eq "/#{project_path}/-/raw/#{ref_escaped}/files/images/logo-black.png"
end
end
@@ -326,7 +326,7 @@ describe Banzai::Filter::RelativeLinkFilter do
it 'does not escape the space twice' do
doc = filter(link('README.md'))
- expect(doc.at_css('a')['href']).to eq "/#{project_path}/blob/#{Addressable::URI.escape(ref)}/with%20space/README.md"
+ expect(doc.at_css('a')['href']).to eq "/#{project_path}/-/blob/#{Addressable::URI.escape(ref)}/with%20space/README.md"
end
end
end
diff --git a/spec/lib/gitlab/conflict/file_spec.rb b/spec/lib/gitlab/conflict/file_spec.rb
index adf5a232a75..7ecc42ea497 100644
--- a/spec/lib/gitlab/conflict/file_spec.rb
+++ b/spec/lib/gitlab/conflict/file_spec.rb
@@ -258,7 +258,7 @@ FILE
describe '#as_json' do
it 'includes the blob path for the file' do
expect(conflict_file.as_json[:blob_path])
- .to eq("/#{project.full_path}/blob/#{our_commit.oid}/files/ruby/regex.rb")
+ .to eq("/#{project.full_path}/-/blob/#{our_commit.oid}/files/ruby/regex.rb")
end
it 'includes the blob icon for the file' do
diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb
index a033316a6d9..3db8900ed8e 100644
--- a/spec/lib/gitlab/database_spec.rb
+++ b/spec/lib/gitlab/database_spec.rb
@@ -324,6 +324,7 @@ describe Gitlab::Database do
context 'with version < 9.5' do
let(:version) { 9.4 }
+
it 'refuses setting the upsert' do
expect(connection)
.not_to receive(:execute)
diff --git a/spec/lib/gitlab/dependency_linker/godeps_json_linker_spec.rb b/spec/lib/gitlab/dependency_linker/godeps_json_linker_spec.rb
index 9f8542a76c9..7128689e362 100644
--- a/spec/lib/gitlab/dependency_linker/godeps_json_linker_spec.rb
+++ b/spec/lib/gitlab/dependency_linker/godeps_json_linker_spec.rb
@@ -75,8 +75,8 @@ describe Gitlab::DependencyLinker::GodepsJsonLinker do
end
it 'links GitLab projects' do
- expect(subject).to include(link('gitlab.com/group/project/path', 'https://gitlab.com/group/project/tree/master/path'))
- expect(subject).to include(link('gitlab.com/group/subgroup/project.git/path', 'https://gitlab.com/group/subgroup/project/tree/master/path'))
+ expect(subject).to include(link('gitlab.com/group/project/path', 'https://gitlab.com/group/project/-/tree/master/path'))
+ expect(subject).to include(link('gitlab.com/group/subgroup/project.git/path', 'https://gitlab.com/group/subgroup/project/-/tree/master/path'))
end
it 'links Golang packages' do
diff --git a/spec/lib/gitlab/middleware/go_spec.rb b/spec/lib/gitlab/middleware/go_spec.rb
index 2b90035d148..99c2a364dfc 100644
--- a/spec/lib/gitlab/middleware/go_spec.rb
+++ b/spec/lib/gitlab/middleware/go_spec.rb
@@ -241,7 +241,7 @@ describe Gitlab::Middleware::Go do
project_url = "http://#{Gitlab.config.gitlab.host}/#{path}"
expect(response[0]).to eq(200)
expect(response[1]['Content-Type']).to eq('text/html')
- expected_body = %{<html><head><meta name="go-import" content="#{Gitlab.config.gitlab.host}/#{path} git #{repository_url}" /><meta name="go-source" content="#{Gitlab.config.gitlab.host}/#{path} #{project_url} #{project_url}/tree/#{branch}{/dir} #{project_url}/blob/#{branch}{/dir}/{file}#L{line}" /></head><body>go get #{Gitlab.config.gitlab.url}/#{path}</body></html>}
+ expected_body = %{<html><head><meta name="go-import" content="#{Gitlab.config.gitlab.host}/#{path} git #{repository_url}" /><meta name="go-source" content="#{Gitlab.config.gitlab.host}/#{path} #{project_url} #{project_url}/-/tree/#{branch}{/dir} #{project_url}/-/blob/#{branch}{/dir}/{file}#L{line}" /></head><body>go get #{Gitlab.config.gitlab.url}/#{path}</body></html>}
expect(response[2].body).to eq([expected_body])
end
end
diff --git a/spec/lib/gitlab/prometheus/queries/knative_invocation_query_spec.rb b/spec/lib/gitlab/prometheus/queries/knative_invocation_query_spec.rb
index 0936d895453..fa2dccc7c92 100644
--- a/spec/lib/gitlab/prometheus/queries/knative_invocation_query_spec.rb
+++ b/spec/lib/gitlab/prometheus/queries/knative_invocation_query_spec.rb
@@ -16,12 +16,12 @@ describe Gitlab::Prometheus::Queries::KnativeInvocationQuery do
create(:prometheus_metric,
:common,
identifier: :system_metrics_knative_function_invocation_count,
- query: 'sum(ceil(rate(istio_requests_total{destination_service_namespace="%{kube_namespace}", destination_app=~"%{function_name}.*"}[1m])*60))')
+ query: 'sum(ceil(rate(istio_requests_total{destination_service_namespace="%{kube_namespace}", destination_service=~"%{function_name}.*"}[1m])*60))')
end
it 'has the query, but no data' do
expect(client).to receive(:query_range).with(
- 'sum(ceil(rate(istio_requests_total{destination_service_namespace="test-ns", destination_app=~"test-name.*"}[1m])*60))',
+ 'sum(ceil(rate(istio_requests_total{destination_service_namespace="test-ns", destination_service=~"test-name.*"}[1m])*60))',
hash_including(:start, :stop)
)
diff --git a/spec/lib/quality/test_level_spec.rb b/spec/lib/quality/test_level_spec.rb
index c85994402dd..13817bdcc72 100644
--- a/spec/lib/quality/test_level_spec.rb
+++ b/spec/lib/quality/test_level_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Quality::TestLevel do
context 'when level is unit' do
it 'returns a pattern' do
expect(subject.pattern(:unit))
- .to eq("spec/{bin,config,db,dependencies,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,migrations,models,policies,presenters,rack_servers,routing,rubocop,serializers,services,sidekiq,tasks,uploaders,validators,views,workers,elastic_integration}{,/**/}*_spec.rb")
+ .to eq("spec/{bin,config,db,dependencies,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,models,policies,presenters,rack_servers,routing,rubocop,serializers,services,sidekiq,tasks,uploaders,validators,views,workers,elastic_integration}{,/**/}*_spec.rb")
end
end
@@ -82,7 +82,7 @@ RSpec.describe Quality::TestLevel do
context 'when level is unit' do
it 'returns a regexp' do
expect(subject.regexp(:unit))
- .to eq(%r{spec/(bin|config|db|dependencies|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|migrations|models|policies|presenters|rack_servers|routing|rubocop|serializers|services|sidekiq|tasks|uploaders|validators|views|workers|elastic_integration)})
+ .to eq(%r{spec/(bin|config|db|dependencies|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|models|policies|presenters|rack_servers|routing|rubocop|serializers|services|sidekiq|tasks|uploaders|validators|views|workers|elastic_integration)})
end
end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index ad256c10964..e4a7d62eb02 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -109,6 +109,7 @@ describe Notify do
describe 'that are reassigned' do
let(:previous_assignee) { create(:user, name: 'Previous Assignee') }
+
subject { described_class.reassigned_issue_email(recipient.id, issue.id, [previous_assignee.id], current_user.id) }
it_behaves_like 'a multiple recipients email'
@@ -207,6 +208,7 @@ describe Notify do
describe 'status changed' do
let(:status) { 'closed' }
+
subject { described_class.issue_status_changed_email(recipient.id, issue.id, status, current_user.id) }
it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
@@ -235,6 +237,7 @@ describe Notify do
describe 'moved to another project' do
let(:new_issue) { create(:issue) }
+
subject { described_class.issue_moved_email(recipient, issue, new_issue, current_user) }
context 'when a user has permissions to access the new issue' do
@@ -334,6 +337,7 @@ describe Notify do
describe 'that are reassigned' do
let(:previous_assignee) { create(:user, name: 'Previous Assignee') }
+
subject { described_class.reassigned_merge_request_email(recipient.id, merge_request.id, [previous_assignee.id], current_user.id) }
it_behaves_like 'a multiple recipients email'
@@ -426,6 +430,7 @@ describe Notify do
describe 'status changed' do
let(:status) { 'reopened' }
+
subject { described_class.merge_request_status_email(recipient.id, merge_request.id, status, current_user.id) }
it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
@@ -454,6 +459,7 @@ describe Notify do
describe 'that are merged' do
let(:merge_author) { create(:user) }
+
subject { described_class.merged_merge_request_email(recipient.id, merge_request.id, merge_author.id) }
it_behaves_like 'a multiple recipients email'
@@ -698,6 +704,7 @@ describe Notify do
describe 'project was moved' do
let(:recipient) { user }
+
subject { described_class.project_was_moved_email(project.id, user.id, "gitlab/gitlab") }
it_behaves_like 'an email sent to a user'
@@ -725,6 +732,7 @@ describe Notify do
project.request_access(user)
project.requesters.find_by(user_id: user.id)
end
+
subject { described_class.member_access_requested_email('project', project_member.id, recipient.id) }
it_behaves_like 'an email sent from GitLab'
@@ -750,6 +758,7 @@ describe Notify do
project.request_access(user)
project.requesters.find_by(user_id: user.id)
end
+
subject { described_class.member_access_denied_email('project', project.id, user.id) }
it_behaves_like 'an email sent from GitLab'
@@ -769,6 +778,7 @@ describe Notify do
let(:owner) { create(:user, name: "Chang O'Keefe") }
let(:project) { create(:project, :public, namespace: owner.namespace) }
let(:project_member) { create(:project_member, project: project, user: user) }
+
subject { described_class.member_access_granted_email('project', project_member.id) }
it_behaves_like 'an email sent from GitLab'
@@ -1190,6 +1200,7 @@ describe Notify do
group.request_access(user)
group.requesters.find_by(user_id: user.id)
end
+
subject { described_class.member_access_requested_email('group', group_member.id, recipient.id) }
it_behaves_like 'an email sent from GitLab'
@@ -1216,6 +1227,7 @@ describe Notify do
group.requesters.find_by(user_id: user.id)
end
let(:recipient) { user }
+
subject { described_class.member_access_denied_email('group', group.id, user.id) }
it_behaves_like 'an email sent from GitLab'
diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb
index 5b45dc078de..c1057af5f80 100644
--- a/spec/models/clusters/applications/knative_spec.rb
+++ b/spec/models/clusters/applications/knative_spec.rb
@@ -123,7 +123,7 @@ describe Clusters::Applications::Knative do
subject { knative.install_command }
it 'is initialized with latest version' do
- expect(subject.version).to eq('0.7.0')
+ expect(subject.version).to eq('0.9.0')
end
it_behaves_like 'a command'
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 99d7e4d156f..7170003857e 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -697,7 +697,7 @@ describe Project do
let(:project) { create(:project, :repository) }
it 'returns the README' do
- expect(project.readme_url).to eq("#{project.web_url}/blob/master/README.md")
+ expect(project.readme_url).to eq("#{project.web_url}/-/blob/master/README.md")
end
end
end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 7465a616a83..188eafadfc1 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -307,6 +307,7 @@ describe ProjectPolicy do
context 'for a guest in a private project' do
let(:project) { create(:project, :private) }
+
subject { described_class.new(guest, project) }
it 'disallows the guest from reading the merge request and merge request iid' do
@@ -320,6 +321,7 @@ describe ProjectPolicy do
describe 'for unconfirmed user' do
let(:unconfirmed_user) { create(:user, confirmed_at: nil) }
+
subject { described_class.new(unconfirmed_user, project) }
it 'disallows to modify pipelines' do
diff --git a/spec/presenters/blob_presenter_spec.rb b/spec/presenters/blob_presenter_spec.rb
index 8680e8b9b45..ee7bfd1256d 100644
--- a/spec/presenters/blob_presenter_spec.rb
+++ b/spec/presenters/blob_presenter_spec.rb
@@ -21,7 +21,7 @@ describe BlobPresenter, :seed_helper do
subject { described_class.new(blob) }
- it { expect(subject.web_url).to eq("http://localhost/#{project.full_path}/blob/#{blob.commit_id}/#{blob.path}") }
+ it { expect(subject.web_url).to eq("http://localhost/#{project.full_path}/-/blob/#{blob.commit_id}/#{blob.path}") }
end
describe '#highlight' do
diff --git a/spec/presenters/label_presenter_spec.rb b/spec/presenters/label_presenter_spec.rb
index d566da7c872..e9f9657490d 100644
--- a/spec/presenters/label_presenter_spec.rb
+++ b/spec/presenters/label_presenter_spec.rb
@@ -41,6 +41,7 @@ describe LabelPresenter do
describe '#filter_path' do
context 'with group as context subject' do
let(:label_in_group) { build_stubbed(:label, project: project).present(issuable_subject: group) }
+
subject { label_in_group.filter_path }
it { is_expected.to eq(issues_group_path(group, label_name: [label_in_group.title])) }
diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb
index 6ce6f84cf61..025f083ab27 100644
--- a/spec/presenters/merge_request_presenter_spec.rb
+++ b/spec/presenters/merge_request_presenter_spec.rb
@@ -334,7 +334,7 @@ describe MergeRequestPresenter do
allow(resource).to receive(:target_branch_exists?) { true }
is_expected
- .to eq("/#{resource.target_project.full_path}/commits/#{resource.target_branch}")
+ .to eq("/#{resource.target_project.full_path}/-/commits/#{resource.target_branch}")
end
end
@@ -358,7 +358,7 @@ describe MergeRequestPresenter do
allow(resource).to receive(:source_branch_exists?) { true }
is_expected
- .to eq("/#{resource.source_project.full_path}/commits/#{resource.source_branch}")
+ .to eq("/#{resource.source_project.full_path}/-/commits/#{resource.source_branch}")
end
end
@@ -382,7 +382,7 @@ describe MergeRequestPresenter do
allow(resource).to receive(:target_branch_exists?) { true }
is_expected
- .to eq("/#{resource.target_project.full_path}/tree/#{resource.target_branch}")
+ .to eq("/#{resource.target_project.full_path}/-/tree/#{resource.target_branch}")
end
end
@@ -496,7 +496,7 @@ describe MergeRequestPresenter do
allow(resource).to receive(:source_branch_exists?) { true }
is_expected
- .to eq("<a href=\"/#{resource.source_project.full_path}/tree/#{resource.source_branch}\">#{resource.source_branch}</a>")
+ .to eq("<a href=\"/#{resource.source_project.full_path}/-/tree/#{resource.source_branch}\">#{resource.source_branch}</a>")
end
it 'escapes html, when source_branch does not exist' do
diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb
index ce095d2225f..318024bacd6 100644
--- a/spec/presenters/project_presenter_spec.rb
+++ b/spec/presenters/project_presenter_spec.rb
@@ -436,6 +436,7 @@ describe ProjectPresenter do
describe '#repo_statistics_buttons' do
let(:presenter) { described_class.new(project, current_user: user) }
+
subject(:empty_repo_statistics_buttons) { presenter.empty_repo_statistics_buttons }
before do
diff --git a/spec/presenters/tree_entry_presenter_spec.rb b/spec/presenters/tree_entry_presenter_spec.rb
index d74ee5dc28f..0c29fe3e5ff 100644
--- a/spec/presenters/tree_entry_presenter_spec.rb
+++ b/spec/presenters/tree_entry_presenter_spec.rb
@@ -11,6 +11,6 @@ describe TreeEntryPresenter do
let(:presenter) { described_class.new(tree) }
describe '.web_url' do
- it { expect(presenter.web_url).to eq("http://localhost/#{project.full_path}/tree/#{tree.commit_id}/#{tree.path}") }
+ it { expect(presenter.web_url).to eq("http://localhost/#{project.full_path}/-/tree/#{tree.commit_id}/#{tree.path}") }
end
end
diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb
index 80040cddd4d..19a34314bb8 100644
--- a/spec/requests/api/award_emoji_spec.rb
+++ b/spec/requests/api/award_emoji_spec.rb
@@ -9,6 +9,7 @@ describe API::AwardEmoji do
set(:award_emoji) { create(:award_emoji, awardable: issue, user: user) }
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let!(:downvote) { create(:award_emoji, :downvote, awardable: merge_request, user: user) }
+
set(:note) { create(:note, project: project, noteable: issue) }
before do
diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb
index 8a67e956165..510ef9d7d0a 100644
--- a/spec/requests/api/boards_spec.rb
+++ b/spec/requests/api/boards_spec.rb
@@ -69,6 +69,7 @@ describe API::Boards do
set(:group) { create(:group) }
set(:board_parent) { create(:group, parent: group ) }
let(:url) { "/groups/#{board_parent.id}/boards/#{board.id}/lists" }
+
set(:board) { create(:board, group: board_parent) }
it 'creates a new board list for ancestor group labels' do
diff --git a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
index 5b910d5bfe0..b24981873c8 100644
--- a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
+++ b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
@@ -75,6 +75,7 @@ describe 'Adding an AwardEmoji' do
describe 'marking Todos as done' do
let(:user) { current_user}
+
subject { post_graphql_mutation(mutation, current_user: user) }
include_examples 'creating award emojis marks Todos as done'
diff --git a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
index ae628d3e56c..5e2c0e668a5 100644
--- a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
+++ b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
@@ -83,6 +83,7 @@ describe 'Toggling an AwardEmoji' do
describe 'marking Todos as done' do
let(:user) { current_user}
+
subject { post_graphql_mutation(mutation, current_user: user) }
include_examples 'creating award emojis marks Todos as done'
diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb
index 866adbd424e..186f0f52a46 100644
--- a/spec/requests/api/project_import_spec.rb
+++ b/spec/requests/api/project_import_spec.rb
@@ -7,6 +7,7 @@ describe API::ProjectImport do
let(:user) { create(:user) }
let(:file) { File.join('spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') }
let(:namespace) { create(:group) }
+
before do
allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
stub_uploads_object_storage(FileUploader)
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index cda2dd7d2f4..eb3d5e698d8 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -715,7 +715,7 @@ describe API::Projects do
post api('/projects', user), params: project
- expect(json_response['readme_url']).to eql("#{Gitlab.config.gitlab.url}/#{json_response['namespace']['full_path']}/somewhere/blob/master/README.md")
+ expect(json_response['readme_url']).to eql("#{Gitlab.config.gitlab.url}/#{json_response['namespace']['full_path']}/somewhere/-/blob/master/README.md")
end
it 'sets tag list to a project' do
@@ -1882,6 +1882,7 @@ describe API::Projects do
describe "POST /projects/:id/share" do
let(:group) { create(:group) }
+
before do
group.add_developer(user)
end
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 6599e4b8f23..af86ba86303 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe API::Settings, 'Settings' do
let(:user) { create(:user) }
+
set(:admin) { create(:admin) }
describe "GET /application/settings" do
diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb
index eb9d0d38bcb..f32be7a8765 100644
--- a/spec/requests/api/snippets_spec.rb
+++ b/spec/requests/api/snippets_spec.rb
@@ -375,6 +375,7 @@ describe API::Snippets do
describe 'DELETE /snippets/:id' do
let!(:public_snippet) { create(:personal_snippet, :public, author: user) }
+
it 'deletes snippet' do
expect do
delete api("/snippets/#{public_snippet.id}", user)
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 29088a42fbe..0a22a09b8a6 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -2124,6 +2124,7 @@ describe API::Users do
describe 'GET /user/status' do
let(:path) { '/user/status' }
+
it_behaves_like 'rendering user status'
end
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index 42b4bd71b88..7424b7ee8d0 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -834,7 +834,7 @@ describe 'Git HTTP requests' do
Blob.decorate(Gitlab::Git::Blob.find(project.repository, 'master', 'bar/branch-test.txt'), project)
end
- get "/#{project.full_path}/blob/master/info/refs"
+ get "/#{project.full_path}/-/blob/master/info/refs"
end
it "returns the file" do
@@ -844,7 +844,7 @@ describe 'Git HTTP requests' do
context "when the file does not exist" do
before do
- get "/#{project.full_path}/blob/master/info/refs"
+ get "/#{project.full_path}/-/blob/master/info/refs"
end
it "redirects" do
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 96956d85de4..7816b77d14c 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -454,11 +454,14 @@ describe 'project routing' do
it_behaves_like 'RESTful project resources' do
let(:actions) { [:show] }
let(:controller) { 'commits' }
+ let(:controller_path) { '/-/commits' }
end
it 'to #show' do
- expect(get('/gitlab/gitlabhq/commits/master.atom')).to route_to('projects/commits#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master.atom')
+ expect(get('/gitlab/gitlabhq/-/commits/master.atom')).to route_to('projects/commits#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master.atom')
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/commits/master.atom", "/gitlab/gitlabhq/-/commits/master.atom"
end
# project_project_members GET /:project_id/project_members(.:format) project_members#index
@@ -550,62 +553,68 @@ describe 'project routing' do
# project_blame GET /:project_id/blame/:id(.:format) blame#show {id: /[^\0]+/, project_id: /[^\/]+/}
describe Projects::BlameController, 'routing' do
it 'to #show' do
- expect(get('/gitlab/gitlabhq/blame/master/app/models/project.rb')).to route_to('projects/blame#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
- expect(get('/gitlab/gitlabhq/blame/master/files.scss')).to route_to('projects/blame#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss')
+ expect(get('/gitlab/gitlabhq/-/blame/master/app/models/project.rb')).to route_to('projects/blame#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
+ expect(get('/gitlab/gitlabhq/-/blame/master/files.scss')).to route_to('projects/blame#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss')
newline_file = "new\n\nline.txt"
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
- assert_routing({ path: "/gitlab/gitlabhq/blame/master/#{url_encoded_newline_file}",
+ assert_routing({ path: "/gitlab/gitlabhq/-/blame/master/#{url_encoded_newline_file}",
method: :get },
{ controller: 'projects/blame', action: 'show',
namespace_id: 'gitlab', project_id: 'gitlabhq',
id: "master/#{newline_file}" })
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/blame/master/readme.md", "/gitlab/gitlabhq/-/blame/master/readme.md"
end
# project_blob GET /:project_id/blob/:id(.:format) blob#show {id: /[^\0]+/, project_id: /[^\/]+/}
describe Projects::BlobController, 'routing' do
it 'to #show' do
- expect(get('/gitlab/gitlabhq/blob/master/app/models/project.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
- expect(get('/gitlab/gitlabhq/blob/master/app/models/compare.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/compare.rb')
- expect(get('/gitlab/gitlabhq/blob/master/app/models/diff.js')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/diff.js')
- expect(get('/gitlab/gitlabhq/blob/master/files.scss')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss')
- expect(get('/gitlab/gitlabhq/blob/master/blob/index.js')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/blob/index.js')
- expect(get('/gitlab/gitlabhq/blob/blob/master/blob/index.js')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'blob/master/blob/index.js')
+ expect(get('/gitlab/gitlabhq/-/blob/master/app/models/project.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
+ expect(get('/gitlab/gitlabhq/-/blob/master/app/models/compare.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/compare.rb')
+ expect(get('/gitlab/gitlabhq/-/blob/master/app/models/diff.js')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/diff.js')
+ expect(get('/gitlab/gitlabhq/-/blob/master/files.scss')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss')
+ expect(get('/gitlab/gitlabhq/-/blob/master/blob/index.js')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/blob/index.js')
+ expect(get('/gitlab/gitlabhq/-/blob/blob/master/blob/index.js')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'blob/master/blob/index.js')
newline_file = "new\n\nline.txt"
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
- assert_routing({ path: "/gitlab/gitlabhq/blob/blob/master/blob/#{url_encoded_newline_file}",
+ assert_routing({ path: "/gitlab/gitlabhq/-/blob/blob/master/blob/#{url_encoded_newline_file}",
method: :get },
{ controller: 'projects/blob', action: 'show',
namespace_id: 'gitlab', project_id: 'gitlabhq',
id: "blob/master/blob/#{newline_file}" })
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/blob/master/readme.md", "/gitlab/gitlabhq/-/blob/master/readme.md"
end
# project_tree GET /:project_id/tree/:id(.:format) tree#show {id: /[^\0]+/, project_id: /[^\/]+/}
describe Projects::TreeController, 'routing' do
it 'to #show' do
- expect(get('/gitlab/gitlabhq/tree/master/app/models/project.rb')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
- expect(get('/gitlab/gitlabhq/tree/master/files.scss')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss')
- expect(get('/gitlab/gitlabhq/tree/master/tree/files')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/tree/files')
- expect(get('/gitlab/gitlabhq/tree/tree/master/tree/files')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'tree/master/tree/files')
+ expect(get('/gitlab/gitlabhq/-/tree/master/app/models/project.rb')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
+ expect(get('/gitlab/gitlabhq/-/tree/master/files.scss')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss')
+ expect(get('/gitlab/gitlabhq/-/tree/master/tree/files')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/tree/files')
+ expect(get('/gitlab/gitlabhq/-/tree/tree/master/tree/files')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'tree/master/tree/files')
newline_file = "new\n\nline.txt"
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
- assert_routing({ path: "/gitlab/gitlabhq/tree/master/#{url_encoded_newline_file}",
+ assert_routing({ path: "/gitlab/gitlabhq/-/tree/master/#{url_encoded_newline_file}",
method: :get },
{ controller: 'projects/tree', action: 'show',
namespace_id: 'gitlab', project_id: 'gitlabhq',
id: "master/#{newline_file}" })
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/tree/master/app", "/gitlab/gitlabhq/-/tree/master/app"
end
# project_find_file GET /:namespace_id/:project_id/find_file/*id(.:format) projects/find_file#show {:id=>/[^\0]+/, :namespace_id=>/[a-zA-Z.0-9_\-]+/, :project_id=>/[a-zA-Z.0-9_\-]+(?<!\.atom)/, :format=>/html/}
# project_files GET /:namespace_id/:project_id/files/*id(.:format) projects/find_file#list {:id=>/(?:[^.]|\.(?!json$))+/, :namespace_id=>/[a-zA-Z.0-9_\-]+/, :project_id=>/[a-zA-Z.0-9_\-]+(?<!\.atom)/, :format=>/json/}
describe Projects::FindFileController, 'routing' do
it 'to #show' do
- expect(get('/gitlab/gitlabhq/find_file/master')).to route_to('projects/find_file#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master')
+ expect(get('/gitlab/gitlabhq/-/find_file/master')).to route_to('projects/find_file#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master')
newline_file = "new\n\nline.txt"
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
- assert_routing({ path: "/gitlab/gitlabhq/find_file/#{url_encoded_newline_file}",
+ assert_routing({ path: "/gitlab/gitlabhq/-/find_file/#{url_encoded_newline_file}",
method: :get },
{ controller: 'projects/find_file', action: 'show',
namespace_id: 'gitlab', project_id: 'gitlabhq',
@@ -613,26 +622,29 @@ describe 'project routing' do
end
it 'to #list' do
- expect(get('/gitlab/gitlabhq/files/master.json')).to route_to('projects/find_file#list', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master.json')
+ expect(get('/gitlab/gitlabhq/-/files/master.json')).to route_to('projects/find_file#list', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master.json')
newline_file = "new\n\nline.txt"
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
- assert_routing({ path: "/gitlab/gitlabhq/files/#{url_encoded_newline_file}",
+ assert_routing({ path: "/gitlab/gitlabhq/-/files/#{url_encoded_newline_file}",
method: :get },
{ controller: 'projects/find_file', action: 'list',
namespace_id: 'gitlab', project_id: 'gitlabhq',
id: "#{newline_file}" })
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/find_file/master", "/gitlab/gitlabhq/-/find_file/master"
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/files/master.json", "/gitlab/gitlabhq/-/files/master.json"
end
describe Projects::BlobController, 'routing' do
it 'to #edit' do
- expect(get('/gitlab/gitlabhq/edit/master/app/models/project.rb')).to(
+ expect(get('/gitlab/gitlabhq/-/edit/master/app/models/project.rb')).to(
route_to('projects/blob#edit',
namespace_id: 'gitlab', project_id: 'gitlabhq',
id: 'master/app/models/project.rb'))
newline_file = "new\n\nline.txt"
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
- assert_routing({ path: "/gitlab/gitlabhq/edit/master/docs/#{url_encoded_newline_file}",
+ assert_routing({ path: "/gitlab/gitlabhq/-/edit/master/docs/#{url_encoded_newline_file}",
method: :get },
{ controller: 'projects/blob', action: 'edit',
namespace_id: 'gitlab', project_id: 'gitlabhq',
@@ -640,13 +652,13 @@ describe 'project routing' do
end
it 'to #preview' do
- expect(post('/gitlab/gitlabhq/preview/master/app/models/project.rb')).to(
+ expect(post('/gitlab/gitlabhq/-/preview/master/app/models/project.rb')).to(
route_to('projects/blob#preview',
namespace_id: 'gitlab', project_id: 'gitlabhq',
id: 'master/app/models/project.rb'))
newline_file = "new\n\nline.txt"
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
- assert_routing({ path: "/gitlab/gitlabhq/edit/master/docs/#{url_encoded_newline_file}",
+ assert_routing({ path: "/gitlab/gitlabhq/-/edit/master/docs/#{url_encoded_newline_file}",
method: :get },
{ controller: 'projects/blob', action: 'edit',
namespace_id: 'gitlab', project_id: 'gitlabhq',
@@ -659,12 +671,14 @@ describe 'project routing' do
it 'to #show' do
newline_file = "new\n\nline.txt"
url_encoded_newline_file = ERB::Util.url_encode(newline_file)
- assert_routing({ path: "/gitlab/gitlabhq/raw/master/#{url_encoded_newline_file}",
+ assert_routing({ path: "/gitlab/gitlabhq/-/raw/master/#{url_encoded_newline_file}",
method: :get },
{ controller: 'projects/raw', action: 'show',
namespace_id: 'gitlab', project_id: 'gitlabhq',
id: "master/#{newline_file}" })
end
+
+ it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/raw/master/app/models/project.rb", "/gitlab/gitlabhq/-/raw/master/app/models/project.rb"
end
# project_compare_index GET /:project_id/compare(.:format) compare#index {id: /[^\/]+/, project_id: /[^\/]+/}
diff --git a/spec/serializers/blob_entity_spec.rb b/spec/serializers/blob_entity_spec.rb
index 7e3a0a87bd5..3cd967ed44c 100644
--- a/spec/serializers/blob_entity_spec.rb
+++ b/spec/serializers/blob_entity_spec.rb
@@ -23,7 +23,7 @@ describe BlobEntity do
mode: "100644",
readable_text: true,
icon: "file-text-o",
- url: "/#{project.full_path}/blob/master/bar/branch-test.txt"
+ url: "/#{project.full_path}/-/blob/master/bar/branch-test.txt"
})
end
end
diff --git a/spec/serializers/cluster_application_entity_spec.rb b/spec/serializers/cluster_application_entity_spec.rb
index cb9325986d7..c700c150461 100644
--- a/spec/serializers/cluster_application_entity_spec.rb
+++ b/spec/serializers/cluster_application_entity_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
describe ClusterApplicationEntity do
describe '#as_json' do
let(:application) { build(:clusters_applications_helm, version: '0.1.1') }
+
subject { described_class.new(application).as_json }
it 'has name' do
diff --git a/spec/serializers/cluster_entity_spec.rb b/spec/serializers/cluster_entity_spec.rb
index 22b9166f922..e3826a7221d 100644
--- a/spec/serializers/cluster_entity_spec.rb
+++ b/spec/serializers/cluster_entity_spec.rb
@@ -39,6 +39,7 @@ describe ClusterEntity do
context 'when no application has been installed' do
let(:cluster) { create(:cluster) }
+
subject { described_class.new(cluster).as_json[:applications]}
it 'contains helm as not_installable' do
diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb
index e4d1d7f9049..f392ecea959 100644
--- a/spec/serializers/environment_entity_spec.rb
+++ b/spec/serializers/environment_entity_spec.rb
@@ -9,6 +9,7 @@ describe EnvironmentEntity do
end
let(:environment) { create(:environment) }
+
subject { entity.as_json }
it 'exposes latest deployment' do
diff --git a/spec/serializers/group_child_entity_spec.rb b/spec/serializers/group_child_entity_spec.rb
index 198a55d5433..cae263e7fd5 100644
--- a/spec/serializers/group_child_entity_spec.rb
+++ b/spec/serializers/group_child_entity_spec.rb
@@ -9,6 +9,7 @@ describe GroupChildEntity do
let(:user) { create(:user) }
let(:request) { double('request') }
let(:entity) { described_class.new(object, request: request) }
+
subject(:json) { entity.as_json }
before do
diff --git a/spec/serializers/group_child_serializer_spec.rb b/spec/serializers/group_child_serializer_spec.rb
index 128e06cd172..92f083ed23e 100644
--- a/spec/serializers/group_child_serializer_spec.rb
+++ b/spec/serializers/group_child_serializer_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
describe GroupChildSerializer do
let(:request) { double('request') }
let(:user) { create(:user) }
+
subject(:serializer) { described_class.new(current_user: user) }
describe '#represent' do
diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb
index ea9052b4046..0593dd527cc 100644
--- a/spec/serializers/merge_request_poll_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb
@@ -60,7 +60,7 @@ describe MergeRequestPollWidgetEntity do
project.add_developer(user)
expect(subject[:new_blob_path])
- .to eq("/#{resource.project.full_path}/new/#{resource.source_branch}")
+ .to eq("/#{resource.project.full_path}/-/new/#{resource.source_branch}")
end
end
diff --git a/spec/serializers/note_entity_spec.rb b/spec/serializers/note_entity_spec.rb
index cec07cda063..f37fffb5048 100644
--- a/spec/serializers/note_entity_spec.rb
+++ b/spec/serializers/note_entity_spec.rb
@@ -10,6 +10,7 @@ describe NoteEntity do
let(:entity) { described_class.new(note, request: request) }
let(:note) { create(:note) }
let(:user) { create(:user) }
+
subject { entity.as_json }
it_behaves_like 'note entity'
diff --git a/spec/serializers/project_note_entity_spec.rb b/spec/serializers/project_note_entity_spec.rb
index 7c76f230781..469bf2b86de 100644
--- a/spec/serializers/project_note_entity_spec.rb
+++ b/spec/serializers/project_note_entity_spec.rb
@@ -10,6 +10,7 @@ describe ProjectNoteEntity do
let(:entity) { described_class.new(note, request: request) }
let(:note) { create(:note) }
let(:user) { create(:user) }
+
subject { entity.as_json }
it_behaves_like 'note entity'
diff --git a/spec/serializers/user_entity_spec.rb b/spec/serializers/user_entity_spec.rb
index edb49757b38..71107daf6ac 100644
--- a/spec/serializers/user_entity_spec.rb
+++ b/spec/serializers/user_entity_spec.rb
@@ -7,6 +7,7 @@ describe UserEntity do
let(:entity) { described_class.new(user) }
let(:user) { create(:user) }
+
subject { entity.as_json }
it 'exposes user name and login' do
diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index a3b527e0ffe..ad4ae93a027 100644
--- a/spec/support/helpers/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
@@ -351,7 +351,7 @@ module KubernetesHelpers
def kube_knative_services_body(**options)
{
"kind" => "List",
- "items" => [knative_07_service(options)]
+ "items" => [knative_09_service(options)]
}
end
@@ -540,6 +540,58 @@ module KubernetesHelpers
end
# noinspection RubyStringKeysInHashInspection
+ def knative_09_service(name: 'kubetest', namespace: 'default', domain: 'example.com', description: 'a knative service', environment: 'production')
+ { "apiVersion" => "serving.knative.dev/v1alpha1",
+ "kind" => "Service",
+ "metadata" =>
+ { "annotations" =>
+ { "serving.knative.dev/creator" => "system:serviceaccount:#{namespace}:#{namespace}-service-account",
+ "serving.knative.dev/lastModifier" => "system:serviceaccount:#{namespace}:#{namespace}-service-account" },
+ "creationTimestamp" => "2019-10-22T21:19:13Z",
+ "generation" => 1,
+ "labels" => { "service" => name },
+ "name" => name,
+ "namespace" => namespace,
+ "resourceVersion" => "289726",
+ "selfLink" => "/apis/serving.knative.dev/v1alpha1/namespaces/#{namespace}/services/#{name}",
+ "uid" => "988349fa-f511-11e9-9ea1-42010a80005e" },
+ "spec" => {
+ "template" => {
+ "metadata" => {
+ "annotations" => { "Description" => description },
+ "creationTimestamp" => "2019-10-22T21:19:12Z",
+ "labels" => { "service" => name }
+ },
+ "spec" => {
+ "containers" => [{
+ "env" =>
+ [{ "name" => "timestamp", "value" => "2019-10-22 21:19:12" }],
+ "image" => "image_name",
+ "name" => "user-container",
+ "resources" => {}
+ }],
+ "timeoutSeconds" => 300
+ }
+ },
+ "traffic" => [{ "latestRevision" => true, "percent" => 100 }]
+ },
+ "status" =>
+ { "address" => { "url" => "http://#{name}.#{namespace}.svc.cluster.local" },
+ "conditions" =>
+ [{ "lastTransitionTime" => "2019-10-22T21:20:15Z", "status" => "True", "type" => "ConfigurationsReady" },
+ { "lastTransitionTime" => "2019-10-22T21:20:15Z", "status" => "True", "type" => "Ready" },
+ { "lastTransitionTime" => "2019-10-22T21:20:15Z", "status" => "True", "type" => "RoutesReady" }],
+ "latestCreatedRevisionName" => "#{name}-92tsj",
+ "latestReadyRevisionName" => "#{name}-92tsj",
+ "observedGeneration" => 1,
+ "traffic" => [{ "latestRevision" => true, "percent" => 100, "revisionName" => "#{name}-92tsj" }],
+ "url" => "http://#{name}.#{namespace}.#{domain}" },
+ "environment_scope" => environment,
+ "cluster_id" => 5,
+ "podcount" => 0 }
+ end
+
+ # noinspection RubyStringKeysInHashInspection
def knative_05_service(name: 'kubetest', namespace: 'default', domain: 'example.com', description: 'a knative service', environment: 'production')
{ "apiVersion" => "serving.knative.dev/v1alpha1",
"kind" => "Service",
diff --git a/spec/support/shared_examples/policies/project_policy_shared_examples.rb b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
index 37f8bc14e20..1831fc10628 100644
--- a/spec/support/shared_examples/policies/project_policy_shared_examples.rb
+++ b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
@@ -152,6 +152,7 @@ end
RSpec.shared_examples 'project policies as developer' do
context 'abilities for non-public projects' do
let(:project) { create(:project, namespace: owner.namespace) }
+
subject { described_class.new(developer, project) }
it do
diff --git a/spec/uploaders/file_mover_spec.rb b/spec/uploaders/file_mover_spec.rb
index c4a315b3fd6..9f053f03b0e 100644
--- a/spec/uploaders/file_mover_spec.rb
+++ b/spec/uploaders/file_mover_spec.rb
@@ -22,6 +22,7 @@ describe FileMover do
end
let(:file) { fixture_file_upload('spec/fixtures/banana_sample.gif') }
+
subject { described_class.new(temp_file_path, from_model: user, to_model: snippet).execute }
describe '#execute' do
diff --git a/spec/validators/addressable_url_validator_spec.rb b/spec/validators/addressable_url_validator_spec.rb
index 6927a1f67a1..e8a44f7a12a 100644
--- a/spec/validators/addressable_url_validator_spec.rb
+++ b/spec/validators/addressable_url_validator_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe AddressableUrlValidator do
let!(:badge) { build(:badge, link_url: 'http://www.example.com') }
+
subject { validator.validate(badge) }
include_examples 'url validator examples', described_class::DEFAULT_OPTIONS[:schemes]
diff --git a/spec/validators/devise_email_validator_spec.rb b/spec/validators/devise_email_validator_spec.rb
index 7860b659bd3..1dbf3f66cfd 100644
--- a/spec/validators/devise_email_validator_spec.rb
+++ b/spec/validators/devise_email_validator_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe DeviseEmailValidator do
let!(:user) { build(:user, public_email: 'test@example.com') }
+
subject { validator.validate(user) }
describe 'validations' do
diff --git a/spec/views/help/index.html.haml_spec.rb b/spec/views/help/index.html.haml_spec.rb
index 474a294ce0d..98040da9d2c 100644
--- a/spec/views/help/index.html.haml_spec.rb
+++ b/spec/views/help/index.html.haml_spec.rb
@@ -40,7 +40,7 @@ describe 'help/index' do
render
expect(rendered).to match '8.0.2'
- expect(rendered).to have_link('abcdefg', href: %r{https://gitlab.com/gitlab-org/(gitlab|gitlab-foss)/commits/abcdefg})
+ expect(rendered).to have_link('abcdefg', href: %r{https://gitlab.com/gitlab-org/(gitlab|gitlab-foss)/-/commits/abcdefg})
end
end
end
diff --git a/spec/workers/expire_job_cache_worker_spec.rb b/spec/workers/expire_job_cache_worker_spec.rb
index 6ac285ca944..eeab304d926 100644
--- a/spec/workers/expire_job_cache_worker_spec.rb
+++ b/spec/workers/expire_job_cache_worker_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
describe ExpireJobCacheWorker do
set(:pipeline) { create(:ci_empty_pipeline) }
let(:project) { pipeline.project }
+
subject { described_class.new }
describe '#perform' do
diff --git a/spec/workers/expire_pipeline_cache_worker_spec.rb b/spec/workers/expire_pipeline_cache_worker_spec.rb
index 5652f5e8685..e162a227a66 100644
--- a/spec/workers/expire_pipeline_cache_worker_spec.rb
+++ b/spec/workers/expire_pipeline_cache_worker_spec.rb
@@ -6,6 +6,7 @@ describe ExpirePipelineCacheWorker do
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:pipeline) { create(:ci_pipeline, project: project) }
+
subject { described_class.new }
describe '#perform' do
diff --git a/spec/workers/mail_scheduler/notification_service_worker_spec.rb b/spec/workers/mail_scheduler/notification_service_worker_spec.rb
index 0729c5f9ffb..14a9f0ed8b7 100644
--- a/spec/workers/mail_scheduler/notification_service_worker_spec.rb
+++ b/spec/workers/mail_scheduler/notification_service_worker_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
describe MailScheduler::NotificationServiceWorker do
let(:worker) { described_class.new }
let(:method) { 'new_key' }
+
set(:key) { create(:personal_key) }
def serialize(*args)
diff --git a/spec/workers/repository_check/batch_worker_spec.rb b/spec/workers/repository_check/batch_worker_spec.rb
index 051c6a5d141..12e7d1879d0 100644
--- a/spec/workers/repository_check/batch_worker_spec.rb
+++ b/spec/workers/repository_check/batch_worker_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe RepositoryCheck::BatchWorker do
let(:shard_name) { 'default' }
+
subject { described_class.new }
before do
diff --git a/yarn.lock b/yarn.lock
index fbc6733fea4..aa45c5dc6b2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -278,6 +278,14 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-optional-catch-binding" "^7.2.0"
+"@babel/plugin-proposal-optional-chaining@^7.7.5":
+ version "7.7.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.7.5.tgz#f0835f044cef85b31071a924010a2a390add11d4"
+ integrity sha512-sOwFqT8JSchtJeDD+CjmWCaiFoLxY4Ps7NjvwHC/U7l4e9i5pTRNt8nDMIFSOUL+ncFbYSwruHM8WknYItWdXw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-syntax-optional-chaining" "^7.7.4"
+
"@babel/plugin-proposal-private-methods@^7.6.0":
version "7.6.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.6.0.tgz#19ddc493c7b5d47afdd4291e740c609a83c9fae4"
@@ -337,6 +345,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
+"@babel/plugin-syntax-optional-chaining@^7.7.4":
+ version "7.7.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.7.4.tgz#c91fdde6de85d2eb8906daea7b21944c3610c901"
+ integrity sha512-2MqYD5WjZSbJdUagnJvIdSfkb/ucOC9/1fRJxm7GAxY6YQLWlUvkfxoNbUPcPLHJyetKUDQ4+yyuUyAoc0HriA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
"@babel/plugin-transform-arrow-functions@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550"