Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 06:08:21 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 06:08:21 +0300
commit93c966ae2abeb481cfa894351b74f954e406582d (patch)
tree6e1b7619e3d5e7acac52e7de1135dd67d0cb53d5 /spec
parent48641d6d58d6d5d19b8b2ffc66646c7e94d552a1 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/frontend/boards/mock_data.js2
-rw-r--r--spec/frontend/boards/stores/actions_spec.js13
-rw-r--r--spec/helpers/analytics/unique_visits_helper_spec.rb34
-rw-r--r--spec/lib/gitlab/analytics/unique_visits_spec.rb81
-rw-r--r--spec/models/concerns/atomic_internal_id_spec.rb18
-rw-r--r--spec/models/internal_id_spec.rb279
-rw-r--r--spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb6
7 files changed, 163 insertions, 270 deletions
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index 73372eafb89..6ac4db8cdaa 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -291,7 +291,7 @@ export const setMockEndpoints = (opts = {}) => {
export const mockList = {
id: 'gid://gitlab/List/1',
- title: 'Backlog',
+ title: 'Open',
position: -Infinity,
listType: 'backlog',
collapsed: false,
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index ebed33e5b34..5e16e389ddc 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -715,6 +715,19 @@ describe('fetchItemsForList', () => {
[listId]: pageInfo,
};
+ describe('when list id is undefined', () => {
+ it('does not call the query', async () => {
+ jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
+
+ await actions.fetchItemsForList(
+ { state, getters: () => {}, commit: () => {} },
+ { listId: undefined },
+ );
+
+ expect(gqlClient.query).toHaveBeenCalledTimes(0);
+ });
+ });
+
it('should commit mutations REQUEST_ITEMS_FOR_LIST and RECEIVE_ITEMS_FOR_LIST_SUCCESS on success', (done) => {
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
diff --git a/spec/helpers/analytics/unique_visits_helper_spec.rb b/spec/helpers/analytics/unique_visits_helper_spec.rb
deleted file mode 100644
index b4b370c169d..00000000000
--- a/spec/helpers/analytics/unique_visits_helper_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe Analytics::UniqueVisitsHelper do
- include Devise::Test::ControllerHelpers
-
- describe '#track_visit' do
- let(:target_id) { 'p_analytics_valuestream' }
- let(:current_user) { create(:user) }
-
- it 'does not track visit if user is not logged in' do
- expect_any_instance_of(Gitlab::Analytics::UniqueVisits).not_to receive(:track_visit)
-
- helper.track_visit(target_id)
- end
-
- it 'tracks visit if user is logged in' do
- sign_in(current_user)
-
- expect_any_instance_of(Gitlab::Analytics::UniqueVisits).to receive(:track_visit)
-
- helper.track_visit(target_id)
- end
-
- it 'tracks visit if user is not logged in, but has the cookie already' do
- helper.request.cookies[:visitor_id] = { value: SecureRandom.uuid, expires: 24.months }
-
- expect_any_instance_of(Gitlab::Analytics::UniqueVisits).to receive(:track_visit)
-
- helper.track_visit(target_id)
- end
- end
-end
diff --git a/spec/lib/gitlab/analytics/unique_visits_spec.rb b/spec/lib/gitlab/analytics/unique_visits_spec.rb
deleted file mode 100644
index f4d5c0b1eca..00000000000
--- a/spec/lib/gitlab/analytics/unique_visits_spec.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Analytics::UniqueVisits, :clean_gitlab_redis_shared_state do
- let(:unique_visits) { Gitlab::Analytics::UniqueVisits.new }
- let(:target1_id) { 'g_analytics_contribution' }
- let(:target2_id) { 'g_analytics_insights' }
- let(:target3_id) { 'g_analytics_issues' }
- let(:target4_id) { 'g_compliance_dashboard' }
- let(:target5_id) { 'i_compliance_credential_inventory' }
- let(:visitor1_id) { 'dfb9d2d2-f56c-4c77-8aeb-6cddc4a1f857' }
- let(:visitor2_id) { '1dd9afb2-a3ee-4de1-8ae3-a405579c8584' }
- let(:visitor3_id) { '34rfjuuy-ce56-sa35-ds34-dfer567dfrf2' }
-
- around do |example|
- # We need to freeze to a reference time
- # because visits are grouped by the week number in the year
- # Without freezing the time, the test may behave inconsistently
- # depending on which day of the week test is run.
- reference_time = Time.utc(2020, 6, 1)
- travel_to(reference_time) { example.run }
- end
-
- describe '#track_visit' do
- it 'tracks the unique weekly visits for targets' do
- unique_visits.track_visit(target1_id, values: visitor1_id, time: 7.days.ago)
- unique_visits.track_visit(target1_id, values: visitor1_id, time: 7.days.ago)
- unique_visits.track_visit(target1_id, values: visitor2_id, time: 7.days.ago)
-
- unique_visits.track_visit(target2_id, values: visitor2_id, time: 7.days.ago)
- unique_visits.track_visit(target2_id, values: visitor1_id, time: 8.days.ago)
- unique_visits.track_visit(target2_id, values: visitor1_id, time: 15.days.ago)
-
- unique_visits.track_visit(target4_id, values: visitor3_id, time: 7.days.ago)
-
- unique_visits.track_visit(target5_id, values: visitor3_id, time: 15.days.ago)
- unique_visits.track_visit(target5_id, values: visitor2_id, time: 15.days.ago)
-
- expect(unique_visits.unique_visits_for(targets: target1_id)).to eq(2)
- expect(unique_visits.unique_visits_for(targets: target2_id)).to eq(1)
- expect(unique_visits.unique_visits_for(targets: target4_id)).to eq(1)
-
- expect(unique_visits.unique_visits_for(targets: target2_id, start_date: 15.days.ago)).to eq(1)
-
- expect(unique_visits.unique_visits_for(targets: target3_id)).to eq(0)
-
- expect(unique_visits.unique_visits_for(targets: target5_id, start_date: 15.days.ago)).to eq(2)
-
- expect(unique_visits.unique_visits_for(targets: :analytics)).to eq(2)
- expect(unique_visits.unique_visits_for(targets: :analytics, start_date: 15.days.ago)).to eq(1)
- expect(unique_visits.unique_visits_for(targets: :analytics, start_date: 30.days.ago)).to eq(0)
-
- expect(unique_visits.unique_visits_for(targets: :analytics, start_date: 4.weeks.ago, end_date: Date.current)).to eq(2)
-
- expect(unique_visits.unique_visits_for(targets: :compliance)).to eq(1)
- expect(unique_visits.unique_visits_for(targets: :compliance, start_date: 15.days.ago)).to eq(2)
- expect(unique_visits.unique_visits_for(targets: :compliance, start_date: 30.days.ago)).to eq(0)
-
- expect(unique_visits.unique_visits_for(targets: :compliance, start_date: 4.weeks.ago, end_date: Date.current)).to eq(2)
- end
-
- it 'sets the keys in Redis to expire automatically after 12 weeks' do
- unique_visits.track_visit(target1_id, values: visitor1_id)
-
- Gitlab::Redis::SharedState.with do |redis|
- redis.scan_each(match: "{#{target1_id}}-*").each do |key|
- expect(redis.ttl(key)).to be_within(5.seconds).of(12.weeks)
- end
- end
- end
-
- it 'raises an error if an invalid target id is given' do
- invalid_target_id = "x_invalid"
-
- expect do
- unique_visits.track_visit(invalid_target_id, values: visitor1_id)
- end.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent)
- end
- end
-end
diff --git a/spec/models/concerns/atomic_internal_id_spec.rb b/spec/models/concerns/atomic_internal_id_spec.rb
index 35b0f107676..b803e699b25 100644
--- a/spec/models/concerns/atomic_internal_id_spec.rb
+++ b/spec/models/concerns/atomic_internal_id_spec.rb
@@ -240,18 +240,12 @@ RSpec.describe AtomicInternalId do
end
describe '.with_project_iid_supply' do
- let(:iid) { 100 }
-
- it 'wraps generate and track_greatest in a concurrency-safe lock' do
- expect_next_instance_of(InternalId::InternalIdGenerator) do |g|
- expect(g).to receive(:with_lock).and_call_original
- expect(g.record).to receive(:last_value).and_return(iid)
- expect(g).to receive(:track_greatest).with(iid + 4)
- end
-
- ::Milestone.with_project_iid_supply(milestone.project) do |supply|
- 4.times { supply.next_value }
- end
+ it 'supplies a stream of iid values' do
+ expect do
+ ::Milestone.with_project_iid_supply(milestone.project) do |supply|
+ 4.times { supply.next_value }
+ end
+ end.to change { InternalId.find_by(project: milestone.project, usage: :milestones)&.last_value.to_i }.by(4)
end
end
end
diff --git a/spec/models/internal_id_spec.rb b/spec/models/internal_id_spec.rb
index 390d1552c16..696b5b48cbf 100644
--- a/spec/models/internal_id_spec.rb
+++ b/spec/models/internal_id_spec.rb
@@ -39,216 +39,217 @@ RSpec.describe InternalId do
end
end
- describe '.generate_next' do
- subject { described_class.generate_next(id_subject, scope, usage, init) }
+ shared_examples_for 'a monotonically increasing id generator' do
+ describe '.generate_next' do
+ subject { described_class.generate_next(id_subject, scope, usage, init) }
- context 'in the absence of a record' do
- it 'creates a record if not yet present' do
- expect { subject }.to change { described_class.count }.from(0).to(1)
- end
+ context 'in the absence of a record' do
+ it 'creates a record if not yet present' do
+ expect { subject }.to change { described_class.count }.from(0).to(1)
+ end
- it 'stores record attributes' do
- subject
+ it 'stores record attributes' do
+ subject
- described_class.first.tap do |record|
- expect(record.project).to eq(project)
- expect(record.usage).to eq(usage.to_s)
+ described_class.first.tap do |record|
+ expect(record.project).to eq(project)
+ expect(record.usage).to eq(usage.to_s)
+ end
end
- end
- context 'with existing issues' do
- before do
- create_list(:issue, 2, project: project)
- described_class.delete_all
- end
+ context 'with existing issues' do
+ before do
+ create_list(:issue, 2, project: project)
+ described_class.delete_all
+ end
- it 'calculates last_value values automatically' do
- expect(subject).to eq(project.issues.size + 1)
+ it 'calculates last_value values automatically' do
+ expect(subject).to eq(project.issues.size + 1)
+ end
end
end
- context 'with concurrent inserts on table' do
- it 'looks up the record if it was created concurrently' do
- args = { **scope, usage: described_class.usages[usage.to_s] }
- record = double
- expect(described_class).to receive(:find_by).with(args).and_return(nil) # first call, record not present
- expect(described_class).to receive(:find_by).with(args).and_return(record) # second call, record was created by another process
- expect(described_class).to receive(:create!).and_raise(ActiveRecord::RecordNotUnique, 'record not unique')
- expect(record).to receive(:increment_and_save!)
-
- subject
+ it 'generates a strictly monotone, gapless sequence' do
+ seq = Array.new(10).map do
+ described_class.generate_next(issue, scope, usage, init)
end
- end
- end
+ normalized = seq.map { |i| i - seq.min }
- it 'generates a strictly monotone, gapless sequence' do
- seq = Array.new(10).map do
- described_class.generate_next(issue, scope, usage, init)
+ expect(normalized).to eq((0..seq.size - 1).to_a)
end
- normalized = seq.map { |i| i - seq.min }
-
- expect(normalized).to eq((0..seq.size - 1).to_a)
- end
- context 'there are no instances to pass in' do
- let(:id_subject) { Issue }
+ context 'there are no instances to pass in' do
+ let(:id_subject) { Issue }
- it 'accepts classes instead' do
- expect(subject).to eq(1)
+ it 'accepts classes instead' do
+ expect(subject).to eq(1)
+ end
end
- end
- context 'when executed outside of transaction' do
- it 'increments counter with in_transaction: "false"' do
- allow(ActiveRecord::Base.connection).to receive(:transaction_open?) { false }
+ context 'when executed outside of transaction' do
+ it 'increments counter with in_transaction: "false"' do
+ allow(ActiveRecord::Base.connection).to receive(:transaction_open?) { false }
- expect(InternalId::InternalIdGenerator.internal_id_transactions_total).to receive(:increment)
- .with(operation: :generate, usage: 'issues', in_transaction: 'false').and_call_original
+ expect(InternalId.internal_id_transactions_total).to receive(:increment)
+ .with(operation: :generate, usage: 'issues', in_transaction: 'false').and_call_original
- subject
+ subject
+ end
end
- end
- context 'when executed within transaction' do
- it 'increments counter with in_transaction: "true"' do
- expect(InternalId::InternalIdGenerator.internal_id_transactions_total).to receive(:increment)
- .with(operation: :generate, usage: 'issues', in_transaction: 'true').and_call_original
+ context 'when executed within transaction' do
+ it 'increments counter with in_transaction: "true"' do
+ expect(InternalId.internal_id_transactions_total).to receive(:increment)
+ .with(operation: :generate, usage: 'issues', in_transaction: 'true').and_call_original
- InternalId.transaction { subject }
+ InternalId.transaction { subject }
+ end
end
end
- end
- describe '.reset' do
- subject { described_class.reset(issue, scope, usage, value) }
+ describe '.reset' do
+ subject { described_class.reset(issue, scope, usage, value) }
- context 'in the absence of a record' do
- let(:value) { 2 }
+ context 'in the absence of a record' do
+ let(:value) { 2 }
- it 'does not revert back the value' do
- expect { subject }.not_to change { described_class.count }
- expect(subject).to be_falsey
+ it 'does not revert back the value' do
+ expect { subject }.not_to change { described_class.count }
+ expect(subject).to be_falsey
+ end
end
- end
- context 'when valid iid is used to reset' do
- let!(:value) { generate_next }
+ context 'when valid iid is used to reset' do
+ let!(:value) { generate_next }
- context 'and iid is a latest one' do
- it 'does rewind and next generated value is the same' do
- expect(subject).to be_truthy
- expect(generate_next).to eq(value)
+ context 'and iid is a latest one' do
+ it 'does rewind and next generated value is the same' do
+ expect(subject).to be_truthy
+ expect(generate_next).to eq(value)
+ end
end
- end
- context 'and iid is not a latest one' do
- it 'does not rewind' do
- generate_next
+ context 'and iid is not a latest one' do
+ it 'does not rewind' do
+ generate_next
- expect(subject).to be_falsey
- expect(generate_next).to be > value
+ expect(subject).to be_falsey
+ expect(generate_next).to be > value
+ end
end
- end
- def generate_next
- described_class.generate_next(issue, scope, usage, init)
+ def generate_next
+ described_class.generate_next(issue, scope, usage, init)
+ end
end
- end
- context 'when executed outside of transaction' do
- let(:value) { 2 }
+ context 'when executed outside of transaction' do
+ let(:value) { 2 }
- it 'increments counter with in_transaction: "false"' do
- allow(ActiveRecord::Base.connection).to receive(:transaction_open?) { false }
+ it 'increments counter with in_transaction: "false"' do
+ allow(ActiveRecord::Base.connection).to receive(:transaction_open?) { false }
- expect(InternalId::InternalIdGenerator.internal_id_transactions_total).to receive(:increment)
- .with(operation: :reset, usage: 'issues', in_transaction: 'false').and_call_original
+ expect(InternalId.internal_id_transactions_total).to receive(:increment)
+ .with(operation: :reset, usage: 'issues', in_transaction: 'false').and_call_original
- subject
+ subject
+ end
end
- end
- context 'when executed within transaction' do
- let(:value) { 2 }
+ context 'when executed within transaction' do
+ let(:value) { 2 }
- it 'increments counter with in_transaction: "true"' do
- expect(InternalId::InternalIdGenerator.internal_id_transactions_total).to receive(:increment)
- .with(operation: :reset, usage: 'issues', in_transaction: 'true').and_call_original
+ it 'increments counter with in_transaction: "true"' do
+ expect(InternalId.internal_id_transactions_total).to receive(:increment)
+ .with(operation: :reset, usage: 'issues', in_transaction: 'true').and_call_original
- InternalId.transaction { subject }
+ InternalId.transaction { subject }
+ end
end
end
- end
- describe '.track_greatest' do
- let(:value) { 9001 }
+ describe '.track_greatest' do
+ let(:value) { 9001 }
- subject { described_class.track_greatest(id_subject, scope, usage, value, init) }
+ subject { described_class.track_greatest(id_subject, scope, usage, value, init) }
- context 'in the absence of a record' do
- it 'creates a record if not yet present' do
- expect { subject }.to change { described_class.count }.from(0).to(1)
+ context 'in the absence of a record' do
+ it 'creates a record if not yet present' do
+ expect { subject }.to change { described_class.count }.from(0).to(1)
+ end
end
- end
- it 'stores record attributes' do
- subject
+ it 'stores record attributes' do
+ subject
- described_class.first.tap do |record|
- expect(record.project).to eq(project)
- expect(record.usage).to eq(usage.to_s)
- expect(record.last_value).to eq(value)
+ described_class.first.tap do |record|
+ expect(record.project).to eq(project)
+ expect(record.usage).to eq(usage.to_s)
+ expect(record.last_value).to eq(value)
+ end
end
- end
- context 'with existing issues' do
- before do
- create(:issue, project: project)
- described_class.delete_all
- end
+ context 'with existing issues' do
+ before do
+ create(:issue, project: project)
+ described_class.delete_all
+ end
- it 'still returns the last value to that of the given value' do
- expect(subject).to eq(value)
+ it 'still returns the last value to that of the given value' do
+ expect(subject).to eq(value)
+ end
end
- end
- context 'when value is less than the current last_value' do
- it 'returns the current last_value' do
- described_class.create!(**scope, usage: usage, last_value: 10_001)
+ context 'when value is less than the current last_value' do
+ it 'returns the current last_value' do
+ described_class.create!(**scope, usage: usage, last_value: 10_001)
- expect(subject).to eq 10_001
+ expect(subject).to eq 10_001
+ end
end
- end
- context 'there are no instances to pass in' do
- let(:id_subject) { Issue }
+ context 'there are no instances to pass in' do
+ let(:id_subject) { Issue }
- it 'accepts classes instead' do
- expect(subject).to eq(value)
+ it 'accepts classes instead' do
+ expect(subject).to eq(value)
+ end
end
- end
- context 'when executed outside of transaction' do
- it 'increments counter with in_transaction: "false"' do
- allow(ActiveRecord::Base.connection).to receive(:transaction_open?) { false }
+ context 'when executed outside of transaction' do
+ it 'increments counter with in_transaction: "false"' do
+ allow(ActiveRecord::Base.connection).to receive(:transaction_open?) { false }
- expect(InternalId::InternalIdGenerator.internal_id_transactions_total).to receive(:increment)
- .with(operation: :track_greatest, usage: 'issues', in_transaction: 'false').and_call_original
+ expect(InternalId.internal_id_transactions_total).to receive(:increment)
+ .with(operation: :track_greatest, usage: 'issues', in_transaction: 'false').and_call_original
- subject
+ subject
+ end
end
- end
- context 'when executed within transaction' do
- it 'increments counter with in_transaction: "true"' do
- expect(InternalId::InternalIdGenerator.internal_id_transactions_total).to receive(:increment)
- .with(operation: :track_greatest, usage: 'issues', in_transaction: 'true').and_call_original
+ context 'when executed within transaction' do
+ it 'increments counter with in_transaction: "true"' do
+ expect(InternalId.internal_id_transactions_total).to receive(:increment)
+ .with(operation: :track_greatest, usage: 'issues', in_transaction: 'true').and_call_original
- InternalId.transaction { subject }
+ InternalId.transaction { subject }
+ end
end
end
end
+ context 'when the feature flag is disabled' do
+ stub_feature_flags(generate_iids_without_explicit_locking: false)
+
+ it_behaves_like 'a monotonically increasing id generator'
+ end
+
+ context 'when the feature flag is enabled' do
+ stub_feature_flags(generate_iids_without_explicit_locking: true)
+
+ it_behaves_like 'a monotonically increasing id generator'
+ end
+
describe '#increment_and_save!' do
let(:id) { create(:internal_id) }
diff --git a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
index 42f82987989..03f565e0aac 100644
--- a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
+++ b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
@@ -165,9 +165,9 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
3.times { supply.next_value }
end
- current_value = described_class.public_send(method_name, scope_value, &:current_value)
-
- expect(current_value).to eq(iid + 3)
+ described_class.public_send(method_name, scope_value) do |supply|
+ expect(supply.next_value).to eq(iid + 4)
+ end
end
end