diff options
24 files changed, 213 insertions, 393 deletions
diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue index 8ef31b9b983..9f6049b7b6d 100644 --- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue +++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue @@ -1,21 +1,11 @@ <script> -import { - GlForm, - GlIcon, - GlLink, - GlButton, - GlSprintf, - GlAlert, - GlModal, - GlModalDirective, -} from '@gitlab/ui'; +import { GlForm, GlIcon, GlLink, GlButton, GlSprintf, GlAlert } from '@gitlab/ui'; import axios from '~/lib/utils/axios_utils'; import csrf from '~/lib/utils/csrf'; import { setUrlFragment } from '~/lib/utils/url_utility'; import { __, s__, sprintf } from '~/locale'; import Tracking from '~/tracking'; import MarkdownField from '~/vue_shared/components/markdown/field.vue'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { CONTENT_EDITOR_LOADED_ACTION, SAVED_USING_CONTENT_EDITOR_ACTION, @@ -64,28 +54,6 @@ export default { ), primaryAction: s__('WikiPage|Retry'), }, - useNewEditor: { - primaryLabel: s__('WikiPage|Use the new editor'), - secondaryLabel: s__('WikiPage|Try this later'), - title: s__('WikiPage|Get a richer editing experience'), - text: s__( - "WikiPage|Try the new visual Markdown editor. Read the %{linkStart}documentation%{linkEnd} to learn what's currently supported.", - ), - }, - switchToOldEditor: { - label: s__('WikiPage|Switch me back to the classic editor.'), - helpText: s__( - "WikiPage|This editor is in beta and may not display the page's contents properly. Switching back to the classic editor will discard changes you've made in the new editor.", - ), - modal: { - title: s__('WikiPage|Are you sure you want to switch back to the classic editor?'), - primary: s__('WikiPage|Switch to classic editor'), - cancel: s__('WikiPage|Keep editing'), - text: s__( - "WikiPage|Switching to the classic editor will discard any changes you've made in the new editor.", - ), - }, - }, feedbackTip: __( 'Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}.', ), @@ -108,7 +76,6 @@ export default { editSourceButtonText: s__('WikiPage|Edit source'), editRichTextButtonText: s__('WikiPage|Edit rich text'), }, - contentEditorFeedbackIssue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332629', components: { GlAlert, GlForm, @@ -116,24 +83,19 @@ export default { GlIcon, GlLink, GlButton, - GlModal, MarkdownField, ContentEditor: () => import( /* webpackChunkName: 'content_editor' */ '~/content_editor/components/content_editor.vue' ), }, - directives: { - GlModalDirective, - }, - mixins: [trackingMixin, glFeatureFlagMixin()], + mixins: [trackingMixin], inject: ['formatOptions', 'pageInfo'], data() { return { title: this.pageInfo.title?.trim() || '', format: this.pageInfo.format || 'markdown', content: this.pageInfo.content || '', - isContentEditorAlertDismissed: false, useContentEditor: false, commitMessage: '', isDirty: false, @@ -194,25 +156,9 @@ export default { isMarkdownFormat() { return this.format === 'markdown'; }, - showContentEditorAlert() { - return ( - !this.glFeatures.wikiSwitchBetweenContentEditorRawMarkdown && - this.isMarkdownFormat && - !this.useContentEditor && - !this.isContentEditorAlertDismissed - ); - }, - showSwitchEditingModeButton() { - return this.glFeatures.wikiSwitchBetweenContentEditorRawMarkdown && this.isMarkdownFormat; - }, displayWikiSpecificMarkdownHelp() { return !this.isContentEditorActive; }, - displaySwitchBackToClassicEditorMessage() { - return ( - !this.glFeatures.wikiSwitchBetweenContentEditorRawMarkdown && this.isContentEditorActive - ); - }, disableSubmitButton() { return this.noContent || !this.title || this.contentEditorRenderFailed; }, @@ -312,23 +258,6 @@ export default { this.commitMessage = newCommitMessage; }, - initContentEditor() { - this.useContentEditor = true; - }, - - switchToOldEditor() { - this.useContentEditor = false; - }, - - confirmSwitchToOldEditor() { - if (this.contentEditorRenderFailed) { - this.contentEditorRenderFailed = false; - this.switchToOldEditor(); - } else { - this.$refs.confirmSwitchToOldEditorModal.show(); - } - }, - trackContentEditorLoaded() { this.track(CONTENT_EDITOR_LOADED_ACTION); }, @@ -349,10 +278,6 @@ export default { }, }); }, - - dismissContentEditorAlert() { - this.isContentEditorAlertDismissed = true; - }, }, }; </script> @@ -438,10 +363,7 @@ export default { }}</label> </div> <div class="col-sm-10"> - <div - v-if="showSwitchEditingModeButton" - class="gl-display-flex gl-justify-content-end gl-mb-3" - > + <div v-if="isMarkdownFormat" class="gl-display-flex gl-justify-content-end gl-mb-3"> <gl-button data-testid="toggle-editing-mode-button" data-qa-selector="editing_mode_button" @@ -451,42 +373,6 @@ export default { >{{ toggleEditingModeButtonText }}</gl-button > </div> - <gl-alert - v-if="showContentEditorAlert" - class="gl-mb-6" - variant="info" - data-qa-selector="try_new_editor_container" - :primary-button-text="$options.i18n.contentEditor.useNewEditor.primaryLabel" - :secondary-button-text="$options.i18n.contentEditor.useNewEditor.secondaryLabel" - :dismiss-label="$options.i18n.contentEditor.useNewEditor.secondaryLabel" - :title="$options.i18n.contentEditor.useNewEditor.title" - @primaryAction="initContentEditor" - @secondaryAction="dismissContentEditorAlert" - @dismiss="dismissContentEditorAlert" - > - <gl-sprintf :message="$options.i18n.contentEditor.useNewEditor.text"> - <template - #link="// eslint-disable-next-line vue/no-template-shadow - { content }" - ><gl-link - :href="contentEditorHelpPath" - target="_blank" - data-testid="content-editor-help-link" - >{{ content }}</gl-link - ></template - > - </gl-sprintf> - </gl-alert> - <gl-modal - ref="confirmSwitchToOldEditorModal" - modal-id="confirm-switch-to-old-editor" - :title="$options.i18n.contentEditor.switchToOldEditor.modal.title" - :action-primary="{ text: $options.i18n.contentEditor.switchToOldEditor.modal.primary }" - :action-cancel="{ text: $options.i18n.contentEditor.switchToOldEditor.modal.cancel }" - @primary="switchToOldEditor" - > - {{ $options.i18n.contentEditor.switchToOldEditor.modal.text }} - </gl-modal> <markdown-field v-if="!isContentEditorActive" :markdown-preview-path="pageInfo.markdownPreviewPath" @@ -516,7 +402,6 @@ export default { </textarea> </template> </markdown-field> - <div v-if="isContentEditorActive"> <gl-alert class="gl-mb-6" variant="tip" :dismissible="false"> <gl-sprintf :message="$options.i18n.contentEditor.feedbackTip"> @@ -560,12 +445,6 @@ export default { ></template > </gl-sprintf> - <span v-if="displaySwitchBackToClassicEditorMessage"> - {{ $options.i18n.contentEditor.switchToOldEditor.helpText }} - <gl-button variant="link" @click="confirmSwitchToOldEditor">{{ - $options.i18n.contentEditor.switchToOldEditor.label - }}</gl-button> - </span> </div> </div> </div> diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb index 51bfa06a623..e673ba501ff 100644 --- a/app/controllers/concerns/wiki_actions.rb +++ b/app/controllers/concerns/wiki_actions.rb @@ -21,10 +21,6 @@ module WikiActions before_action :load_sidebar, except: [:pages] before_action :set_content_class - before_action do - push_frontend_feature_flag(:wiki_switch_between_content_editor_raw_markdown, @group, default_enabled: :yaml) - end - before_action only: [:show, :edit, :update] do @valid_encoding = valid_encoding? end diff --git a/app/finders/bulk_imports/entities_finder.rb b/app/finders/bulk_imports/entities_finder.rb index 2947d155668..78446f104d0 100644 --- a/app/finders/bulk_imports/entities_finder.rb +++ b/app/finders/bulk_imports/entities_finder.rb @@ -2,10 +2,10 @@ module BulkImports class EntitiesFinder - def initialize(user:, bulk_import: nil, status: nil) + def initialize(user:, bulk_import: nil, params: {}) @user = user @bulk_import = bulk_import - @status = status + @params = params end def execute @@ -14,6 +14,7 @@ module BulkImports .by_user_id(user.id) .then(&method(:filter_by_bulk_import)) .then(&method(:filter_by_status)) + .then(&method(:sort)) end private @@ -23,13 +24,19 @@ module BulkImports def filter_by_bulk_import(entities) return entities unless bulk_import - entities.where(bulk_import_id: bulk_import.id) # rubocop: disable CodeReuse/ActiveRecord + entities.by_bulk_import_id(bulk_import.id) end def filter_by_status(entities) - return entities unless ::BulkImports::Entity.all_human_statuses.include?(status) + return entities unless ::BulkImports::Entity.all_human_statuses.include?(@params[:status]) - entities.with_status(status) + entities.with_status(@params[:status]) + end + + def sort(entities) + return entities unless @params[:sort] + + entities.order_by_created_at(@params[:sort]) end end end diff --git a/app/finders/bulk_imports/imports_finder.rb b/app/finders/bulk_imports/imports_finder.rb index b554bbfa5e7..d682080576f 100644 --- a/app/finders/bulk_imports/imports_finder.rb +++ b/app/finders/bulk_imports/imports_finder.rb @@ -2,13 +2,14 @@ module BulkImports class ImportsFinder - def initialize(user:, status: nil) + def initialize(user:, params: {}) @user = user - @status = status + @params = params end def execute - filter_by_status(user.bulk_imports) + imports = filter_by_status(user.bulk_imports) + sort(imports) end private @@ -16,9 +17,15 @@ module BulkImports attr_reader :user, :status def filter_by_status(imports) - return imports unless BulkImport.all_human_statuses.include?(status) + return imports unless BulkImport.all_human_statuses.include?(@params[:status]) - imports.with_status(status) + imports.with_status(@params[:status]) + end + + def sort(imports) + return imports unless @params[:sort] + + imports.order_by_created_at(@params[:sort]) end end end diff --git a/app/graphql/types/repository/blob_type.rb b/app/graphql/types/repository/blob_type.rb index 652e2882584..dd5c70887de 100644 --- a/app/graphql/types/repository/blob_type.rb +++ b/app/graphql/types/repository/blob_type.rb @@ -101,10 +101,6 @@ module Types description: 'Web path to blob on an environment.', calls_gitaly: true - field :code_owners, [Types::UserType], null: true, - description: 'List of code owners for the blob.', - calls_gitaly: true - field :file_type, GraphQL::Types::String, null: true, description: 'Expected format of the blob based on the extension.' diff --git a/app/models/bulk_import.rb b/app/models/bulk_import.rb index fd0ca332dc6..2200a66b3c2 100644 --- a/app/models/bulk_import.rb +++ b/app/models/bulk_import.rb @@ -17,6 +17,7 @@ class BulkImport < ApplicationRecord enum source_type: { gitlab: 0 } scope :stale, -> { where('created_at < ?', 8.hours.ago).where(status: [0, 1]) } + scope :order_by_created_at, -> (direction) { order(created_at: direction) } state_machine :status, initial: :created do state :created, value: 0 diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb index f998aea91a1..edead35bafe 100644 --- a/app/models/bulk_imports/entity.rb +++ b/app/models/bulk_imports/entity.rb @@ -52,6 +52,8 @@ class BulkImports::Entity < ApplicationRecord scope :by_user_id, ->(user_id) { joins(:bulk_import).where(bulk_imports: { user_id: user_id }) } scope :stale, -> { where('created_at < ?', 8.hours.ago).where(status: [0, 1]) } + scope :by_bulk_import_id, ->(bulk_import_id) { where(bulk_import_id: bulk_import_id)} + scope :order_by_created_at, -> (direction) { order(created_at: direction) } state_machine :status, initial: :created do state :created, value: 0 diff --git a/config/feature_flags/development/wiki_switch_between_content_editor_raw_markdown.yml b/config/feature_flags/development/wiki_switch_between_content_editor_raw_markdown.yml deleted file mode 100644 index dbdf2d616d2..00000000000 --- a/config/feature_flags/development/wiki_switch_between_content_editor_raw_markdown.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: wiki_switch_between_content_editor_raw_markdown -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74457 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345398 -milestone: '14.6' -type: development -group: group::editor -default_enabled: true diff --git a/doc/api/bulk_imports.md b/doc/api/bulk_imports.md index 2b71c83b224..cae23b35fbe 100644 --- a/doc/api/bulk_imports.md +++ b/doc/api/bulk_imports.md @@ -58,11 +58,12 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla GET /bulk_imports ``` -| Attribute | Type | Required | Description | -|:-----------|:--------|:---------|:---------------------------------------| -| `per_page` | integer | no | Number of records to return per page. | -| `page` | integer | no | Page to retrieve. | -| `status` | string | no | Import status. | +| Attribute | Type | Required | Description | +|:-----------|:--------|:---------|:--------------------------------------------------------------------------------------------| +| `per_page` | integer | no | Number of records to return per page. | +| `page` | integer | no | Page to retrieve. | +| `sort` | string | no | Return GitLab migration sorted in `asc` or `desc` order by creation date. Default is `desc` | +| `status` | string | no | Import status. | The status can be one of the following: @@ -100,11 +101,12 @@ curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab GET /bulk_imports/entities ``` -| Attribute | Type | Required | Description | -|:-----------|:--------|:---------|:---------------------------------------| -| `per_page` | integer | no | Number of records to return per page. | -| `page` | integer | no | Page to retrieve. | -| `status` | string | no | Import status. | +| Attribute | Type | Required | Description | +|:-----------|:--------|:---------|:-----------------------------------------------------------------------------------------------------| +| `per_page` | integer | no | Number of records to return per page. | +| `page` | integer | no | Page to retrieve. | +| `sort` | string | no | Return GitLab migration entities sorted in `asc` or `desc` order by creation date. Default is `desc` | +| `status` | string | no | Import status. | The status can be one of the following: @@ -184,11 +186,12 @@ curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab GET /bulk_imports/:id/entities ``` -| Attribute | Type | Required | Description | -|:-----------|:--------|:---------|:---------------------------------------| -| `per_page` | integer | no | Number of records to return per page. | -| `page` | integer | no | Page to retrieve. | -| `status` | string | no | Import status. | +| Attribute | Type | Required | Description | +|:-----------|:--------|:---------|:--------------------------------------------------------------------------------------------| +| `per_page` | integer | no | Number of records to return per page. | +| `page` | integer | no | Page to retrieve. | +| `sort` | string | no | Return GitLab migration sorted in `asc` or `desc` order by creation date. Default is `desc` | +| `status` | string | no | Import status. | The status can be one of the following: diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md index fd6c39ffbf1..3222d5d0ec1 100644 --- a/doc/user/application_security/dast/index.md +++ b/doc/user/application_security/dast/index.md @@ -1053,7 +1053,7 @@ To run an on-demand scan either at a scheduled date or frequency, read 1. From your project's home page, go to **Security & Compliance > On-demand Scans** in the left sidebar. -1. Select **New DAST scan**. +1. Select **New scan**. 1. Complete the **Scan name** and **Description** fields. 1. In GitLab 13.10 and later, select the desired branch from the **Branch** dropdown. 1. In **Scanner profile**, select a scanner profile from the dropdown. @@ -1088,7 +1088,7 @@ To schedule a scan: 1. On the top bar, select **Menu > Projects** and find your project. 1. On the left sidebar, select **Security & Compliance > On-demand Scans**. -1. Select **New DAST scan**. +1. Select **New scan**. 1. Complete the **Scan name** and **Description** text boxes. 1. In GitLab 13.10 and later, from the **Branch** dropdown list, select the desired branch. 1. In the **Scanner profile** section, from the dropdown list, select a scanner profile. diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md index 33f6c32d334..7d155ea9b06 100644 --- a/doc/user/project/wiki/index.md +++ b/doc/user/project/wiki/index.md @@ -327,13 +327,7 @@ to disable the wiki but toggle it on (in blue). > - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5643) in GitLab 14.0. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345398) switching between editing experiences in GitLab 14.7 [with a flag](../../../administration/feature_flags.md) named `wiki_switch_between_content_editor_raw_markdown`. Enabled by default. - -FLAG: -On self-managed GitLab, by default this feature is available. -To hide the feature, ask an administrator to -[disable the feature flag](../../../administration/feature_flags.md) named -`wiki_switch_between_content_editor_raw_markdown`. -On GitLab.com, this feature is available. +> - Switching between editing experiences generally available in GitLab 14.10. [Feature flag `wiki_switch_between_content_editor_raw_markdown`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83760) removed. GitLab version 14.0 introduces a WYSIWYG editing experience for GitLab Flavored Markdown in Wikis through the [Content Editor](../../../development/fe_guide/content_editor.md). diff --git a/lib/api/bulk_imports.rb b/lib/api/bulk_imports.rb index c732da17166..53967e0af5d 100644 --- a/lib/api/bulk_imports.rb +++ b/lib/api/bulk_imports.rb @@ -10,7 +10,7 @@ module API def bulk_imports @bulk_imports ||= ::BulkImports::ImportsFinder.new( user: current_user, - status: params[:status] + params: params ).execute end @@ -22,7 +22,7 @@ module API @bulk_import_entities ||= ::BulkImports::EntitiesFinder.new( user: current_user, bulk_import: bulk_import, - status: params[:status] + params: params ).execute end @@ -70,6 +70,8 @@ module API end params do use :pagination + optional :sort, type: String, values: %w[asc desc], default: 'desc', + desc: 'Return GitLab Migrations sorted in created by `asc` or `desc` order.' optional :status, type: String, values: BulkImport.all_human_statuses, desc: 'Return GitLab Migrations with specified status' end @@ -82,13 +84,15 @@ module API end params do use :pagination + optional :sort, type: String, values: %w[asc desc], default: 'desc', + desc: 'Return GitLab Migrations sorted in created by `asc` or `desc` order.' optional :status, type: String, values: ::BulkImports::Entity.all_human_statuses, desc: "Return all GitLab Migrations' entities with specified status" end get :entities do entities = ::BulkImports::EntitiesFinder.new( user: current_user, - status: params[:status] + params: params ).execute present paginate(entities), with: Entities::BulkImports::Entity diff --git a/lib/gitlab/graphql/project/dast_profile_connection_extension.rb b/lib/gitlab/graphql/project/dast_profile_connection_extension.rb index a3c3f2f2b7e..45f90de2f17 100644 --- a/lib/gitlab/graphql/project/dast_profile_connection_extension.rb +++ b/lib/gitlab/graphql/project/dast_profile_connection_extension.rb @@ -2,7 +2,7 @@ module Gitlab module Graphql module Project - class DastProfileConnectionExtension < GraphQL::Schema::Field::ConnectionExtension + class DastProfileConnectionExtension < GraphQL::Schema::FieldExtension def after_resolve(value:, object:, context:, **rest) preload_authorizations(context[:project_dast_profiles]) context[:project_dast_profiles] = nil diff --git a/locale/gitlab.pot b/locale/gitlab.pot index a5e32bfe7bc..d85a2767f06 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -25953,10 +25953,10 @@ msgstr "" msgid "OnDemandScans|My daily scan" msgstr "" -msgid "OnDemandScans|New DAST scan" +msgid "OnDemandScans|New on-demand DAST scan" msgstr "" -msgid "OnDemandScans|New on-demand DAST scan" +msgid "OnDemandScans|New scan" msgstr "" msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed scanner profile." @@ -42283,9 +42283,6 @@ msgstr "" msgid "WikiPage|An error occurred while trying to render the content editor. Please try again later." msgstr "" -msgid "WikiPage|Are you sure you want to switch back to the classic editor?" -msgstr "" - msgid "WikiPage|Cancel" msgstr "" @@ -42310,12 +42307,6 @@ msgstr "" msgid "WikiPage|Format" msgstr "" -msgid "WikiPage|Get a richer editing experience" -msgstr "" - -msgid "WikiPage|Keep editing" -msgstr "" - msgid "WikiPage|Learn more." msgstr "" @@ -42328,18 +42319,6 @@ msgstr "" msgid "WikiPage|Save changes" msgstr "" -msgid "WikiPage|Switch me back to the classic editor." -msgstr "" - -msgid "WikiPage|Switch to classic editor" -msgstr "" - -msgid "WikiPage|Switching to the classic editor will discard any changes you've made in the new editor." -msgstr "" - -msgid "WikiPage|This editor is in beta and may not display the page's contents properly. Switching back to the classic editor will discard changes you've made in the new editor." -msgstr "" - msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title." msgstr "" @@ -42352,18 +42331,9 @@ msgstr "" msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}." msgstr "" -msgid "WikiPage|Try the new visual Markdown editor. Read the %{linkStart}documentation%{linkEnd} to learn what's currently supported." -msgstr "" - -msgid "WikiPage|Try this later" -msgstr "" - msgid "WikiPage|Update %{pageTitle}" msgstr "" -msgid "WikiPage|Use the new editor" -msgstr "" - msgid "WikiPage|Write your content or drag files hereā¦" msgstr "" diff --git a/qa/qa/page/component/wiki_page_form.rb b/qa/qa/page/component/wiki_page_form.rb index 8f504b784b2..74b6c6b2d5e 100644 --- a/qa/qa/page/component/wiki_page_form.rb +++ b/qa/qa/page/component/wiki_page_form.rb @@ -14,7 +14,6 @@ module QA element :wiki_content_textarea element :wiki_message_textbox element :wiki_submit_button - element :try_new_editor_container element :editing_mode_button end diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb index 1a09a3e8e59..18a30ee0e49 100644 --- a/qa/qa/resource/project.rb +++ b/qa/qa/resource/project.rb @@ -105,7 +105,16 @@ module QA def fabricate_via_api! resource_web_url(api_get) rescue ResourceNotFoundError - super + response = super + + # If a project is being imported, wait until it completes before we let the test continue. + # Otherwise we see Git repository errors + # See https://gitlab.com/gitlab-org/gitlab/-/issues/356101 + Support::Retrier.retry_until(max_duration: 60, sleep_interval: 5) do + %w[none finished].include?(reload!.api_resource[:import_status]) + end + + response end def api_get_path diff --git a/qa/qa/specs/features/api/3_create/repository/commit_to_templated_project_spec.rb b/qa/qa/specs/features/api/3_create/repository/commit_to_templated_project_spec.rb new file mode 100644 index 00000000000..fdac28693e0 --- /dev/null +++ b/qa/qa/specs/features/api/3_create/repository/commit_to_templated_project_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + describe 'Create a new project from a template' do + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'templated-project' + project.template_name = 'dotnetcore' + end + end + + it 'commits via the api' do + expect do + Resource::Repository::Commit.fabricate_via_api! do |commit| + commit.project = project + commit.update_files( + [ + { + file_path: '.gitlab-ci.yml', + content: 'script' + } + ] + ) + commit.add_files( + [ + { + file_path: 'foo', + content: 'bar' + } + ] + ) + end + end.not_to raise_exception + end + end + end +end diff --git a/spec/finders/bulk_imports/entities_finder_spec.rb b/spec/finders/bulk_imports/entities_finder_spec.rb index e053011b60d..54c792cb4d8 100644 --- a/spec/finders/bulk_imports/entities_finder_spec.rb +++ b/spec/finders/bulk_imports/entities_finder_spec.rb @@ -51,7 +51,7 @@ RSpec.describe BulkImports::EntitiesFinder do end context 'when status is specified' do - subject { described_class.new(user: user, status: 'failed') } + subject { described_class.new(user: user, params: { status: 'failed' }) } it 'returns a list of import entities filtered by status' do expect(subject.execute) @@ -61,7 +61,7 @@ RSpec.describe BulkImports::EntitiesFinder do end context 'when invalid status is specified' do - subject { described_class.new(user: user, status: 'invalid') } + subject { described_class.new(user: user, params: { status: 'invalid' }) } it 'does not filter entities by status' do expect(subject.execute) @@ -74,11 +74,37 @@ RSpec.describe BulkImports::EntitiesFinder do end context 'when bulk import and status are specified' do - subject { described_class.new(user: user, bulk_import: user_import_2, status: 'finished') } + subject { described_class.new(user: user, bulk_import: user_import_2, params: { status: 'finished' }) } it 'returns matched import entities' do expect(subject.execute).to contain_exactly(finished_entity_2) end end + + context 'when order is specifed' do + subject { described_class.new(user: user, params: { sort: order }) } + + context 'when order is specified as asc' do + let(:order) { :asc } + + it 'returns entities sorted ascending' do + expect(subject.execute).to eq([ + started_entity_1, finished_entity_1, failed_entity_1, + started_entity_2, finished_entity_2, failed_entity_2 + ]) + end + end + + context 'when order is specified as desc' do + let(:order) { :desc } + + it 'returns entities sorted descending' do + expect(subject.execute).to eq([ + failed_entity_2, finished_entity_2, started_entity_2, + failed_entity_1, finished_entity_1, started_entity_1 + ]) + end + end + end end end diff --git a/spec/finders/bulk_imports/imports_finder_spec.rb b/spec/finders/bulk_imports/imports_finder_spec.rb index aac83c86c84..2f550514a33 100644 --- a/spec/finders/bulk_imports/imports_finder_spec.rb +++ b/spec/finders/bulk_imports/imports_finder_spec.rb @@ -16,19 +16,39 @@ RSpec.describe BulkImports::ImportsFinder do end context 'when status is specified' do - subject { described_class.new(user: user, status: 'started') } + subject { described_class.new(user: user, params: { status: 'started' }) } it 'returns a list of import entities filtered by status' do expect(subject.execute).to contain_exactly(started_import) end context 'when invalid status is specified' do - subject { described_class.new(user: user, status: 'invalid') } + subject { described_class.new(user: user, params: { status: 'invalid' }) } it 'does not filter entities by status' do expect(subject.execute).to contain_exactly(started_import, finished_import) end end end + + context 'when order is specifed' do + subject { described_class.new(user: user, params: { sort: order }) } + + context 'when order is specified as asc' do + let(:order) { :asc } + + it 'returns entities sorted ascending' do + expect(subject.execute).to eq([started_import, finished_import]) + end + end + + context 'when order is specified as desc' do + let(:order) { :desc } + + it 'returns entities sorted descending' do + expect(subject.execute).to eq([finished_import, started_import]) + end + end + end end end diff --git a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js index e118a35804f..e20640da609 100644 --- a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js +++ b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js @@ -1,5 +1,5 @@ import { nextTick } from 'vue'; -import { GlLoadingIcon, GlModal, GlAlert, GlButton } from '@gitlab/ui'; +import { GlAlert, GlButton } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; @@ -32,11 +32,7 @@ describe('WikiForm', () => { const findMessage = () => wrapper.find('#wiki_message'); const findSubmitButton = () => wrapper.findByTestId('wiki-submit-button'); const findCancelButton = () => wrapper.findByTestId('wiki-cancel-button'); - const findUseNewEditorButton = () => wrapper.findByText('Use the new editor'); const findToggleEditingModeButton = () => wrapper.findByTestId('toggle-editing-mode-button'); - const findDismissContentEditorAlertButton = () => wrapper.findByText('Try this later'); - const findSwitchToOldEditorButton = () => - wrapper.findByRole('button', { name: 'Switch me back to the classic editor.' }); const findTitleHelpLink = () => wrapper.findByText('Learn more.'); const findMarkdownHelpLink = () => wrapper.findByTestId('wiki-markdown-help-link'); const findContentEditor = () => wrapper.findComponent(ContentEditor); @@ -293,27 +289,21 @@ describe('WikiForm', () => { ); }); - describe('when wikiSwitchBetweenContentEditorRawMarkdown feature flag is not enabled', () => { + describe('toggle editing mode control', () => { beforeEach(() => { - createWrapper({ - glFeatures: { wikiSwitchBetweenContentEditorRawMarkdown: false }, - }); - }); - - it('hides toggle editing mode button', () => { - expect(findToggleEditingModeButton().exists()).toBe(false); - }); - }); - - describe('when wikiSwitchBetweenContentEditorRawMarkdown feature flag is enabled', () => { - beforeEach(() => { - createWrapper({ - glFeatures: { wikiSwitchBetweenContentEditorRawMarkdown: true }, - }); + createWrapper(); }); - it('hides gl-alert containing "use new editor" button', () => { - expect(findUseNewEditorButton().exists()).toBe(false); + it.each` + format | enabled | action + ${'markdown'} | ${true} | ${'displays'} + ${'rdoc'} | ${false} | ${'hides'} + ${'asciidoc'} | ${false} | ${'hides'} + ${'org'} | ${false} | ${'hides'} + `('$action toggle editing mode button when format is $format', async ({ format, enabled }) => { + await setFormat(format); + + expect(findToggleEditingModeButton().exists()).toBe(enabled); }); it('displays toggle editing mode button', () => { @@ -326,8 +316,8 @@ describe('WikiForm', () => { }); describe('when clicking the toggle editing mode button', () => { - beforeEach(() => { - findToggleEditingModeButton().vm.$emit('click'); + beforeEach(async () => { + await findToggleEditingModeButton().trigger('click'); }); it('hides the classic editor', () => { @@ -343,17 +333,13 @@ describe('WikiForm', () => { describe('when content editor is active', () => { let mockContentEditor; - beforeEach(() => { + beforeEach(async () => { mockContentEditor = { getSerializedContent: jest.fn(), setSerializedContent: jest.fn(), }; - findToggleEditingModeButton().vm.$emit('click'); - }); - - it('hides switch to old editor button', () => { - expect(findSwitchToOldEditorButton().exists()).toBe(false); + await findToggleEditingModeButton().trigger('click'); }); it('displays "Edit source" label in the toggle editing mode button', () => { @@ -363,13 +349,13 @@ describe('WikiForm', () => { describe('when clicking the toggle editing mode button', () => { const contentEditorFakeSerializedContent = 'fake content'; - beforeEach(() => { + beforeEach(async () => { mockContentEditor.getSerializedContent.mockReturnValueOnce( contentEditorFakeSerializedContent, ); findContentEditor().vm.$emit('initialized', mockContentEditor); - findToggleEditingModeButton().vm.$emit('click'); + await findToggleEditingModeButton().trigger('click'); }); it('hides the content editor', () => { @@ -388,75 +374,12 @@ describe('WikiForm', () => { }); describe('wiki content editor', () => { - it.each` - format | buttonExists - ${'markdown'} | ${true} - ${'rdoc'} | ${false} - `( - 'gl-alert containing "use new editor" button exists: $buttonExists if format is $format', - async ({ format, buttonExists }) => { - createWrapper(); - - await setFormat(format); - - expect(findUseNewEditorButton().exists()).toBe(buttonExists); - }, - ); - - it('gl-alert containing "use new editor" button is dismissed on clicking dismiss button', async () => { - createWrapper(); - - await findDismissContentEditorAlertButton().trigger('click'); - - expect(findUseNewEditorButton().exists()).toBe(false); - }); - - const assertOldEditorIsVisible = () => { - expect(findContentEditor().exists()).toBe(false); - expect(findClassicEditor().exists()).toBe(true); - expect(findSubmitButton().props('disabled')).toBe(false); - - expect(wrapper.text()).not.toContain( - "Switching will discard any changes you've made in the new editor.", - ); - expect(wrapper.text()).not.toContain( - "This editor is in beta and may not display the page's contents properly.", - ); - }; - - it('shows classic editor by default', () => { - createWrapper({ persisted: true }); - - assertOldEditorIsVisible(); - }); - - describe('switch format to rdoc', () => { - beforeEach(async () => { - createWrapper({ persisted: true }); - - await setFormat('rdoc'); - }); - - it('continues to show the classic editor', assertOldEditorIsVisible); - - describe('switch format back to markdown', () => { - beforeEach(async () => { - await setFormat('markdown'); - }); - - it( - 'still shows the classic editor and does not automatically switch to the content editor ', - assertOldEditorIsVisible, - ); - }); - }); - describe('clicking "use new editor": editor fails to load', () => { beforeEach(async () => { createWrapper({ mountFn: mount }); mock.onPost(/preview-markdown/).reply(400); - await findUseNewEditorButton().trigger('click'); + await findToggleEditingModeButton().trigger('click'); // try waiting for content editor to load (but it will never actually load) await waitForPromises(); @@ -466,14 +389,14 @@ describe('WikiForm', () => { expect(findSubmitButton().props('disabled')).toBe(true); }); - describe('clicking "switch to classic editor"', () => { + describe('toggling editing modes to the classic editor', () => { beforeEach(() => { - return findSwitchToOldEditorButton().trigger('click'); + return findToggleEditingModeButton().trigger('click'); }); - it('switches to classic editor directly without showing a modal', () => { - expect(wrapper.findComponent(ContentEditor).exists()).toBe(false); - expect(wrapper.findComponent(MarkdownField).exists()).toBe(true); + it('switches to classic editor', () => { + expect(findContentEditor().exists()).toBe(false); + expect(findClassicEditor().exists()).toBe(true); }); }); }); @@ -484,31 +407,19 @@ describe('WikiForm', () => { mock.onPost(/preview-markdown/).reply(200, { body: '<p>hello <strong>world</strong></p>' }); - await findUseNewEditorButton().trigger('click'); + await findToggleEditingModeButton().trigger('click'); + await waitForPromises(); }); it('shows a tip to send feedback', () => { expect(wrapper.text()).toContain('Tell us your experiences with the new Markdown editor'); }); - it('shows warnings that the rich text editor is in beta and may not work properly', () => { - expect(wrapper.text()).toContain( - "This editor is in beta and may not display the page's contents properly.", - ); - }); - it('shows the rich text editor when loading finishes', async () => { - // wait for content editor to load - await waitForPromises(); - - expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false); - expect(wrapper.findComponent(ContentEditor).exists()).toBe(true); + expect(findContentEditor().exists()).toBe(true); }); it('sends tracking event when editor loads', async () => { - // wait for content editor to load - await waitForPromises(); - expect(trackingSpy).toHaveBeenCalledWith(undefined, CONTENT_EDITOR_LOADED_ACTION, { label: WIKI_CONTENT_EDITOR_TRACKING_LABEL, }); @@ -564,49 +475,6 @@ describe('WikiForm', () => { expect(findContent().element.value).toBe('hello **world**'); }); }); - - describe('clicking "switch to classic editor"', () => { - let modal; - - beforeEach(async () => { - modal = wrapper.findComponent(GlModal); - jest.spyOn(modal.vm, 'show'); - - findSwitchToOldEditorButton().trigger('click'); - }); - - it('shows a modal confirming the change', () => { - expect(modal.vm.show).toHaveBeenCalled(); - }); - - describe('confirming "switch to classic editor" in the modal', () => { - beforeEach(async () => { - wrapper.vm.contentEditor.tiptapEditor.commands.setContent( - '<p>hello __world__ from content editor</p>', - true, - ); - - wrapper.findComponent(GlModal).vm.$emit('primary'); - - await nextTick(); - }); - - it('switches to classic editor', () => { - expect(wrapper.findComponent(ContentEditor).exists()).toBe(false); - expect(wrapper.findComponent(MarkdownField).exists()).toBe(true); - }); - - it('does not show a warning about content editor', () => { - expect(wrapper.text()).not.toContain( - "This editor is in beta and may not display the page's contents properly.", - ); - }); - - it('the classic editor retains its old value and does not use the content from the content editor', () => { - expect(findContent().element.value).toBe(' My page content '); - }); - }); - }); }); }); }); diff --git a/spec/graphql/types/range_input_type_spec.rb b/spec/graphql/types/range_input_type_spec.rb index fc9126247fa..dbfcf4a41c7 100644 --- a/spec/graphql/types/range_input_type_spec.rb +++ b/spec/graphql/types/range_input_type_spec.rb @@ -24,7 +24,7 @@ RSpec.describe ::Types::RangeInputType do it 'follows expected subtyping relationships for instances' do context = GraphQL::Query::Context.new( - query: double('query', schema: nil), + query: GraphQL::Query.new(GitlabSchema), values: {}, object: nil ) diff --git a/spec/graphql/types/repository/blob_type_spec.rb b/spec/graphql/types/repository/blob_type_spec.rb index a813ef85e6e..787b5f4a311 100644 --- a/spec/graphql/types/repository/blob_type_spec.rb +++ b/spec/graphql/types/repository/blob_type_spec.rb @@ -34,7 +34,6 @@ RSpec.describe Types::Repository::BlobType do :environment_external_url_for_route_map, :code_navigation_path, :project_blob_path_root, - :code_owners, :simple_viewer, :rich_viewer, :plain_data, @@ -47,6 +46,6 @@ RSpec.describe Types::Repository::BlobType do :ide_fork_and_edit_path, :fork_and_view_path, :language - ) + ).at_least end end diff --git a/spec/requests/api/bulk_imports_spec.rb b/spec/requests/api/bulk_imports_spec.rb index 1602819a02e..3b8136f265b 100644 --- a/spec/requests/api/bulk_imports_spec.rb +++ b/spec/requests/api/bulk_imports_spec.rb @@ -18,6 +18,29 @@ RSpec.describe API::BulkImports do expect(response).to have_gitlab_http_status(:ok) expect(json_response.pluck('id')).to contain_exactly(import_1.id, import_2.id) end + + context 'sort parameter' do + it 'sorts by created_at descending by default' do + get api('/bulk_imports', user) + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response.pluck('id')).to eq([import_2.id, import_1.id]) + end + + it 'sorts by created_at descending when explicitly specified' do + get api('/bulk_imports', user), params: { sort: 'desc' } + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response.pluck('id')).to eq([import_2.id, import_1.id]) + end + + it 'sorts by created_at ascending when explicitly specified' do + get api('/bulk_imports', user), params: { sort: 'asc' } + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response.pluck('id')).to eq([import_1.id, import_2.id]) + end + end end describe 'POST /bulk_imports' do diff --git a/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb index 85490bffc0e..12a4c6d7583 100644 --- a/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb +++ b/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb @@ -145,19 +145,6 @@ RSpec.shared_examples 'User updates wiki page' do it_behaves_like 'edits content using the content editor' end - - context 'with feature flag off' do - before do - stub_feature_flags(wiki_switch_between_content_editor_raw_markdown: false) - visit(wiki_path(wiki)) - - click_link('Edit') - - click_button 'Use the new editor' - end - - it_behaves_like 'edits content using the content editor' - end end end |