diff options
Diffstat (limited to 'spec/support')
-rw-r--r-- | spec/support/api/time_tracking_shared_examples.rb | 132 | ||||
-rw-r--r-- | spec/support/cycle_analytics_helpers/test_generation.rb | 13 | ||||
-rw-r--r-- | spec/support/javascript_fixtures_helpers.rb | 21 | ||||
-rw-r--r-- | spec/support/matchers/be_valid_commit.rb | 8 | ||||
-rw-r--r-- | spec/support/notify_shared_examples.rb | 17 | ||||
-rw-r--r-- | spec/support/reactive_caching_helpers.rb | 30 | ||||
-rw-r--r-- | spec/support/seed_helper.rb | 112 | ||||
-rw-r--r-- | spec/support/seed_repo.rb | 143 | ||||
-rw-r--r-- | spec/support/sidekiq.rb | 5 | ||||
-rw-r--r-- | spec/support/stub_env.rb | 7 | ||||
-rw-r--r-- | spec/support/taskable_shared_examples.rb | 24 | ||||
-rw-r--r-- | spec/support/test_env.rb | 3 | ||||
-rw-r--r-- | spec/support/time_tracking_shared_examples.rb | 82 |
13 files changed, 571 insertions, 26 deletions
diff --git a/spec/support/api/time_tracking_shared_examples.rb b/spec/support/api/time_tracking_shared_examples.rb new file mode 100644 index 00000000000..210cd5817e0 --- /dev/null +++ b/spec/support/api/time_tracking_shared_examples.rb @@ -0,0 +1,132 @@ +shared_examples 'an unauthorized API user' do + it { is_expected.to eq(403) } +end + +shared_examples 'time tracking endpoints' do |issuable_name| + issuable_collection_name = issuable_name.pluralize + + describe "POST /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/time_estimate" do + context 'with an unauthorized user' do + subject { post(api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_estimate", non_member), duration: '1w') } + + it_behaves_like 'an unauthorized API user' + end + + it "sets the time estimate for #{issuable_name}" do + post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_estimate", user), duration: '1w' + + expect(response).to have_http_status(200) + expect(json_response['human_time_estimate']).to eq('1w') + end + + describe 'updating the current estimate' do + before do + post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_estimate", user), duration: '1w' + end + + context 'when duration has a bad format' do + it 'does not modify the original estimate' do + post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_estimate", user), duration: 'foo' + + expect(response).to have_http_status(400) + expect(issuable.reload.human_time_estimate).to eq('1w') + end + end + + context 'with a valid duration' do + it 'updates the estimate' do + post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_estimate", user), duration: '3w1h' + + expect(response).to have_http_status(200) + expect(issuable.reload.human_time_estimate).to eq('3w 1h') + end + end + end + end + + describe "POST /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/reset_time_estimate" do + context 'with an unauthorized user' do + subject { post(api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/reset_time_estimate", non_member)) } + + it_behaves_like 'an unauthorized API user' + end + + it "resets the time estimate for #{issuable_name}" do + post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/reset_time_estimate", user) + + expect(response).to have_http_status(200) + expect(json_response['time_estimate']).to eq(0) + end + end + + describe "POST /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/add_spent_time" do + context 'with an unauthorized user' do + subject do + post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/add_spent_time", non_member), + duration: '2h' + end + + it_behaves_like 'an unauthorized API user' + end + + it "add spent time for #{issuable_name}" do + post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/add_spent_time", user), + duration: '2h' + + expect(response).to have_http_status(201) + expect(json_response['human_total_time_spent']).to eq('2h') + end + + context 'when subtracting time' do + it 'subtracts time of the total spent time' do + issuable.update_attributes!(spend_time: { duration: 7200, user: user }) + + post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/add_spent_time", user), + duration: '-1h' + + expect(response).to have_http_status(201) + expect(json_response['total_time_spent']).to eq(3600) + end + end + + context 'when time to subtract is greater than the total spent time' do + it 'does not modify the total time spent' do + issuable.update_attributes!(spend_time: { duration: 7200, user: user }) + + post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/add_spent_time", user), + duration: '-1w' + + expect(response).to have_http_status(400) + expect(json_response['message']['time_spent'].first).to match(/exceeds the total time spent/) + end + end + end + + describe "POST /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/reset_spent_time" do + context 'with an unauthorized user' do + subject { post(api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/reset_spent_time", non_member)) } + + it_behaves_like 'an unauthorized API user' + end + + it "resets spent time for #{issuable_name}" do + post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/reset_spent_time", user) + + expect(response).to have_http_status(200) + expect(json_response['total_time_spent']).to eq(0) + end + end + + describe "GET /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/time_stats" do + it "returns the time stats for #{issuable_name}" do + issuable.update_attributes!(spend_time: { duration: 1800, user: user }, + time_estimate: 3600) + + get api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_stats", user) + + expect(response).to have_http_status(200) + expect(json_response['total_time_spent']).to eq(1800) + expect(json_response['time_estimate']).to eq(3600) + end + end +end diff --git a/spec/support/cycle_analytics_helpers/test_generation.rb b/spec/support/cycle_analytics_helpers/test_generation.rb index 8e19a6c92e2..35b40d73191 100644 --- a/spec/support/cycle_analytics_helpers/test_generation.rb +++ b/spec/support/cycle_analytics_helpers/test_generation.rb @@ -2,7 +2,6 @@ # Note: The ABC size is large here because we have a method generating test cases with # multiple nested contexts. This shouldn't count as a violation. - module CycleAnalyticsHelpers module TestGeneration # Generate the most common set of specs that all cycle analytics phases need to have. @@ -51,7 +50,7 @@ module CycleAnalyticsHelpers end median_time_difference = time_differences.sort[2] - expect(subject.send(phase)).to be_within(5).of(median_time_difference) + expect(subject[phase].median).to be_within(5).of(median_time_difference) end context "when the data belongs to another project" do @@ -83,7 +82,7 @@ module CycleAnalyticsHelpers # Turn off the stub before checking assertions allow(self).to receive(:project).and_call_original - expect(subject.send(phase)).to be_nil + expect(subject[phase].median).to be_nil end end @@ -106,7 +105,7 @@ module CycleAnalyticsHelpers Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn - expect(subject.send(phase)).to be_nil + expect(subject[phase].median).to be_nil end end end @@ -126,7 +125,7 @@ module CycleAnalyticsHelpers Timecop.freeze(end_time + 1.day) { post_fn[self, data] } if post_fn end - expect(subject.send(phase)).to be_nil + expect(subject[phase].median).to be_nil end end end @@ -145,7 +144,7 @@ module CycleAnalyticsHelpers post_fn[self, data] if post_fn end - expect(subject.send(phase)).to be_nil + expect(subject[phase].median).to be_nil end end end @@ -153,7 +152,7 @@ module CycleAnalyticsHelpers context "when none of the start / end conditions are matched" do it "returns nil" do - expect(subject.send(phase)).to be_nil + expect(subject[phase].median).to be_nil end end end diff --git a/spec/support/javascript_fixtures_helpers.rb b/spec/support/javascript_fixtures_helpers.rb index 99e98eebdb4..0b8729db0f9 100644 --- a/spec/support/javascript_fixtures_helpers.rb +++ b/spec/support/javascript_fixtures_helpers.rb @@ -20,12 +20,26 @@ module JavaScriptFixturesHelpers # Public: Store a response object as fixture file # - # response - response object to store + # response - string or response object to store # fixture_file_name - file name to store the fixture in (relative to FIXTURE_PATH) # def store_frontend_fixture(response, fixture_file_name) fixture_file_name = File.expand_path(fixture_file_name, FIXTURE_PATH) + fixture = response.respond_to?(:body) ? parse_response(response) : response + + FileUtils.mkdir_p(File.dirname(fixture_file_name)) + File.write(fixture_file_name, fixture) + end + + private + + # Private: Prepare a response object for use as a frontend fixture + # + # response - response object to prepare + # + def parse_response(response) fixture = response.body + fixture.force_encoding("utf-8") response_mime_type = Mime::Type.lookup(response.content_type) if response_mime_type.html? @@ -34,7 +48,7 @@ module JavaScriptFixturesHelpers link_tags = doc.css('link') link_tags.remove - scripts = doc.css('script') + scripts = doc.css("script:not([type='text/template'])") scripts.remove fixture = doc.to_html @@ -44,7 +58,6 @@ module JavaScriptFixturesHelpers fixture.gsub!(%r{="/}, "=\"http://#{test_host}/") end - FileUtils.mkdir_p(File.dirname(fixture_file_name)) - File.write(fixture_file_name, fixture) + fixture end end diff --git a/spec/support/matchers/be_valid_commit.rb b/spec/support/matchers/be_valid_commit.rb new file mode 100644 index 00000000000..3696e4d5f03 --- /dev/null +++ b/spec/support/matchers/be_valid_commit.rb @@ -0,0 +1,8 @@ +RSpec::Matchers.define :be_valid_commit do + match do |actual| + actual && + actual.id == SeedRepo::Commit::ID && + actual.message == SeedRepo::Commit::MESSAGE && + actual.author_name == SeedRepo::Commit::AUTHOR_FULL_NAME + end +end diff --git a/spec/support/notify_shared_examples.rb b/spec/support/notify_shared_examples.rb index 49867aa5cc4..a3724b801b3 100644 --- a/spec/support/notify_shared_examples.rb +++ b/spec/support/notify_shared_examples.rb @@ -179,9 +179,24 @@ shared_examples 'it should show Gmail Actions View Commit link' do end shared_examples 'an unsubscribeable thread' do + it_behaves_like 'an unsubscribeable thread with incoming address without %{key}' + + it 'has a List-Unsubscribe header in the correct format' do + is_expected.to have_header 'List-Unsubscribe', /unsubscribe/ + is_expected.to have_header 'List-Unsubscribe', /mailto/ + is_expected.to have_header 'List-Unsubscribe', /^<.+,.+>$/ + end + + it { is_expected.to have_body_text /unsubscribe/ } +end + +shared_examples 'an unsubscribeable thread with incoming address without %{key}' do + include_context 'reply-by-email is enabled with incoming address without %{key}' + it 'has a List-Unsubscribe header in the correct format' do is_expected.to have_header 'List-Unsubscribe', /unsubscribe/ - is_expected.to have_header 'List-Unsubscribe', /^<.+>$/ + is_expected.not_to have_header 'List-Unsubscribe', /mailto/ + is_expected.to have_header 'List-Unsubscribe', /^<[^,]+>$/ end it { is_expected.to have_body_text /unsubscribe/ } diff --git a/spec/support/reactive_caching_helpers.rb b/spec/support/reactive_caching_helpers.rb index 279db3c5748..98eb57f8b54 100644 --- a/spec/support/reactive_caching_helpers.rb +++ b/spec/support/reactive_caching_helpers.rb @@ -3,31 +3,35 @@ module ReactiveCachingHelpers ([subject.class.reactive_cache_key.call(subject)].flatten + qualifiers).join(':') end - def stub_reactive_cache(subject = nil, data = nil) + def alive_reactive_cache_key(subject, *qualifiers) + reactive_cache_key(subject, *(qualifiers + ['alive'])) + end + + def stub_reactive_cache(subject = nil, data = nil, *qualifiers) allow(ReactiveCachingWorker).to receive(:perform_async) allow(ReactiveCachingWorker).to receive(:perform_in) - write_reactive_cache(subject, data) if data + write_reactive_cache(subject, data, *qualifiers) if data end - def read_reactive_cache(subject) - Rails.cache.read(reactive_cache_key(subject)) + def read_reactive_cache(subject, *qualifiers) + Rails.cache.read(reactive_cache_key(subject, *qualifiers)) end - def write_reactive_cache(subject, data) - start_reactive_cache_lifetime(subject) - Rails.cache.write(reactive_cache_key(subject), data) + def write_reactive_cache(subject, data, *qualifiers) + start_reactive_cache_lifetime(subject, *qualifiers) + Rails.cache.write(reactive_cache_key(subject, *qualifiers), data) end - def reactive_cache_alive?(subject) - Rails.cache.read(reactive_cache_key(subject, 'alive')) + def reactive_cache_alive?(subject, *qualifiers) + Rails.cache.read(alive_reactive_cache_key(subject, *qualifiers)) end - def invalidate_reactive_cache(subject) - Rails.cache.delete(reactive_cache_key(subject, 'alive')) + def invalidate_reactive_cache(subject, *qualifiers) + Rails.cache.delete(alive_reactive_cache_key(subject, *qualifiers)) end - def start_reactive_cache_lifetime(subject) - Rails.cache.write(reactive_cache_key(subject, 'alive'), true) + def start_reactive_cache_lifetime(subject, *qualifiers) + Rails.cache.write(alive_reactive_cache_key(subject, *qualifiers), true) end def expect_reactive_cache_update_queued(subject) diff --git a/spec/support/seed_helper.rb b/spec/support/seed_helper.rb new file mode 100644 index 00000000000..03fa0a66b9a --- /dev/null +++ b/spec/support/seed_helper.rb @@ -0,0 +1,112 @@ +# This file is specific to specs in spec/lib/gitlab/git/ + +SEED_REPOSITORY_PATH = File.expand_path('../../tmp/repositories', __dir__) +TEST_REPO_PATH = File.join(SEED_REPOSITORY_PATH, 'gitlab-git-test.git') +TEST_NORMAL_REPO_PATH = File.join(SEED_REPOSITORY_PATH, "not-bare-repo.git") +TEST_MUTABLE_REPO_PATH = File.join(SEED_REPOSITORY_PATH, "mutable-repo.git") +TEST_BROKEN_REPO_PATH = File.join(SEED_REPOSITORY_PATH, "broken-repo.git") + +module SeedHelper + GITLAB_URL = "https://gitlab.com/gitlab-org/gitlab-git-test.git" + + def ensure_seeds + if File.exist?(SEED_REPOSITORY_PATH) + FileUtils.rm_r(SEED_REPOSITORY_PATH) + end + + FileUtils.mkdir_p(SEED_REPOSITORY_PATH) + + create_bare_seeds + create_normal_seeds + create_mutable_seeds + create_broken_seeds + create_git_attributes + create_invalid_git_attributes + end + + def create_bare_seeds + system(git_env, *%W(#{Gitlab.config.git.bin_path} clone --bare #{GITLAB_URL}), + chdir: SEED_REPOSITORY_PATH, + out: '/dev/null', + err: '/dev/null') + end + + def create_normal_seeds + system(git_env, *%W(#{Gitlab.config.git.bin_path} clone #{TEST_REPO_PATH} #{TEST_NORMAL_REPO_PATH}), + out: '/dev/null', + err: '/dev/null') + end + + def create_mutable_seeds + system(git_env, *%W(#{Gitlab.config.git.bin_path} clone #{TEST_REPO_PATH} #{TEST_MUTABLE_REPO_PATH}), + out: '/dev/null', + err: '/dev/null') + + system(git_env, *%w(git branch -t feature origin/feature), + chdir: TEST_MUTABLE_REPO_PATH, out: '/dev/null', err: '/dev/null') + + system(git_env, *%W(#{Gitlab.config.git.bin_path} remote add expendable #{GITLAB_URL}), + chdir: TEST_MUTABLE_REPO_PATH, out: '/dev/null', err: '/dev/null') + end + + def create_broken_seeds + system(git_env, *%W(#{Gitlab.config.git.bin_path} clone --bare #{TEST_REPO_PATH} #{TEST_BROKEN_REPO_PATH}), + out: '/dev/null', + err: '/dev/null') + + refs_path = File.join(TEST_BROKEN_REPO_PATH, 'refs') + + FileUtils.rm_r(refs_path) + end + + def create_git_attributes + dir = File.join(SEED_REPOSITORY_PATH, 'with-git-attributes.git', 'info') + + FileUtils.mkdir_p(dir) + + File.open(File.join(dir, 'attributes'), 'w') do |handle| + handle.write <<-EOF.strip +# This is a comment, it should be ignored. + +*.txt text +*.jpg -text +*.sh eol=lf gitlab-language=shell +*.haml.* gitlab-language=haml +foo/bar.* foo +*.cgi key=value?p1=v1&p2=v2 +/*.png gitlab-language=png +*.binary binary + +# This uses a tab instead of spaces to ensure the parser also supports this. +*.md\tgitlab-language=markdown +bla/bla.txt + EOF + end + end + + def create_invalid_git_attributes + dir = File.join(SEED_REPOSITORY_PATH, 'with-invalid-git-attributes.git', 'info') + + FileUtils.mkdir_p(dir) + + enc = Encoding::UTF_16 + + File.open(File.join(dir, 'attributes'), 'w', encoding: enc) do |handle| + handle.write('# hello'.encode(enc)) + end + end + + # Prevent developer git configurations from being persisted to test + # repositories + def git_env + { 'GIT_TEMPLATE_DIR' => '' } + end +end + +RSpec.configure do |config| + config.include SeedHelper, :seed_helper + + config.before(:all, :seed_helper) do + ensure_seeds + end +end diff --git a/spec/support/seed_repo.rb b/spec/support/seed_repo.rb new file mode 100644 index 00000000000..9f2cd7c67c5 --- /dev/null +++ b/spec/support/seed_repo.rb @@ -0,0 +1,143 @@ +# Seed repo: +# 0e50ec4d3c7ce42ab74dda1d422cb2cbffe1e326 Merge branch 'lfs_pointers' into 'master' +# 33bcff41c232a11727ac6d660bd4b0c2ba86d63d Add valid and invalid lfs pointers +# 732401c65e924df81435deb12891ef570167d2e2 Update year in license file +# b0e52af38d7ea43cf41d8a6f2471351ac036d6c9 Empty commit +# 40f4a7a617393735a95a0bb67b08385bc1e7c66d Add ISO-8859-encoded file +# 66028349a123e695b589e09a36634d976edcc5e8 Merge branch 'add-comments-to-gitmodules' into 'master' +# de5714f34c4e34f1d50b9a61a2e6c9132fe2b5fd Add comments to the end of .gitmodules to test parsing +# fa1b1e6c004a68b7d8763b86455da9e6b23e36d6 Merge branch 'add-files' into 'master' +# eb49186cfa5c4338011f5f590fac11bd66c5c631 Add submodules nested deeper than the root +# 18d9c205d0d22fdf62bc2f899443b83aafbf941f Add executables and links files +# 5937ac0a7beb003549fc5fd26fc247adbce4a52e Add submodule from gitlab.com +# 570e7b2abdd848b95f2f578043fc23bd6f6fd24d Change some files +# 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 More submodules +# d14d6c0abdd253381df51a723d58691b2ee1ab08 Remove ds_store files +# c1acaa58bbcbc3eafe538cb8274ba387047b69f8 Ignore DS files +# ae73cb07c9eeaf35924a10f713b364d32b2dd34f Binary file added +# 874797c3a73b60d2187ed6e2fcabd289ff75171e Ruby files modified +# 2f63565e7aac07bcdadb654e253078b727143ec4 Modified image +# 33f3729a45c02fc67d00adb1b8bca394b0e761d9 Image added +# 913c66a37b4a45b9769037c55c2d238bd0942d2e Files, encoding and much more +# cfe32cf61b73a0d5e9f13e774abde7ff789b1660 Add submodule +# 6d394385cf567f80a8fd85055db1ab4c5295806f Added contributing guide +# 1a0b36b3cdad1d2ee32457c102a8c0b7056fa863 Initial commit + +module SeedRepo + module BigCommit + ID = "913c66a37b4a45b9769037c55c2d238bd0942d2e" + PARENT_ID = "cfe32cf61b73a0d5e9f13e774abde7ff789b1660" + MESSAGE = "Files, encoding and much more" + AUTHOR_FULL_NAME = "Dmitriy Zaporozhets" + FILES_COUNT = 2 + end + + module Commit + ID = "570e7b2abdd848b95f2f578043fc23bd6f6fd24d" + PARENT_ID = "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9" + MESSAGE = "Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n" + AUTHOR_FULL_NAME = "Dmitriy Zaporozhets" + FILES = ["files/ruby/popen.rb", "files/ruby/regex.rb"] + FILES_COUNT = 2 + C_FILE_PATH = "files/ruby" + C_FILES = ["popen.rb", "regex.rb", "version_info.rb"] + BLOB_FILE = %{%h3= @key.title\n%hr\n%pre= @key.key\n.actions\n = link_to 'Remove', @key, :confirm => 'Are you sure?', :method => :delete, :class => \"btn danger delete-key\"\n\n\n} + BLOB_FILE_PATH = "app/views/keys/show.html.haml" + end + + module EmptyCommit + ID = "b0e52af38d7ea43cf41d8a6f2471351ac036d6c9" + PARENT_ID = "40f4a7a617393735a95a0bb67b08385bc1e7c66d" + MESSAGE = "Empty commit" + AUTHOR_FULL_NAME = "Rémy Coutable" + FILES = [] + FILES_COUNT = FILES.count + end + + module EncodingCommit + ID = "40f4a7a617393735a95a0bb67b08385bc1e7c66d" + PARENT_ID = "66028349a123e695b589e09a36634d976edcc5e8" + MESSAGE = "Add ISO-8859-encoded file" + AUTHOR_FULL_NAME = "Stan Hu" + FILES = ["encoding/iso8859.txt"] + FILES_COUNT = FILES.count + end + + module FirstCommit + ID = "1a0b36b3cdad1d2ee32457c102a8c0b7056fa863" + PARENT_ID = nil + MESSAGE = "Initial commit" + AUTHOR_FULL_NAME = "Dmitriy Zaporozhets" + FILES = ["LICENSE", ".gitignore", "README.md"] + FILES_COUNT = 3 + end + + module LastCommit + ID = "4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6" + PARENT_ID = "0e1b353b348f8477bdbec1ef47087171c5032cd9" + MESSAGE = "Merge branch 'master' into 'master'" + AUTHOR_FULL_NAME = "Stan Hu" + FILES = ["bin/executable"] + FILES_COUNT = FILES.count + end + + module Repo + HEAD = "master" + BRANCHES = %w[ + feature + fix + fix-blob-path + fix-existing-submodule-dir + fix-mode + gitattributes + gitattributes-updated + master + merge-test + ] + TAGS = %w[v1.0.0 v1.1.0 v1.2.0 v1.2.1] + end + + module RubyBlob + ID = "7e3e39ebb9b2bf433b4ad17313770fbe4051649c" + NAME = "popen.rb" + CONTENT = <<-eos +require 'fileutils' +require 'open3' + +module Popen + extend self + + def popen(cmd, path=nil) + unless cmd.is_a?(Array) + raise RuntimeError, "System commands must be given as an array of strings" + end + + path ||= Dir.pwd + + vars = { + "PWD" => path + } + + options = { + chdir: path + } + + unless File.directory?(path) + FileUtils.mkdir_p(path) + end + + @cmd_output = "" + @cmd_status = 0 + + Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| + @cmd_output << stdout.read + @cmd_output << stderr.read + @cmd_status = wait_thr.value.exitstatus + end + + return @cmd_output, @cmd_status + end +end + eos + end +end diff --git a/spec/support/sidekiq.rb b/spec/support/sidekiq.rb new file mode 100644 index 00000000000..575d3451150 --- /dev/null +++ b/spec/support/sidekiq.rb @@ -0,0 +1,5 @@ +require 'sidekiq/testing/inline' + +Sidekiq::Testing.server_middleware do |chain| + chain.add Gitlab::SidekiqStatus::ServerMiddleware +end diff --git a/spec/support/stub_env.rb b/spec/support/stub_env.rb new file mode 100644 index 00000000000..18597b5c71f --- /dev/null +++ b/spec/support/stub_env.rb @@ -0,0 +1,7 @@ +module StubENV + def stub_env(key, value) + allow(ENV).to receive(:[]).and_call_original unless @env_already_stubbed + @env_already_stubbed ||= true + allow(ENV).to receive(:[]).with(key).and_return(value) + end +end diff --git a/spec/support/taskable_shared_examples.rb b/spec/support/taskable_shared_examples.rb index ad1c783df4d..1b6c33248c9 100644 --- a/spec/support/taskable_shared_examples.rb +++ b/spec/support/taskable_shared_examples.rb @@ -33,6 +33,30 @@ shared_examples 'a Taskable' do end end + describe 'with nested tasks' do + before do + subject.description = <<-EOT.strip_heredoc + - [ ] Task a + - [x] Task a.1 + - [ ] Task a.2 + - [ ] Task b + + 1. [ ] Task 1 + 1. [ ] Task 1.1 + 1. [ ] Task 1.2 + 1. [x] Task 2 + 1. [x] Task 2.1 + EOT + end + + it 'returns the correct task status' do + expect(subject.task_status).to match('3 of') + expect(subject.task_status).to match('9 tasks completed') + expect(subject.task_status_short).to match('3/') + expect(subject.task_status_short).to match('9 tasks') + end + end + describe 'with an incomplete task' do before do subject.description = <<-EOT.strip_heredoc diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 4cf81be3adc..90f1a9c8798 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -35,7 +35,8 @@ module TestEnv 'conflict-missing-side' => 'eb227b3', 'conflict-non-utf8' => 'd0a293c', 'conflict-too-large' => '39fa04f', - 'deleted-image-test' => '6c17798' + 'deleted-image-test' => '6c17798', + 'wip' => 'b9238ee' } # gitlab-test-fork is a fork of gitlab-fork, but we don't necessarily diff --git a/spec/support/time_tracking_shared_examples.rb b/spec/support/time_tracking_shared_examples.rb new file mode 100644 index 00000000000..02657684b57 --- /dev/null +++ b/spec/support/time_tracking_shared_examples.rb @@ -0,0 +1,82 @@ +shared_examples 'issuable time tracker' do + it 'renders the sidebar component empty state' do + page.within '.time-tracking-no-tracking-pane' do + expect(page).to have_content 'No estimate or time spent' + end + end + + it 'updates the sidebar component when estimate is added' do + submit_time('/estimate 3w 1d 1h') + + page.within '.time-tracking-estimate-only-pane' do + expect(page).to have_content '3w 1d 1h' + end + end + + it 'updates the sidebar component when spent is added' do + submit_time('/spend 3w 1d 1h') + + page.within '.time-tracking-spend-only-pane' do + expect(page).to have_content '3w 1d 1h' + end + end + + it 'shows the comparison when estimate and spent are added' do + submit_time('/estimate 3w 1d 1h') + submit_time('/spend 3w 1d 1h') + + page.within '.time-tracking-comparison-pane' do + expect(page).to have_content '3w 1d 1h' + end + end + + it 'updates the sidebar component when estimate is removed' do + submit_time('/estimate 3w 1d 1h') + submit_time('/remove_estimate') + + page.within '#issuable-time-tracker' do + expect(page).to have_content 'No estimate or time spent' + end + end + + it 'updates the sidebar component when spent is removed' do + submit_time('/spend 3w 1d 1h') + submit_time('/remove_time_spent') + + page.within '#issuable-time-tracker' do + expect(page).to have_content 'No estimate or time spent' + end + end + + it 'shows the help state when icon is clicked' do + page.within '#issuable-time-tracker' do + find('.help-button').click + expect(page).to have_content 'Track time with slash commands' + expect(page).to have_content 'Learn more' + end + end + + it 'hides the help state when close icon is clicked' do + page.within '#issuable-time-tracker' do + find('.help-button').click + find('.close-help-button').click + + expect(page).not_to have_content 'Track time with slash commands' + expect(page).not_to have_content 'Learn more' + end + end + + it 'displays the correct help url' do + page.within '#issuable-time-tracker' do + find('.help-button').click + + expect(find_link('Learn more')[:href]).to have_content('/help/workflow/time_tracking.md') + end + end +end + +def submit_time(slash_command) + fill_in 'note[note]', with: slash_command + click_button 'Comment' + wait_for_ajax +end |