From e9626c2383e1bbf325a302bb840891c3c7b8cb07 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Fri, 13 Aug 2021 06:10:15 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .../components/content_editor.vue | 7 ++- .../components/toolbar_image_button.vue | 1 + .../toolbar_text_style_dropdown.vue | 3 ++ .../shared/wikis/components/wiki_form.vue | 1 + .../json_format_actions_support.rb | 2 +- .../counts_28d/20210216181158_epics.yml | 13 +++-- .../counts_all/20210216181134_epics.yml | 13 +++-- doc/api/index.md | 6 ++- doc/api/oauth2.md | 44 +++++++++++++++ doc/api/users.md | 2 +- doc/ci/lint.md | 4 +- doc/ci/pipelines/index.md | 16 +++--- .../testing_guide/best_practices.md | 6 ++- qa/qa.rb | 1 + qa/qa/page/component/content_editor.rb | 54 +++++++++++++++++++ qa/qa/page/component/wiki.rb | 12 +++++ qa/qa/page/component/wiki_page_form.rb | 7 +++ qa/qa/page/project/wiki/edit.rb | 1 + .../3_create/wiki/content_editor_spec.rb | 43 +++++++++++++++ 19 files changed, 206 insertions(+), 30 deletions(-) create mode 100644 qa/qa/page/component/content_editor.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb diff --git a/app/assets/javascripts/content_editor/components/content_editor.vue b/app/assets/javascripts/content_editor/components/content_editor.vue index 965fcc6ce79..a372233e543 100644 --- a/app/assets/javascripts/content_editor/components/content_editor.vue +++ b/app/assets/javascripts/content_editor/components/content_editor.vue @@ -93,7 +93,12 @@ export default {
-
+
diff --git a/app/assets/javascripts/content_editor/components/toolbar_image_button.vue b/app/assets/javascripts/content_editor/components/toolbar_image_button.vue index 6d970b27705..649e23c29aa 100644 --- a/app/assets/javascripts/content_editor/components/toolbar_image_button.vue +++ b/app/assets/javascripts/content_editor/components/toolbar_image_button.vue @@ -98,6 +98,7 @@ export default { name="content_editor_image" :accept="$options.acceptedMimes" class="gl-display-none" + data-qa-selector="file_upload_field" @change="onFileSelect" /> diff --git a/app/assets/javascripts/content_editor/components/toolbar_text_style_dropdown.vue b/app/assets/javascripts/content_editor/components/toolbar_text_style_dropdown.vue index 1bcad5a4c6d..13728d4001d 100644 --- a/app/assets/javascripts/content_editor/components/toolbar_text_style_dropdown.vue +++ b/app/assets/javascripts/content_editor/components/toolbar_text_style_dropdown.vue @@ -61,6 +61,7 @@ export default { @@ -69,6 +70,8 @@ export default { :key="index" is-check-item :is-checked="isActive(item)" + data-qa-selector="text_style_menu_item" + :data-qa-text-style="item.label" @click="execute(item)" > {{ item.label }} 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 68865281b27..a8ec731e105 100644 --- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue +++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue @@ -397,6 +397,7 @@ export default { 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" diff --git a/app/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support.rb b/app/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support.rb index 9fa448a9abb..0bfea05abc7 100644 --- a/app/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support.rb +++ b/app/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support.rb @@ -18,7 +18,7 @@ module SpammableActions::CaptchaCheck::JsonFormatActionsSupport def with_captcha_check_json_format(&block) # NOTE: "409 - Conflict" seems to be the most appropriate HTTP status code for a response # which requires a CAPTCHA to be solved in order for the request to be resubmitted. - # See https://stackoverflow.com/q/26547466/25192 + # https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10 captcha_render_lambda = -> { render json: spam_action_response_fields(spammable), status: :conflict } with_captcha_check_common(captcha_render_lambda: captcha_render_lambda, &block) end diff --git a/config/metrics/counts_28d/20210216181158_epics.yml b/config/metrics/counts_28d/20210216181158_epics.yml index db7e8870c6a..4a896092194 100644 --- a/config/metrics/counts_28d/20210216181158_epics.yml +++ b/config/metrics/counts_28d/20210216181158_epics.yml @@ -1,20 +1,19 @@ --- data_category: Optional key_path: usage_activity_by_stage_monthly.plan.epics -description: +description: Count distinct author ids from epics product_section: dev -product_stage: +product_stage: plan product_group: group::plan -product_category: +product_category: epics value_type: number status: data_available time_frame: 28d -data_source: +data_source: database distribution: -- ce +- ee tier: -- free -skip_validation: true +- premium performance_indicator_type: - gmau - paid_gmau diff --git a/config/metrics/counts_all/20210216181134_epics.yml b/config/metrics/counts_all/20210216181134_epics.yml index 8b87f64a4e1..ec43965b4fb 100644 --- a/config/metrics/counts_all/20210216181134_epics.yml +++ b/config/metrics/counts_all/20210216181134_epics.yml @@ -1,17 +1,16 @@ --- data_category: Operational key_path: usage_activity_by_stage.plan.epics -description: +description: Count distinct author ids from epics product_section: dev -product_stage: +product_stage: plan product_group: group::plan -product_category: +product_category: epics value_type: number status: data_available time_frame: all -data_source: +data_source: database distribution: -- ce +- ee tier: -- free -skip_validation: true +- premium diff --git a/doc/api/index.md b/doc/api/index.md index 4048a27b81f..12d01828803 100644 --- a/doc/api/index.md +++ b/doc/api/index.md @@ -167,7 +167,11 @@ curl --header "Authorization: Bearer OAUTH-TOKEN" "https://gitlab.example.com/ap Read more about [GitLab as an OAuth2 provider](oauth2.md). NOTE: -We recommend that OAuth access tokens have an expiration. You can use a `refresh_token` to refresh tokens. Integrations may need to be updated to refresh tokens prior to expiration, which is based on the [expires_in](https://datatracker.ietf.org/doc/html/rfc6749#appendix-A.14) property in the token endpoint response. +We recommend OAuth access tokens have an expiration. You can use the `refresh_token` parameter +to refresh tokens. Integrations may need to be updated to use refresh tokens prior to +expiration, which is based on the [expires_in](https://datatracker.ietf.org/doc/html/rfc6749#appendix-A.14) +property in the token endpoint response. See [OAuth2 token](oauth2.md) documentation +for examples requesting a new access token using a refresh token. A default refresh setting of two hours is tracked in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/336598). diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md index f2efa8fb4c0..ce455c89d1a 100644 --- a/doc/api/oauth2.md +++ b/doc/api/oauth2.md @@ -123,6 +123,28 @@ Before starting the flow, generate the `STATE`, the `CODE_VERIFIER` and the `COD "created_at": 1607635748 } ``` + +1. To retrieve a new `access_token`, use the `refresh_token` parameter. Refresh tokens may + be used even after the `access_token` itself expires. This request: + - Invalidates the existing `access_token` and `refresh_token`. + - Sends new tokens in the response. + + ```ruby + parameters = 'client_id=APP_ID&client_secret=APP_SECRET&refresh_token=REFRESH_TOKEN&grant_type=refresh_token&redirect_uri=REDIRECT_URI&code_verifier=CODE_VERIFIER' + RestClient.post 'https://gitlab.example.com/oauth/token', parameters + ``` + + Example response: + + ```json + { + "access_token": "c97d1fe52119f38c7f67f0a14db68d60caa35ddc86fd12401718b649dcfa9c68", + "token_type": "bearer", + "expires_in": 7200, + "refresh_token": "803c1fd487fec35562c205dac93e9d8e08f9d3652a24079d704df3039df1158f", + "created_at": 1628711391 + } + ``` NOTE: The `redirect_uri` must match the `redirect_uri` used in the original @@ -181,6 +203,28 @@ be used as a CSRF token. "created_at": 1607635748 } ``` + +1. To retrieve a new `access_token`, use the `refresh_token` parameter. Refresh tokens may + be used even after the `access_token` itself expires. This request: + - Invalidates the existing `access_token` and `refresh_token`. + - Sends new tokens in the response. + + ```ruby + parameters = 'client_id=APP_ID&client_secret=APP_SECRET&refresh_token=REFRESH_TOKEN&grant_type=refresh_token&redirect_uri=REDIRECT_URI' + RestClient.post 'https://gitlab.example.com/oauth/token', parameters + ``` + + Example response: + + ```json + { + "access_token": "c97d1fe52119f38c7f67f0a14db68d60caa35ddc86fd12401718b649dcfa9c68", + "token_type": "bearer", + "expires_in": 7200, + "refresh_token": "803c1fd487fec35562c205dac93e9d8e08f9d3652a24079d704df3039df1158f", + "created_at": 1628711391 + } + ``` NOTE: The `redirect_uri` must match the `redirect_uri` used in the original diff --git a/doc/api/users.md b/doc/api/users.md index e389759a9ba..6ba751bd292 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -1546,7 +1546,7 @@ curl --request POST --header "PRIVATE-TOKEN: " "https://gitla Returns: -- `201 OK` on success. +- `201 Created` on success. - `404 User Not Found` if user cannot be found. - `403 Forbidden` if the user cannot be approved because they are blocked by an administrator or by LDAP synchronization. diff --git a/doc/ci/lint.md b/doc/ci/lint.md index 746638442a7..4e3ac8b9e93 100644 --- a/doc/ci/lint.md +++ b/doc/ci/lint.md @@ -39,8 +39,8 @@ more complicated issues. To validate the configuration by running a pipeline simulation: 1. Paste the GitLab CI configuration to verify into the text box. -1. Click the **Simulate pipeline creation for the default branch** checkbox. -1. Click **Validate**. +1. Select the **Simulate pipeline creation for the default branch** checkbox. +1. Select **Validate**. ![Dry run](img/ci_lint_dry_run.png) diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md index 2cf823e5746..f3d4cb72e62 100644 --- a/doc/ci/pipelines/index.md +++ b/doc/ci/pipelines/index.md @@ -135,13 +135,13 @@ operation of the pipeline. To execute a pipeline manually: -1. Navigate to your project's **CI/CD > Pipelines**. -1. Select the **Run pipeline** button. -1. On the **Run pipeline** page: - 1. Select the branch or tag to run the pipeline for in the **Run for branch name or tag** field. - 1. Enter any [environment variables](../variables/index.md) required for the pipeline run. - You can set specific variables to have their [values prefilled in the form](#prefill-variables-in-manual-pipelines). - 1. Click the **Run pipeline** button. +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **CI/CD > Pipelines**. +1. Select **Run pipeline**. +1. In the **Run for branch name or tag** field, select the branch or tag to run the pipeline for. +1. Enter any [environment variables](../variables/index.md) required for the pipeline to run. + You can set specific variables to have their [values prefilled in the form](#prefill-variables-in-manual-pipelines). +1. Select **Run pipeline**. The pipeline now executes the jobs as configured. @@ -413,7 +413,7 @@ Feature.disable(:pipeline_graph_layers_view) Pipeline mini graphs take less space and can tell you at a quick glance if all jobs passed or something failed. The pipeline mini graph can -be found when you navigate to: +be found when you go to: - The pipelines index page. - A single commit page. diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md index 6b6fbe3996e..b72d23d3f9b 100644 --- a/doc/development/testing_guide/best_practices.md +++ b/doc/development/testing_guide/best_practices.md @@ -911,14 +911,16 @@ describe '#show', :snowplow do expect_snowplow_event( category: 'Experiment', action: 'start', - standard_context: { namespace: group, project: project } + namespace: group, + project: project ) expect_snowplow_event( category: 'Experiment', action: 'sent', property: 'property', label: 'label', - standard_context: { namespace: group, project: project } + namespace: group, + project: project ) end end diff --git a/qa/qa.rb b/qa/qa.rb index e17b2b86ceb..88d9ea13045 100644 --- a/qa/qa.rb +++ b/qa/qa.rb @@ -544,6 +544,7 @@ module QA autoload :AccessTokens, 'qa/page/component/access_tokens' autoload :CommitModal, 'qa/page/component/commit_modal' autoload :VisibilitySetting, 'qa/page/component/visibility_setting' + autoload :ContentEditor, 'qa/page/component/content_editor' module Import autoload :Gitlab, 'qa/page/component/import/gitlab' diff --git a/qa/qa/page/component/content_editor.rb b/qa/qa/page/component/content_editor.rb new file mode 100644 index 00000000000..b3a42634fe7 --- /dev/null +++ b/qa/qa/page/component/content_editor.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +module QA + module Page + module Component + module ContentEditor + extend QA::Page::PageConcern + + def self.included(base) + super + + base.view 'app/assets/javascripts/content_editor/components/content_editor.vue' do + element :content_editor_container + end + + base.view 'app/assets/javascripts/content_editor/components/toolbar_text_style_dropdown.vue' do + element :text_style_dropdown + element :text_style_menu_item + end + + base.view 'app/assets/javascripts/content_editor/components/toolbar_image_button.vue' do + element :file_upload_field + end + end + + def add_heading(heading, text) + within_element(:content_editor_container) do + text_area.set(text) + # wait for text style option to become active after typing + has_active_element?(:text_style_dropdown, wait: 1) + click_element(:text_style_dropdown) + within_element(:text_style_dropdown) do + click_element(:text_style_menu_item, text_style: heading) + end + end + end + + def upload_image(image_path) + within_element(:content_editor_container) do + # add image on a new line + text_area.send_keys(:return) + find_element(:file_upload_field, visible: false).send_keys(image_path) + end + end + + private + + def text_area + find('[contenteditable="true"]', visible: false) + end + end + end + end +end diff --git a/qa/qa/page/component/wiki.rb b/qa/qa/page/component/wiki.rb index 92eb25af247..c3db1d6c885 100644 --- a/qa/qa/page/component/wiki.rb +++ b/qa/qa/page/component/wiki.rb @@ -68,6 +68,18 @@ module QA def has_no_page? has_element?(:create_first_page_link) end + + def has_heading?(heading_type, text) + within_element(:wiki_page_content) do + has_css?(heading_type, text: text) + end + end + + def has_image?(image_file_name) + within_element(:wiki_page_content) do + has_css?("img[src$='#{image_file_name}']") + end + end end end end diff --git a/qa/qa/page/component/wiki_page_form.rb b/qa/qa/page/component/wiki_page_form.rb index bb22b7da003..6b7452b0e0f 100644 --- a/qa/qa/page/component/wiki_page_form.rb +++ b/qa/qa/page/component/wiki_page_form.rb @@ -14,6 +14,7 @@ module QA element :wiki_content_textarea element :wiki_message_textbox element :wiki_submit_button + element :try_new_editor_container end base.view 'app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue' do @@ -41,6 +42,12 @@ module QA click_element(:delete_button, Page::Modal::DeleteWiki) Page::Modal::DeleteWiki.perform(&:confirm_deletion) end + + def use_new_editor + within_element(:try_new_editor_container) do + click_button('Use the new editor') + end + end end end end diff --git a/qa/qa/page/project/wiki/edit.rb b/qa/qa/page/project/wiki/edit.rb index 70aa10cc43e..e782bbbb432 100644 --- a/qa/qa/page/project/wiki/edit.rb +++ b/qa/qa/page/project/wiki/edit.rb @@ -7,6 +7,7 @@ module QA class Edit < Base include Page::Component::WikiPageForm include Page::Component::WikiSidebar + include Page::Component::ContentEditor end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb new file mode 100644 index 00000000000..2a46604f8ac --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module QA + RSpec.describe 'Create' do + context 'Content Editor' do + let(:initial_wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! } + let(:page_title) { 'Content Editor Page' } + let(:heading_text) { 'My New Heading' } + let(:image_file_name) { 'testfile.png' } + + before do + Flow::Login.sign_in + end + + after do + initial_wiki.project.remove_via_api! + end + + it 'creates a formatted Wiki page with an image uploaded', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1861' do + initial_wiki.visit! + + Page::Project::Wiki::Show.perform(&:click_new_page) + + Page::Project::Wiki::Edit.perform do |edit| + edit.set_title(page_title) + edit.use_new_editor + edit.add_heading('Heading 1', heading_text) + edit.upload_image(File.absolute_path(File.join('qa', 'fixtures', 'designs', image_file_name))) + end + + Page::Project::Wiki::Edit.perform(&:click_submit) + + Page::Project::Wiki::Show.perform do |wiki| + aggregate_failures 'page shows expected content' do + expect(wiki).to have_title(page_title) + expect(wiki).to have_heading('h1', heading_text) + expect(wiki).to have_image(image_file_name) + end + end + end + end + end +end