diff options
47 files changed, 332 insertions, 127 deletions
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index ecd32dcd0ce..4aba633e182 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -196,6 +196,11 @@ ul.content-list { display: flex; align-items: center; white-space: nowrap; + + // Override style that allows the flex-row text to wrap. + &.allow-wrap { + white-space: normal; + } } .row-main-content { diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 3ae804ff231..8389272fd35 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -94,6 +94,25 @@ module ApplicationHelper sanitize(str, tags: %w(a span)) end + def body_data + { + page: body_data_page, + page_type_id: controller.params[:id], + find_file: find_file_path, + group: "#{@group&.path}" + }.merge(project_data) + end + + def project_data + return {} unless @project + + { + project_id: @project.id, + project: @project.path, + namespace_id: @project.namespace&.id + } + end + def body_data_page [*controller.controller_path.split('/'), controller.action_name].compact.join(':') end diff --git a/app/views/clusters/clusters/_namespace.html.haml b/app/views/clusters/clusters/_namespace.html.haml index 0c64819ad62..8a86fd90963 100644 --- a/app/views/clusters/clusters/_namespace.html.haml +++ b/app/views/clusters/clusters/_namespace.html.haml @@ -1,4 +1,4 @@ -- managed_namespace_help_text = s_('ClusterIntegration|Choose a prefix to be used for your namespaces. Defaults to your project path.') +- managed_namespace_help_text = s_('ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared.') - non_managed_namespace_help_text = s_('ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, pod logs, and Web terminals.') - managed_namespace_help_link = link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'), target: '_blank' diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index c38f96f302a..f4ab491a38e 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,7 +1,7 @@ !!! 5 %html{ lang: I18n.locale, class: page_class } = render "layouts/head" - %body{ class: "#{user_application_theme} #{@body_class} #{client_class_list}", data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}", find_file: find_file_path } } + %body{ class: "#{user_application_theme} #{@body_class} #{client_class_list}", data: body_data } = render "layouts/init_auto_complete" if @gfm_form = render "layouts/init_client_detection_flags" = render 'peek/bar' diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml index b04d484c8a7..75805192a61 100644 --- a/app/views/projects/tags/_tag.html.haml +++ b/app/views/projects/tags/_tag.html.haml @@ -1,7 +1,7 @@ - commit = @repository.commit(tag.dereferenced_target) - release = @releases.find { |release| release.tag == tag.name } -%li.flex-row - .row-main-content.str-truncated +%li.flex-row.allow-wrap + .row-main-content = icon('tag') = link_to tag.name, project_tag_path(@project, tag.name), class: 'item-title ref-name prepend-left-4' @@ -26,7 +26,7 @@ = _("Release") = link_to release.name, project_releases_path(@project, anchor: release.tag), class: 'tag-release-link' - if release.description.present? - .description.md.prepend-top-default + .md.prepend-top-default = markdown_field(release, :description) .row-fixed-content.controls.flex-row diff --git a/changelogs/unreleased/33482-allow-text-wrapping-on-repository-tags-page.yml b/changelogs/unreleased/33482-allow-text-wrapping-on-repository-tags-page.yml new file mode 100644 index 00000000000..567e1b7cfda --- /dev/null +++ b/changelogs/unreleased/33482-allow-text-wrapping-on-repository-tags-page.yml @@ -0,0 +1,5 @@ +--- +title: Allow patch notes on repo tags page to word wrap +merge_request: 20135 +author: +type: fixed diff --git a/changelogs/unreleased/add_body_data_elements_for_page_type_id_project_id_and_namespace_id.yml b/changelogs/unreleased/add_body_data_elements_for_page_type_id_project_id_and_namespace_id.yml new file mode 100644 index 00000000000..587741a8ea5 --- /dev/null +++ b/changelogs/unreleased/add_body_data_elements_for_page_type_id_project_id_and_namespace_id.yml @@ -0,0 +1,5 @@ +--- +title: Add body data elements for pageview context +merge_request: 18450 +author: +type: added diff --git a/changelogs/unreleased/update-managed-namespace-prefix-copy.yml b/changelogs/unreleased/update-managed-namespace-prefix-copy.yml new file mode 100644 index 00000000000..e19e8078f64 --- /dev/null +++ b/changelogs/unreleased/update-managed-namespace-prefix-copy.yml @@ -0,0 +1,5 @@ +--- +title: Update copy on managed namespace prefixes +merge_request: 20935 +author: +type: fixed diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md index a6474b8b141..64a59796ebc 100644 --- a/doc/development/documentation/index.md +++ b/doc/development/documentation/index.md @@ -30,6 +30,23 @@ The source of the documentation exists within the codebase of each GitLab applic Documentation issues and merge requests are part of their respective repositories and all have the label `Documentation`. +### Branch naming + +The [CI pipeline for the main GitLab project](../pipelines.md) is configured to automatically +run only the jobs that match the type of contribution. If your contribution contains +**only** documentation changes, then only documentation-related jobs will be run, and +the pipeline will complete much faster than a code contribution. + +If you are submitting documentation-only changes to Runner, Omnibus, or Charts, +the fast pipeline is not determined automatically. Instead, create branches for +docs-only merge requests using the following guide: + +| Branch name | Valid example | +|:----------------------|:-----------------------------| +| Starting with `docs/` | `docs/update-api-issues` | +| Starting with `docs-` | `docs-update-api-issues` | +| Ending in `-docs` | `123-update-api-issues-docs` | + ## Contributing to docs [Contributions to GitLab docs](workflow.md) are welcome from the entire GitLab community. diff --git a/doc/development/testing_guide/end_to_end/best_practices.md b/doc/development/testing_guide/end_to_end/best_practices.md index e2a0d267ba1..fc00fcea67e 100644 --- a/doc/development/testing_guide/end_to_end/best_practices.md +++ b/doc/development/testing_guide/end_to_end/best_practices.md @@ -54,9 +54,9 @@ In summary: - **Do**: Split tests across separate files, unless the tests share expensive setup. - **Don't**: Put new tests in an existing file without considering the impact on parallelization. -## Limit the use of `before(:all)` hook +## Limit the use of `before(:all)` and `after` hooks -Limit the use of `before(:all)` to perform setup tasks with only API calls, non UI operations +Limit the use of `before(:all)` hook to perform setup tasks with only API calls, non UI operations or basic UI operations such as login. We use [`capybara-screenshot`](https://github.com/mattheworiordan/capybara-screenshot) library to automatically save screenshots on failures. @@ -66,6 +66,10 @@ This library [saves the screenshots in the RSpec's `after` hook](https://github. Given this fact, we should limit the use of `before(:all)` to only those operations where a screenshot is not necessary in case of failure and QA logs would be enough for debugging. +Similarly, the `after` hook should only be used for non-UI operations. Any UI operations in `after` hook in a test file +would execute before the `after` hook that takes the screenshot. This would result in moving the UI status away from the +point of failure and so the screenshot would not be captured at the right moment. + ## Ensure tests do not leave the browser logged in All QA tests expect to be able to log in at the start of the test. @@ -74,7 +78,7 @@ That's not possible if a test leaves the browser logged in when it finishes. Nor For an example see: <https://gitlab.com/gitlab-org/gitlab/issues/34736> -Ideally, any actions peformed in an `after(:context)` (or [`before(:context)`](#limit-the-use-of-beforeall-hook)) block would be performed via the API. But if it's necessary to do so via the UI (e.g., if API functionality doesn't exist), make sure to log out at the end of the block. +Ideally, any actions peformed in an `after(:context)` (or [`before(:context)`](#limit-the-use-of-beforeall-and-after-hooks)) block would be performed via the API. But if it's necessary to do so via the UI (e.g., if API functionality doesn't exist), make sure to log out at the end of the block. ```ruby after(:all) do diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md index 73406fd5037..30f9d4e53a3 100644 --- a/doc/user/admin_area/settings/visibility_and_access_controls.md +++ b/doc/user/admin_area/settings/visibility_and_access_controls.md @@ -14,8 +14,11 @@ To access the visibility and access control options: ## Default branch protection -Branch protection specifies which roles can push to branches and which roles can delete -branches. +This global option defines the branch protection that applies to every repository's default branch. [Branch protection](../../project/protected_branches.md) specifies which roles can push to branches and which roles can delete +branches. In this case _Default_ refers to a repository's default branch, which in most cases is _master_. +branches. "Default" in this case refers to a repository's default branch, which in most cases would be "master". + +This setting applies only to each repositories' default branch. To protect other branches, you must configure branch protection in repository. For details, see [Protected Branches](../../project/protected_branches.md). To change the default branch protection: diff --git a/doc/user/project/integrations/github.md b/doc/user/project/integrations/github.md index 9d16748085c..b8b073af2a4 100644 --- a/doc/user/project/integrations/github.md +++ b/doc/user/project/integrations/github.md @@ -33,6 +33,9 @@ with `repo:status` access granted: 1. Optionally uncheck **Static status check names** checkbox to disable static status check names. 1. Save or optionally click "Test Settings". +Once the integration is configured, see [Pipelines for external pull requests](../../../ci/ci_cd_for_external_repos/#pipelines-for-external-pull-requests) +to configure pipelines to run for open pull requests. + #### Static / dynamic status check names > - Introduced in GitLab 11.5: using static status check names as opt-in option. diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 95a04eb18b0..6b6143eba96 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -3595,9 +3595,6 @@ msgstr "" msgid "ClusterIntegration|Certificate Authority bundle (PEM format)" msgstr "" -msgid "ClusterIntegration|Choose a prefix to be used for your namespaces. Defaults to your project path." -msgstr "" - msgid "ClusterIntegration|Choose the %{startLink}security group %{externalLinkIcon} %{endLink} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets." msgstr "" @@ -4132,6 +4129,9 @@ msgstr "" msgid "ClusterIntegration|Service token is required." msgstr "" +msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared." +msgstr "" + msgid "ClusterIntegration|Show" msgstr "" diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb index 66c56c86fc8..7143cc574b8 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb @@ -4,8 +4,7 @@ module QA context 'Configure', :orchestrated, :mattermost do describe 'Mattermost support' do it 'user creates a group with a mattermost team' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in Page::Main::Menu.perform(&:go_to_groups) Page::Dashboard::Groups.perform do |groups| diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb index c9acd7df776..6f75940e1f0 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb @@ -4,8 +4,7 @@ module QA context 'Manage' do describe 'Project transfer between groups' do it 'user transfers a project between groups' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in source_group = Resource::Group.fabricate_via_api! do |group| group.path = 'source-group' diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb index d8233fc5586..1050005a231 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb @@ -4,8 +4,7 @@ module QA context 'Manage', :smoke do describe 'basic user login' do it 'user logs in using basic credentials and logs out' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in Page::Main::Menu.perform do |menu| expect(menu).to have_personal_area diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb index 10cd8470a8f..46a0f1a4c8b 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb @@ -4,8 +4,7 @@ module QA context 'Manage', :orchestrated, :ldap_no_tls, :ldap_tls do describe 'LDAP login' do it 'user logs into GitLab using LDAP credentials' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in Page::Main::Menu.perform do |menu| expect(menu).to have_personal_area diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb index e66c12c1301..a680cfa96bd 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb @@ -4,8 +4,7 @@ module QA context 'Manage', :orchestrated, :mattermost do describe 'Mattermost login' do it 'user logs into Mattermost using GitLab OAuth' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in Support::Retrier.retry_on_exception do Runtime::Browser.visit(:mattermost, Page::Mattermost::Login) diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb index abb46463ed2..9a273e9cd1c 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb @@ -4,8 +4,7 @@ module QA context 'Manage' do describe 'Add project member' do it 'user adds project member' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in user = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb index fbe857dc2a5..9ca933a957f 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb @@ -4,8 +4,7 @@ module QA context 'Manage', :smoke do describe 'Project creation' do it 'user creates a new project' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in created_project = Resource::Project.fabricate_via_browser_ui! do |project| project.name = 'awesome-project' diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb index 4f68500974e..7a47194c3a4 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb @@ -23,8 +23,7 @@ module QA end it 'user imports a GitHub repo' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in imported_project # import the project diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb index fe92fbd3ffe..5f3b492ea81 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb @@ -4,8 +4,7 @@ module QA context 'Manage' do describe 'Project activity' do it 'user creates an event in the activity page upon Git push' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in project_push = Resource::Repository::ProjectPush.fabricate! do |push| push.file_name = 'README.md' diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb index 6bdec232bb0..f48fe78c530 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb @@ -4,8 +4,7 @@ module QA context 'Create' do describe 'Create a new merge request' do before do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in @project = Resource::Project.fabricate_via_api! do |project| project.name = 'project' diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb index 6ca7af8a3af..370bf30f3a4 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb @@ -4,8 +4,7 @@ module QA context 'Create' do describe 'Merge request creation from fork' do it 'user forks a project, submits a merge request and maintainer merges it' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in merge_request = Resource::MergeRequestFromFork.fabricate! do |merge_request| merge_request.fork_branch = 'feature-branch' diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb index c7b5e40d0be..c41cb24f4c2 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb @@ -5,8 +5,7 @@ module QA context 'Create', :quarantine do describe 'Merge request rebasing' do it 'user rebases source branch of merge request' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in project = Resource::Project.fabricate! do |project| project.name = "only-fast-forward" diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb index a93f2695ec2..f1ba726ddec 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb @@ -4,8 +4,7 @@ module QA context 'Create' do describe 'Merge request squashing' do it 'user squashes commits while merging' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in project = Resource::Project.fabricate! do |project| project.name = "squash-before-merge" diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb index 3306c5f5c50..7b1c2a71158 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb @@ -16,8 +16,7 @@ module QA commit_message_of_third_branch = "Add #{file_third_branch}" before do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in project = Resource::Project.fabricate! do |proj| proj.name = 'project-qa-test' diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb index 56a7a04e840..474a7904fea 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb @@ -6,8 +6,7 @@ module QA let(:key_title) { "key for ssh tests #{Time.now.to_f}" } it 'user adds and then removes an SSH key', :smoke do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in key = Resource::SSHKey.fabricate! do |resource| resource.title = key_title diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb index ec3c4c1ae94..3771be1a8d1 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb @@ -6,8 +6,7 @@ module QA context 'Create', :quarantine do describe 'Push over HTTP using Git protocol version 2', :requires_git_protocol_v2 do it 'user pushes to the repository' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in # Create a project to push to project = Resource::Project.fabricate! do |project| diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb index 58f402a19ce..e2b2ee801c3 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb @@ -17,20 +17,15 @@ module QA end end - def login - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) - end - around do |example| # Create an SSH key to be used with Git - login + Flow::Login.sign_in ssh_key example.run # Remove the SSH key - login + Flow::Login.sign_in Page::Main::Menu.perform(&:click_settings_link) Page::Profile::Menu.perform(&:click_ssh_keys) Page::Profile::SSHKeys.perform do |ssh_keys| diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb index 1f4fb08accc..c713f11af7d 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb @@ -4,8 +4,7 @@ module QA context 'Create' do describe 'Git push over HTTP', :ldap_no_tls do it 'user using a personal access token pushes code to the repository' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in access_token = Resource::PersonalAccessToken.fabricate!.access_token diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb index 58e6c160a3a..2bd54d763a6 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb @@ -4,8 +4,7 @@ module QA context 'Create' do describe 'Git push over HTTP', :ldap_no_tls do it 'user pushes code to the repository' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in project_push = Resource::Repository::ProjectPush.fabricate! do |push| push.file_name = 'README.md' diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb index a0251e1c385..1837a110d79 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb @@ -9,8 +9,7 @@ module QA let(:key_title) { "key for ssh tests #{Time.now.to_f}" } it 'user adds an ssh key and pushes code to the repository' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in key = Resource::SSHKey.fabricate! do |resource| resource.title = key_title diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_snippet_spec.rb index cbc9f63f772..277e7364ada 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_snippet_spec.rb @@ -4,8 +4,7 @@ module QA context 'Create', :smoke do describe 'Snippet creation' do it 'User creates a snippet' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in Page::Main::Menu.perform(&:go_to_snippets) diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb index 770d66141eb..42aa527da85 100644 --- a/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb @@ -4,8 +4,7 @@ module QA context 'Create' do describe 'Wiki management' do it 'user creates, edits, clones, and pushes to the wiki' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in wiki = Resource::Wiki.fabricate! do |resource| resource.title = 'Home' diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb index 6f39a755392..9c964c726f1 100644 --- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb @@ -4,8 +4,7 @@ module QA context 'Release' do describe 'Deploy key creation' do it 'user adds a deploy key' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in key = Runtime::Key::RSA.new deploy_key_title = 'deploy key title' diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb index 9dc4bcc8a03..3badaa983cb 100644 --- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb @@ -10,8 +10,7 @@ module QA @job_log_json_flag_enabled = Runtime::Feature.enabled?('job_log_json') Runtime::Feature.disable('job_log_json') if @job_log_json_flag_enabled - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in @runner_name = "qa-runner-#{Time.now.to_i}" diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb index ec0c45652fd..9cb9f9ba529 100644 --- a/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb @@ -4,8 +4,7 @@ module QA context 'Release' do describe 'Deploy token creation' do it 'user adds a deploy token' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.perform(&:sign_in_using_credentials) + Flow::Login.sign_in deploy_token_name = 'deploy token name' one_week_from_now = Date.today + 7 diff --git a/spec/javascripts/lib/utils/accessor_spec.js b/spec/frontend/lib/utils/accessor_spec.js index 0045330e470..752a88296e6 100644 --- a/spec/javascripts/lib/utils/accessor_spec.js +++ b/spec/frontend/lib/utils/accessor_spec.js @@ -1,14 +1,18 @@ +import { useLocalStorageSpy } from 'helpers/local_storage_helper'; import AccessorUtilities from '~/lib/utils/accessor'; describe('AccessorUtilities', () => { + useLocalStorageSpy(); + const testError = new Error('test error'); describe('isPropertyAccessSafe', () => { let base; it('should return `true` if access is safe', () => { - base = { testProp: 'testProp' }; - + base = { + testProp: 'testProp', + }; expect(AccessorUtilities.isPropertyAccessSafe(base, 'testProp')).toBe(true); }); @@ -54,17 +58,12 @@ describe('AccessorUtilities', () => { }); describe('isLocalStorageAccessSafe', () => { - beforeEach(() => { - spyOn(window.localStorage, 'setItem'); - spyOn(window.localStorage, 'removeItem'); - }); - it('should return `true` if access is safe', () => { expect(AccessorUtilities.isLocalStorageAccessSafe()).toBe(true); }); it('should return `false` if access to .setItem isnt safe', () => { - window.localStorage.setItem.and.callFake(() => { + window.localStorage.setItem.mockImplementation(() => { throw testError; }); diff --git a/spec/javascripts/lib/utils/dom_utils_spec.js b/spec/frontend/lib/utils/dom_utils_spec.js index 2bcf37f35c7..10b4a10a8ff 100644 --- a/spec/javascripts/lib/utils/dom_utils_spec.js +++ b/spec/frontend/lib/utils/dom_utils_spec.js @@ -25,7 +25,7 @@ describe('DOM Utils', () => { addClassIfElementExists(childElement, className); - expect(childElement.classList).toContain(className); + expect(childElement.classList).toContainEqual(className); }); it('does not throw if element does not exist', () => { @@ -40,22 +40,44 @@ describe('DOM Utils', () => { describe('canScrollUp', () => { [1, 100].forEach(scrollTop => { it(`is true if scrollTop is > 0 (${scrollTop})`, () => { - expect(canScrollUp({ scrollTop })).toBe(true); + expect( + canScrollUp({ + scrollTop, + }), + ).toBe(true); }); }); [0, -10].forEach(scrollTop => { it(`is false if scrollTop is <= 0 (${scrollTop})`, () => { - expect(canScrollUp({ scrollTop })).toBe(false); + expect( + canScrollUp({ + scrollTop, + }), + ).toBe(false); }); }); it('is true if scrollTop is > margin', () => { - expect(canScrollUp({ scrollTop: TEST_MARGIN + 1 }, TEST_MARGIN)).toBe(true); + expect( + canScrollUp( + { + scrollTop: TEST_MARGIN + 1, + }, + TEST_MARGIN, + ), + ).toBe(true); }); it('is false if scrollTop is <= margin', () => { - expect(canScrollUp({ scrollTop: TEST_MARGIN }, TEST_MARGIN)).toBe(false); + expect( + canScrollUp( + { + scrollTop: TEST_MARGIN, + }, + TEST_MARGIN, + ), + ).toBe(false); }); }); @@ -63,7 +85,11 @@ describe('DOM Utils', () => { let element; beforeEach(() => { - element = { scrollTop: 7, offsetHeight: 22, scrollHeight: 30 }; + element = { + scrollTop: 7, + offsetHeight: 22, + scrollHeight: 30, + }; }); it('is true if element can be scrolled down', () => { diff --git a/spec/javascripts/lib/utils/file_upload_spec.js b/spec/frontend/lib/utils/file_upload_spec.js index 8f7092f63de..1255d6fc14f 100644 --- a/spec/javascripts/lib/utils/file_upload_spec.js +++ b/spec/frontend/lib/utils/file_upload_spec.js @@ -20,7 +20,7 @@ describe('File upload', () => { const btn = document.querySelector('.js-button'); const input = document.querySelector('.js-input'); - spyOn(input, 'click'); + jest.spyOn(input, 'click').mockReturnValue(); btn.click(); @@ -43,7 +43,7 @@ describe('File upload', () => { const btn = document.querySelector('.js-button'); fileUpload('.js-not-button', '.js-input'); - spyOn(input, 'click'); + jest.spyOn(input, 'click').mockReturnValue(); btn.click(); @@ -55,7 +55,7 @@ describe('File upload', () => { const btn = document.querySelector('.js-button'); fileUpload('.js-button', '.js-not-input'); - spyOn(input, 'click'); + jest.spyOn(input, 'click').mockReturnValue(); btn.click(); diff --git a/spec/javascripts/lib/utils/higlight_spec.js b/spec/frontend/lib/utils/highlight_spec.js index 638bbf65ae9..638bbf65ae9 100644 --- a/spec/javascripts/lib/utils/higlight_spec.js +++ b/spec/frontend/lib/utils/highlight_spec.js diff --git a/spec/javascripts/lib/utils/icon_utils_spec.js b/spec/frontend/lib/utils/icon_utils_spec.js index 3fd3940efe8..816d634ad15 100644 --- a/spec/javascripts/lib/utils/icon_utils_spec.js +++ b/spec/frontend/lib/utils/icon_utils_spec.js @@ -17,51 +17,44 @@ describe('Icon utils', () => { let axiosMock; let mockEndpoint; - let getIcon; const mockName = 'mockIconName'; const mockPath = 'mockPath'; + const getIcon = () => iconUtils.getSvgIconPathContent(mockName); beforeEach(() => { axiosMock = new MockAdapter(axios); mockEndpoint = axiosMock.onGet(gon.sprite_icons); - getIcon = iconUtils.getSvgIconPathContent(mockName); }); afterEach(() => { axiosMock.restore(); }); - it('extracts svg icon path content from sprite icons', done => { + it('extracts svg icon path content from sprite icons', () => { mockEndpoint.replyOnce( 200, `<svg><symbol id="${mockName}"><path d="${mockPath}"/></symbol></svg>`, ); - getIcon - .then(path => { - expect(path).toBe(mockPath); - done(); - }) - .catch(done.fail); + + return getIcon().then(path => { + expect(path).toBe(mockPath); + }); }); - it('returns null if icon path content does not exist', done => { + it('returns null if icon path content does not exist', () => { mockEndpoint.replyOnce(200, ``); - getIcon - .then(path => { - expect(path).toBe(null); - done(); - }) - .catch(done.fail); + + return getIcon().then(path => { + expect(path).toBe(null); + }); }); - it('returns null if an http error occurs', done => { + it('returns null if an http error occurs', () => { mockEndpoint.replyOnce(500); - getIcon - .then(path => { - expect(path).toBe(null); - done(); - }) - .catch(done.fail); + + return getIcon().then(path => { + expect(path).toBe(null); + }); }); }); }); diff --git a/spec/javascripts/lib/utils/text_markdown_spec.js b/spec/frontend/lib/utils/text_markdown_spec.js index df4029555bb..ba3e4020e66 100644 --- a/spec/javascripts/lib/utils/text_markdown_spec.js +++ b/spec/frontend/lib/utils/text_markdown_spec.js @@ -243,7 +243,7 @@ describe('init markdown', () => { }); it('uses ace editor insert text when editor is passed in', () => { - spyOn(editor, 'insert'); + jest.spyOn(editor, 'insert').mockReturnValue(); insertMarkdownText({ text: editor.getValue, @@ -258,7 +258,7 @@ describe('init markdown', () => { }); it('adds block tags on line above and below selection', () => { - spyOn(editor, 'insert'); + jest.spyOn(editor, 'insert').mockReturnValue(); const selected = 'this text \n is multiple \n lines'; const text = `before \n ${selected} \n after`; @@ -276,7 +276,7 @@ describe('init markdown', () => { }); it('uses ace editor to navigate back tag length when nothing is selected', () => { - spyOn(editor, 'navigateLeft'); + jest.spyOn(editor, 'navigateLeft').mockReturnValue(); insertMarkdownText({ text: editor.getValue, @@ -291,7 +291,7 @@ describe('init markdown', () => { }); it('ace editor does not navigate back when there is selected text', () => { - spyOn(editor, 'navigateLeft'); + jest.spyOn(editor, 'navigateLeft').mockReturnValue(); insertMarkdownText({ text: editor.getValue, diff --git a/spec/javascripts/lib/utils/users_cache_spec.js b/spec/frontend/lib/utils/users_cache_spec.js index acb5e024acd..7ed87123482 100644 --- a/spec/javascripts/lib/utils/users_cache_spec.js +++ b/spec/frontend/lib/utils/users_cache_spec.js @@ -4,7 +4,10 @@ import UsersCache from '~/lib/utils/users_cache'; describe('UsersCache', () => { const dummyUsername = 'win'; const dummyUserId = 123; - const dummyUser = { name: 'has a farm', username: 'farmer' }; + const dummyUser = { + name: 'has a farm', + username: 'farmer', + }; const dummyUserStatus = 'my status'; beforeEach(() => { @@ -68,7 +71,6 @@ describe('UsersCache', () => { it('does nothing if cache contains no matching data', () => { UsersCache.internalStorage['no body'] = 'no data'; - UsersCache.remove(dummyUsername); expect(UsersCache.internalStorage['no body']).toBe('no data'); @@ -76,7 +78,6 @@ describe('UsersCache', () => { it('removes matching data', () => { UsersCache.internalStorage[dummyUsername] = dummyUser; - UsersCache.remove(dummyUsername); expect(UsersCache.internalStorage).toEqual({}); @@ -87,13 +88,16 @@ describe('UsersCache', () => { let apiSpy; beforeEach(() => { - spyOn(Api, 'users').and.callFake((query, options) => apiSpy(query, options)); + jest.spyOn(Api, 'users').mockImplementation((query, options) => apiSpy(query, options)); }); it('stores and returns data from API call if cache is empty', done => { apiSpy = (query, options) => { expect(query).toBe(''); - expect(options).toEqual({ username: dummyUsername }); + expect(options).toEqual({ + username: dummyUsername, + }); + return Promise.resolve({ data: [dummyUser], }); @@ -110,14 +114,18 @@ describe('UsersCache', () => { it('returns undefined if Ajax call fails and cache is empty', done => { const dummyError = new Error('server exploded'); + apiSpy = (query, options) => { expect(query).toBe(''); - expect(options).toEqual({ username: dummyUsername }); + expect(options).toEqual({ + username: dummyUsername, + }); + return Promise.reject(dummyError); }; UsersCache.retrieve(dummyUsername) - .then(user => fail(`Received unexpected user: ${JSON.stringify(user)}`)) + .then(user => done.fail(`Received unexpected user: ${JSON.stringify(user)}`)) .catch(error => { expect(error).toBe(dummyError); }) @@ -127,7 +135,8 @@ describe('UsersCache', () => { it('makes no Ajax call if matching data exists', done => { UsersCache.internalStorage[dummyUsername] = dummyUser; - apiSpy = () => fail(new Error('expected no Ajax call!')); + + apiSpy = () => done.fail(new Error('expected no Ajax call!')); UsersCache.retrieve(dummyUsername) .then(user => { @@ -142,12 +151,13 @@ describe('UsersCache', () => { let apiSpy; beforeEach(() => { - spyOn(Api, 'user').and.callFake(id => apiSpy(id)); + jest.spyOn(Api, 'user').mockImplementation(id => apiSpy(id)); }); it('stores and returns data from API call if cache is empty', done => { apiSpy = id => { expect(id).toBe(dummyUserId); + return Promise.resolve({ data: dummyUser, }); @@ -164,13 +174,15 @@ describe('UsersCache', () => { it('returns undefined if Ajax call fails and cache is empty', done => { const dummyError = new Error('server exploded'); + apiSpy = id => { expect(id).toBe(dummyUserId); + return Promise.reject(dummyError); }; UsersCache.retrieveById(dummyUserId) - .then(user => fail(`Received unexpected user: ${JSON.stringify(user)}`)) + .then(user => done.fail(`Received unexpected user: ${JSON.stringify(user)}`)) .catch(error => { expect(error).toBe(dummyError); }) @@ -180,7 +192,8 @@ describe('UsersCache', () => { it('makes no Ajax call if matching data exists', done => { UsersCache.internalStorage[dummyUserId] = dummyUser; - apiSpy = () => fail(new Error('expected no Ajax call!')); + + apiSpy = () => done.fail(new Error('expected no Ajax call!')); UsersCache.retrieveById(dummyUserId) .then(user => { @@ -195,12 +208,13 @@ describe('UsersCache', () => { let apiSpy; beforeEach(() => { - spyOn(Api, 'userStatus').and.callFake(id => apiSpy(id)); + jest.spyOn(Api, 'userStatus').mockImplementation(id => apiSpy(id)); }); it('stores and returns data from API call if cache is empty', done => { apiSpy = id => { expect(id).toBe(dummyUserId); + return Promise.resolve({ data: dummyUserStatus, }); @@ -217,13 +231,15 @@ describe('UsersCache', () => { it('returns undefined if Ajax call fails and cache is empty', done => { const dummyError = new Error('server exploded'); + apiSpy = id => { expect(id).toBe(dummyUserId); + return Promise.reject(dummyError); }; UsersCache.retrieveStatusById(dummyUserId) - .then(userStatus => fail(`Received unexpected user: ${JSON.stringify(userStatus)}`)) + .then(userStatus => done.fail(`Received unexpected user: ${JSON.stringify(userStatus)}`)) .catch(error => { expect(error).toBe(dummyError); }) @@ -232,8 +248,11 @@ describe('UsersCache', () => { }); it('makes no Ajax call if matching data exists', done => { - UsersCache.internalStorage[dummyUserId] = { status: dummyUserStatus }; - apiSpy = () => fail(new Error('expected no Ajax call!')); + UsersCache.internalStorage[dummyUserId] = { + status: dummyUserStatus, + }; + + apiSpy = () => done.fail(new Error('expected no Ajax call!')); UsersCache.retrieveStatusById(dummyUserId) .then(userStatus => { diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index d3d25d3cb74..a0c85863150 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -235,4 +235,88 @@ describe ApplicationHelper do end end end + + describe '#body_data' do + context 'when @project is not set' do + it 'does not include project data in the body data elements' do + expect(helper.body_data).to eq( + { + page: 'application', + page_type_id: nil, + find_file: nil, + group: '' + } + ) + end + + context 'when @group is set' do + it 'sets group in the body data elements' do + group = create(:group) + + assign(:group, group) + + expect(helper.body_data).to eq( + { + page: 'application', + page_type_id: nil, + find_file: nil, + group: group.path + } + ) + end + end + end + + context 'when @project is set' do + it 'includes all possible body data elements and associates the project elements with project' do + project = create(:project) + + assign(:project, project) + + expect(helper.body_data).to eq( + { + page: 'application', + page_type_id: nil, + find_file: nil, + group: '', + project_id: project.id, + project: project.name, + namespace_id: project.namespace.id + } + ) + end + + context 'when controller is issues' do + before do + stub_controller_method(:controller_path, 'projects:issues') + end + + context 'when params[:id] is present and the issue exsits and action_name is show' do + it 'sets all project and id elements correctly related to the issue' do + issue = create(:issue) + stub_controller_method(:action_name, 'show') + stub_controller_method(:params, { id: issue.id }) + + assign(:project, issue.project) + + expect(helper.body_data).to eq( + { + page: 'projects:issues:show', + page_type_id: issue.id, + find_file: nil, + group: '', + project_id: issue.project.id, + project: issue.project.name, + namespace_id: issue.project.namespace.id + } + ) + end + end + end + end + + def stub_controller_method(method_name, value) + allow(helper.controller).to receive(method_name).and_return(value) + end + end end diff --git a/spec/views/layouts/application.html.haml_spec.rb b/spec/views/layouts/application.html.haml_spec.rb new file mode 100644 index 00000000000..bdd4a97a1f5 --- /dev/null +++ b/spec/views/layouts/application.html.haml_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'layouts/application' do + let(:user) { create(:user) } + + before do + allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings) + allow(view).to receive(:experiment_enabled?).and_return(false) + allow(view).to receive(:session).and_return({}) + allow(view).to receive(:user_signed_in?).and_return(true) + allow(view).to receive(:current_user).and_return(user) + end + + context 'body data elements for pageview context' do + let(:body_data) do + { + body_data_page: 'projects:issues:show', + body_data_page_type_id: '1', + body_data_project_id: '2', + body_data_namespace_id: '3' + } + end + + before do + allow(view).to receive(:body_data).and_return(body_data) + render + end + + it 'includes the body element page' do + expect(rendered).to include('data-page="projects:issues:show"') + end + + it 'includes the body element page_type_id' do + expect(rendered).to include('data-page-type-id="1"') + end + + it 'includes the body element project_id' do + expect(rendered).to include('data-project-id="2"') + end + + it 'includes the body element namespace_id' do + expect(rendered).to include('data-namespace-id="3"') + end + end +end |