diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-25 21:08:06 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-25 21:08:06 +0000 |
commit | e1549c75843d235607aebac9ed64f2fd10e549ed (patch) | |
tree | d6b4213b87b57b323464c7e5c1b75091212f3373 | |
parent | 5d75b2b9a9d11c20667895e6aa68ea4e76658c5d (diff) | |
download | gitlab-ce-e1549c75843d235607aebac9ed64f2fd10e549ed.tar.gz |
Add latest changes from gitlab-org/gitlab@master
19 files changed, 175 insertions, 108 deletions
diff --git a/.rubocop.yml b/.rubocop.yml index fd0b626919a..06c3deda888 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -202,7 +202,6 @@ GitlabSecurity/PublicSend: Gitlab/DuplicateSpecLocation: Exclude: - - ee/spec/controllers/projects/jobs_controller_spec.rb - ee/spec/helpers/auth_helper_spec.rb - ee/spec/lib/gitlab/gl_repository_spec.rb - ee/spec/lib/gitlab/usage_data_spec.rb @@ -214,7 +213,6 @@ Gitlab/DuplicateSpecLocation: - ee/spec/services/merge_requests/refresh_service_spec.rb - ee/spec/services/merge_requests/update_service_spec.rb - ee/spec/services/system_hooks_service_spec.rb - - ee/spec/controllers/ee/projects/jobs_controller_spec.rb - ee/spec/helpers/ee/auth_helper_spec.rb - ee/spec/lib/ee/gitlab/gl_repository_spec.rb - ee/spec/lib/ee/gitlab/usage_data_spec.rb diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue index 576a9bc7743..f4d37c8c5f3 100644 --- a/app/assets/javascripts/clusters/components/applications.vue +++ b/app/assets/javascripts/clusters/components/applications.vue @@ -1,5 +1,5 @@ <script> -import _ from 'underscore'; +import { escape as esc } from 'lodash'; import helmInstallIllustration from '@gitlab/svgs/dist/illustrations/kubernetes-installation.svg'; import { GlLoadingIcon } from '@gitlab/ui'; import elasticsearchLogo from 'images/cluster_app_logos/elasticsearch.png'; @@ -130,7 +130,7 @@ export default { }, ingressDescription() { return sprintf( - _.escape( + esc( s__( `ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{pricingLink}.`, ), @@ -138,14 +138,14 @@ export default { { pricingLink: `<a href="https://cloud.google.com/compute/pricing#lb" target="_blank" rel="noopener noreferrer"> - ${_.escape(s__('ClusterIntegration|pricing'))}</a>`, + ${esc(s__('ClusterIntegration|pricing'))}</a>`, }, false, ); }, certManagerDescription() { return sprintf( - _.escape( + esc( s__( `ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates @@ -155,14 +155,14 @@ export default { { letsEncrypt: `<a href="https://letsencrypt.org/" target="_blank" rel="noopener noreferrer"> - ${_.escape(s__("ClusterIntegration|Let's Encrypt"))}</a>`, + ${esc(s__("ClusterIntegration|Let's Encrypt"))}</a>`, }, false, ); }, crossplaneDescription() { return sprintf( - _.escape( + esc( s__( `ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{kubectl} or %{gitlabIntegrationLink}. Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on.`, @@ -171,7 +171,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity { gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ee/user/clusters/applications.html#crossplane" target="_blank" rel="noopener noreferrer"> - ${_.escape(s__('ClusterIntegration|Gitlab Integration'))}</a>`, + ${esc(s__('ClusterIntegration|Gitlab Integration'))}</a>`, kubectl: `<code>kubectl</code>`, }, false, @@ -180,7 +180,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity prometheusDescription() { return sprintf( - _.escape( + esc( s__( `ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications.`, @@ -189,7 +189,7 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity { gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html" target="_blank" rel="noopener noreferrer"> - ${_.escape(s__('ClusterIntegration|GitLab Integration'))}</a>`, + ${esc(s__('ClusterIntegration|GitLab Integration'))}</a>`, }, false, ); @@ -215,11 +215,11 @@ Crossplane runs inside your Kubernetes cluster and supports secure connectivity installedVia() { if (this.cloudRun) { return sprintf( - _.escape(s__(`ClusterIntegration|installed via %{installed_via}`)), + esc(s__(`ClusterIntegration|installed via %{installed_via}`)), { installed_via: `<a href="${ this.cloudRunHelpPath - }" target="_blank" rel="noopener noreferrer">${_.escape( + }" target="_blank" rel="noopener noreferrer">${esc( s__('ClusterIntegration|Cloud Run'), )}</a>`, }, diff --git a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue index c31ba7ef14a..bdbaf2ed558 100644 --- a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue +++ b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue @@ -1,5 +1,5 @@ <script> -import _ from 'underscore'; +import { escape as esc } from 'lodash'; import SplitButton from '~/vue_shared/components/split_button.vue'; import { GlModal, GlButton, GlFormInput } from '@gitlab/ui'; import { s__, sprintf } from '~/locale'; @@ -82,7 +82,7 @@ export default { ) : s__('ClusterIntegration|To remove your integration, type %{clusterName} to confirm:'), { - clusterName: `<code>${_.escape(this.clusterName)}</code>`, + clusterName: `<code>${esc(this.clusterName)}</code>`, }, false, ); diff --git a/app/helpers/broadcast_messages_helper.rb b/app/helpers/broadcast_messages_helper.rb index 0c32b48a85a..881e11b10ea 100644 --- a/app/helpers/broadcast_messages_helper.rb +++ b/app/helpers/broadcast_messages_helper.rb @@ -47,7 +47,7 @@ module BroadcastMessagesHelper end def render_broadcast_message(broadcast_message) - if Feature.enabled?(:broadcast_message_placeholders) + if broadcast_message.notification? Banzai.render_field_and_post_process(broadcast_message, :message, { current_user: current_user, skip_project_check: true, diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index 456cc589477..80991657688 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -220,7 +220,7 @@ module MergeRequests def append_closes_description return unless issue&.to_reference.present? - closes_issue = "Closes #{issue.to_reference}" + closes_issue = "#{target_project.autoclose_referenced_issues ? 'Closes' : 'Related to'} #{issue.to_reference}" if description.present? descr_parts = [merge_request.description, closes_issue] diff --git a/bin/secpick b/bin/secpick index 603c6d2c05d..a68dabc8c47 100755 --- a/bin/secpick +++ b/bin/secpick @@ -12,10 +12,8 @@ module Secpick BRANCH_PREFIX = 'security'.freeze STABLE_SUFFIX = 'stable'.freeze - DEFAULT_REMOTE = 'dev'.freeze - SECURITY_REMOTE = 'security'.freeze + DEFAULT_REMOTE = 'security'.freeze - NEW_MR_URL = 'https://dev.gitlab.org/gitlab/gitlabhq/-/merge_requests/new'.freeze SECURITY_MR_URL = 'https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/new'.freeze class SecurityFix @@ -66,18 +64,10 @@ module Secpick end def new_mr_url - if @options[:security_remote] - if ee? - SECURITY_MR_URL - else - SECURITY_MR_URL.sub('/gitlab/', '/gitlab-foss/') - end + if ee? + SECURITY_MR_URL else - if ee? - NEW_MR_URL.sub('gitlabhq', 'gitlab-ee') - else - NEW_MR_URL - end + SECURITY_MR_URL.sub('/gitlab/', '/gitlab-foss/') end end @@ -124,19 +114,10 @@ module Secpick options[:sha] = sha end - opts.on('-r', '--remote abcd', 'Git remote name of dev.gitlab.org (optional, defaults to `dev`)') do |remote| + opts.on('-r', '--remote dev', "Git remote name of security repo (optional, defaults to `#{DEFAULT_REMOTE}`)") do |remote| options[:remote] = remote end - opts.on('--security-remote', 'Use the new Security group-based workflow on gitlab.com (note: mutually exclusive to --remote)') do - unless options[:remote].nil? - abort('Cannot use --security-remote with --remote') - end - - options[:security_remote] = true - options[:remote] = SECURITY_REMOTE - end - opts.on('-d', '--dry-run', 'Only show Git commands, without calling them') do options[:try] = true end @@ -144,11 +125,6 @@ module Secpick opts.on('-h', '--help', 'Displays Help') do puts opts - puts - puts 'NOTE: If `--security-remote` is used, commands will default ' \ - 'to using a `security` remote, and merge requests will be created ' \ - 'on gitlab.com/gitlab-org/security/ rather than dev.gitlab.org.' - exit end end diff --git a/changelogs/unreleased/nicolasdular-broadcast-placeholders-ff.yml b/changelogs/unreleased/nicolasdular-broadcast-placeholders-ff.yml new file mode 100644 index 00000000000..5355f3d2dc8 --- /dev/null +++ b/changelogs/unreleased/nicolasdular-broadcast-placeholders-ff.yml @@ -0,0 +1,5 @@ +--- +title: Add placeholders to broadcast message notifications +merge_request: +author: +type: added diff --git a/doc/api/access_requests.md b/doc/api/access_requests.md index 75622fcc2de..fd667073680 100644 --- a/doc/api/access_requests.md +++ b/doc/api/access_requests.md @@ -7,6 +7,7 @@ The access levels are defined in the `Gitlab::Access` module. Currently, these levels are recognized: ```plaintext +0 => No access 10 => Guest access 20 => Reporter access 30 => Developer access diff --git a/doc/development/performance.md b/doc/development/performance.md index 72eb85c623b..a7ae283432f 100644 --- a/doc/development/performance.md +++ b/doc/development/performance.md @@ -415,6 +415,84 @@ test += " world" When adding new Ruby files, please check that you can add the above header, as omitting it may lead to style check failures. +## Reading from files and other data sources + +Ruby offers several convenience functions that deal with file contents specifically +or I/O streams in general. Functions such as `IO.read` and `IO.readlines` make +it easy to read data into memory, but they can be inefficient when the +data grows large. Because these functions read the entire contents of a data +source into memory, memory use will grow by _at least_ the size of the data source. +In the case of `readlines`, it will grow even further, due to extra bookkeeping +the Ruby VM has to perform to represent each line. + +Consider the following program, which reads a text file that is 750MB on disk: + +```ruby +File.readlines('large_file.txt').each do |line| + puts line +end +``` + +Here is a process memory reading from while the program was running, showing +how we indeed kept the entire file in memory (RSS reported in kilobytes): + +```shell +$ ps -o rss -p <pid> + +RSS +783436 +``` + +And here is an excerpt of what the garbage collector was doing: + +```ruby +pp GC.stat + +{ + :heap_live_slots=>2346848, + :malloc_increase_bytes=>30895288, + ... +} +``` + +We can see that `heap_live_slots` (the number of reachable objects) jumped to ~2.3M, +which is roughly two orders of magnitude more compared to reading the file line by +line instead. It was not just the raw memory usage that increased, but also how the garbage collector (GC) +responded to this change in anticipation of future memory use. We can see that `malloc_increase_bytes` jumped +to ~30MB, which compares to just ~4kB for a "fresh" Ruby program. This figure specifies how +much additional heap space the Ruby GC will claim from the operating system next time it runs out of memory. +Not only did we occupy more memory, we also changed the behavior of the application +to increase memory use at a faster rate. + +The `IO.read` function exhibits similar behavior, with the difference that no extra memory will +be allocated for each line object. + +### Recommendations + +Instead of reading data sources into memory in full, it is better to read them line by line +instead. This is not always an option, for instance when you need to convert a YAML file +into a Ruby `Hash`, but whenever you have data where each row represents some entity that +can be processed and then discarded, you can use the following approaches. + +First, replace calls to `readlines.each` with either `each` or `each_line`. +The `each_line` and `each` functions read the data source line by line without keeping +already visited lines in memory: + +```ruby +File.new('file').each { |line| puts line } +``` + +Alternatively, you can read individual lines explicitly using `IO.readline` or `IO.gets` functions: + +```ruby +while line = file.readline + # process line +end +``` + +This might be preferable if there is a condition that allows exiting the loop early, saving not +just memory but also unnecessary time spent in CPU and I/O for processing lines you're not interested in. + ## Anti-Patterns This is a collection of [anti-patterns][anti-pattern] that should be avoided diff --git a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md index 4f0e506a964..f8dc3366904 100644 --- a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md +++ b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md @@ -13,3 +13,4 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec | `:quarantine` | The test has been [quarantined](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests), will run in a separate job that only includes quarantined tests, and is allowed to fail. The test will be skipped in its regular job so that if it fails it will not hold up the pipeline. | | `:reliable` | The test has been [promoted to a reliable test](https://about.gitlab.com/handbook/engineering/quality/guidelines/reliable-tests/#promoting-an-existing-test-to-reliable) meaning it passes consistently in all pipelines, including merge requests. | | `:requires_admin` | The test requires an admin account. Tests with the tag are excluded when run against Canary and Production environments. | +| `:runner` | The test depends on and will set up a GitLab Runner instance, typically to run a pipeline. | diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md index 5ba63cc07fa..141d1db1bf6 100644 --- a/doc/development/testing_guide/frontend_testing.md +++ b/doc/development/testing_guide/frontend_testing.md @@ -547,16 +547,26 @@ The more challenging part are mocks, which can be used for functions or even dep ### Manual module mocks -Jest supports [manual module mocks](https://jestjs.io/docs/en/manual-mocks) by placing a mock in a `__mocks__/` directory next to the source module. **Don't do this.** We want to keep all of our test-related code in one place (the `spec/` folder), and the logic that Jest uses to apply mocks from `__mocks__/` is rather inconsistent. +Manual mocks are used to mock modules across the entire Jest environment. This is a very powerful testing tool that helps simplify +unit testing by mocking out modules which cannot be easily consumned in our test environment. -Instead, our test runner detects manual mocks from `spec/frontend/mocks/`. Any mock placed here is automatically picked up and injected whenever you import its source module. +> NOTE: Do not use manual mocks if a mock should not be consistently applied (i.e. it's only needed by a few specs). +> Instead, consider using `jest.mock` in the relevant spec file. + +#### Where should I put manual mocks? + +Jest supports [manual module mocks](https://jestjs.io/docs/en/manual-mocks) by placing a mock in a `__mocks__/` directory next to the source module +(e.g. `app/assets/javascripts/ide/__mocks__`). **Don't do this.** We want to keep all of our test-related code in one place (the `spec/` folder). + +If a manual mock is needed for a `node_modules` package, please use the `spec/frontend/__mocks__` folder. Here's an example of +a [Jest mock for the package `monaco-editor`](https://gitlab.com/gitlab-org/gitlab/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js#L1). + +If a manual mock is needed for a CE module, please place it in `spec/frontend/mocks/ce`. - Files in `spec/frontend/mocks/ce` will mock the corresponding CE module from `app/assets/javascripts`, mirroring the source module's path. - Example: `spec/frontend/mocks/ce/lib/utils/axios_utils` will mock the module `~/lib/utils/axios_utils`. -- Files in `spec/frontend/mocks/node` will mock NPM packages of the same name or path. - We don't support mocking EE modules yet. - -If a mock is found for which a source module doesn't exist, the test suite will fail. 'Virtual' mocks, or mocks that don't have a 1-to-1 association with a source module, are not supported yet. +- If a mock is found for which a source module doesn't exist, the test suite will fail. 'Virtual' mocks, or mocks that don't have a 1-to-1 association with a source module, are not supported yet. ### Writing a mock diff --git a/doc/user/analytics/value_stream_analytics.md b/doc/user/analytics/value_stream_analytics.md index ade415ffb37..5d621fb7faf 100644 --- a/doc/user/analytics/value_stream_analytics.md +++ b/doc/user/analytics/value_stream_analytics.md @@ -205,8 +205,11 @@ This stage would not work because the end event has already happened when the st To prevent such invalid stages, the UI prohibits incompatible start and end events. After you select the start event, the stop event dropdown will only list the compatible events. -NOTE: **Note:** -The ability to re-order the stages is [planned](https://gitlab.com/gitlab-org/gitlab/issues/196698). +### Re-ordering stages + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196698) in GitLab 12.10. + +Once a custom stage has been added, you can "drag and drop" stages to rearrange their order. These changes are automatically saved to the system. ### Label based stages diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md index 2949a2d4fc8..b778a543935 100644 --- a/doc/user/profile/account/two_factor_authentication.md +++ b/doc/user/profile/account/two_factor_authentication.md @@ -260,6 +260,8 @@ Sign in and re-enable two-factor authentication as soon as possible. - The user logs out and attempts to log in via `second.host.xyz` - U2F authentication fails, because the U2F key has only been registered on `first.host.xyz`. +- To enforce 2FA at the system or group levels see [Enforce Two-factor Authentication](../../../security/two_factor_authentication.md). + ## Troubleshooting If you are receiving an `invalid pin code` error, this may indicate that there is a time sync issue between the authentication application and the GitLab instance itself. diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb index 05adcc718e8..2502e8beda7 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module QA - context 'Verify', :docker do + context 'Verify', :docker, :runner do describe 'Pipeline creation and processing' do let(:executor) { "qa-runner-#{Time.now.to_i}" } let(:max_wait) { 30 } @@ -12,7 +12,7 @@ module QA end end - before do + let!(:runner) do Resource::Runner.fabricate! do |runner| runner.project = project runner.name = executor @@ -21,7 +21,7 @@ module QA end after do - Service::DockerRun::GitlabRunner.new(executor).remove! + runner.remove_via_api! end it 'users creates a pipeline which gets processed', :smoke do diff --git a/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb index fb1ee4446a9..2550ee7193b 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb @@ -1,20 +1,23 @@ # frozen_string_literal: true module QA - context 'Verify', :docker do + context 'Verify', :docker, :runner do describe 'Runner registration' do let(:executor) { "qa-runner-#{Time.now.to_i}" } + let!(:runner) do + Resource::Runner.fabricate! do |runner| + runner.name = executor + end + end after do - Service::DockerRun::GitlabRunner.new(executor).remove! + runner.remove_via_api! end it 'user registers a new specific runner' do Flow::Login.sign_in - Resource::Runner.fabricate! do |runner| - runner.name = executor - end.project.visit! + runner.project.visit! Page::Project::Menu.perform(&:go_to_ci_cd_settings) Page::Project::Settings::CICD.perform do |settings| 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 581e6b8299e..73f2fef5f1d 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 @@ -3,7 +3,7 @@ require 'digest/sha1' module QA - context 'Release', :docker do + context 'Release', :docker, :runner do describe 'Git clone using a deploy key' do before do Flow::Login.sign_in @@ -16,7 +16,7 @@ module QA @repository_location = @project.repository_ssh_location - Resource::Runner.fabricate_via_api! do |resource| + @runner = Resource::Runner.fabricate_via_api! do |resource| resource.project = @project resource.name = @runner_name resource.tags = %w[qa docker] @@ -25,7 +25,7 @@ module QA end after do - Service::DockerRun::GitlabRunner.new(@runner_name).remove! + @runner.remove_via_api! end keys = [ diff --git a/spec/features/broadcast_messages_spec.rb b/spec/features/broadcast_messages_spec.rb index 41e8e969610..c770e6e4f81 100644 --- a/spec/features/broadcast_messages_spec.rb +++ b/spec/features/broadcast_messages_spec.rb @@ -3,12 +3,23 @@ require 'spec_helper' describe 'Broadcast Messages' do - shared_examples 'a Broadcast Messages' do + let_it_be(:user) { create(:user) } + + shared_examples 'a Broadcast Messages' do |type| it 'shows broadcast message' do visit root_path expect(page).to have_content 'SampleMessage' end + + it 'renders styled links' do + create(:broadcast_message, type, message: "<a href='gitlab.com' style='color: purple'>click me</a>") + + visit root_path + + expected_html = "<p><a href=\"gitlab.com\" style=\"color: purple\">click me</a></p>" + expect(page.body).to include(expected_html) + end end shared_examples 'a dismissable Broadcast Messages' do @@ -35,11 +46,21 @@ describe 'Broadcast Messages' do it_behaves_like 'a Broadcast Messages' - it 'shows broadcast message' do + it 'is not dismissable' do visit root_path expect(page).not_to have_selector('.js-dismiss-current-broadcast-notification') end + + it 'does not replace placeholders' do + create(:broadcast_message, message: 'Hi {{name}}') + + sign_in(user) + + visit root_path + + expect(page).to have_content 'Hi {{name}}' + end end describe 'dismissable banner type' do @@ -51,33 +72,20 @@ describe 'Broadcast Messages' do end describe 'notification type' do - let!(:broadcast_message) { create(:broadcast_message, broadcast_type: 'notification', message: 'SampleMessage') } + let!(:broadcast_message) { create(:broadcast_message, :notification, message: 'SampleMessage') } - it_behaves_like 'a Broadcast Messages' + it_behaves_like 'a Broadcast Messages', :notification it_behaves_like 'a dismissable Broadcast Messages' - end - - it 'renders broadcast message with placeholders' do - create(:broadcast_message, broadcast_type: 'notification', message: 'Hi {{name}}') - user = create(:user) - sign_in(user) + it 'replaces placeholders' do + create(:broadcast_message, :notification, message: 'Hi {{name}}') - visit root_path + sign_in(user) - expect(page).to have_content "Hi #{user.name}" - end - - it 'renders broadcast message with placeholders and styled links' do - create(:broadcast_message, broadcast_type: 'notification', message: "Hi {{name}} <a href='gitlab.com' style='color: purple'>click</a>") - - user = create(:user) - sign_in(user) - - visit root_path + visit root_path - expected_html = "<p>Hi #{user.name} <a href=\"gitlab.com\" style=\"color: purple\">click</a></p>" - expect(page.body).to include(expected_html) + expect(page).to have_content "Hi #{user.name}" + end end end diff --git a/spec/frontend/mocks/mocks_helper.js b/spec/frontend/mocks/mocks_helper.js index 21c032cd3c9..823ab41a5ba 100644 --- a/spec/frontend/mocks/mocks_helper.js +++ b/spec/frontend/mocks/mocks_helper.js @@ -16,7 +16,6 @@ const prefixMap = [ // E.g. the mock ce/foo/bar maps to require path ~/foo/bar { mocksRoot: 'ce', requirePrefix: '~' }, // { mocksRoot: 'ee', requirePrefix: 'ee' }, // We'll deal with EE-specific mocks later - { mocksRoot: 'node', requirePrefix: '' }, // { mocksRoot: 'virtual', requirePrefix: '' }, // We'll deal with virtual mocks later ]; diff --git a/spec/frontend/mocks/mocks_helper_spec.js b/spec/frontend/mocks/mocks_helper_spec.js index 82e88b712c0..a91e8ecfa4a 100644 --- a/spec/frontend/mocks/mocks_helper_spec.js +++ b/spec/frontend/mocks/mocks_helper_spec.js @@ -34,9 +34,8 @@ describe('mocks_helper.js', () => { it('enumerates through mock file roots', () => { setupManualMocks(); - expect(fs.existsSync).toHaveBeenCalledTimes(2); + expect(fs.existsSync).toHaveBeenCalledTimes(1); expect(fs.existsSync).toHaveBeenNthCalledWith(1, absPath('ce')); - expect(fs.existsSync).toHaveBeenNthCalledWith(2, absPath('node')); expect(readdir.sync).toHaveBeenCalledTimes(0); }); @@ -66,19 +65,6 @@ describe('mocks_helper.js', () => { expect(setMock).toHaveBeenNthCalledWith(2, '~/lib/utils/util', './ce/lib/utils/util'); }); - it('sets up mocks for node_modules', () => { - fs.existsSync.mockImplementation(root => root.endsWith('node')); - readdir.sync.mockReturnValue(['jquery', '@babel/core']); - setupManualMocks(); - - expect(readdir.sync).toHaveBeenCalledTimes(1); - expect(readdir.sync.mock.calls[0][0]).toBe(absPath('node')); - - expect(setMock).toHaveBeenCalledTimes(2); - expect(setMock).toHaveBeenNthCalledWith(1, 'jquery', './node/jquery'); - expect(setMock).toHaveBeenNthCalledWith(2, '@babel/core', './node/@babel/core'); - }); - it('sets up mocks for all roots', () => { const files = { [absPath('ce')]: ['root', 'lib/utils/util'], @@ -89,15 +75,12 @@ describe('mocks_helper.js', () => { readdir.sync.mockImplementation(root => files[root]); setupManualMocks(); - expect(readdir.sync).toHaveBeenCalledTimes(2); + expect(readdir.sync).toHaveBeenCalledTimes(1); expect(readdir.sync.mock.calls[0][0]).toBe(absPath('ce')); - expect(readdir.sync.mock.calls[1][0]).toBe(absPath('node')); - expect(setMock).toHaveBeenCalledTimes(4); + expect(setMock).toHaveBeenCalledTimes(2); expect(setMock).toHaveBeenNthCalledWith(1, '~/root', './ce/root'); expect(setMock).toHaveBeenNthCalledWith(2, '~/lib/utils/util', './ce/lib/utils/util'); - expect(setMock).toHaveBeenNthCalledWith(3, 'jquery', './node/jquery'); - expect(setMock).toHaveBeenNthCalledWith(4, '@babel/core', './node/@babel/core'); }); it('fails when given a virtual mock', () => { |