diff options
Diffstat (limited to 'spec/models/design_management')
-rw-r--r-- | spec/models/design_management/design_at_version_spec.rb | 9 | ||||
-rw-r--r-- | spec/models/design_management/design_collection_spec.rb | 9 | ||||
-rw-r--r-- | spec/models/design_management/design_spec.rb | 134 |
3 files changed, 106 insertions, 46 deletions
diff --git a/spec/models/design_management/design_at_version_spec.rb b/spec/models/design_management/design_at_version_spec.rb index 2c640ee5c2c..3c1ff45c53f 100644 --- a/spec/models/design_management/design_at_version_spec.rb +++ b/spec/models/design_management/design_at_version_spec.rb @@ -78,18 +78,23 @@ RSpec.describe DesignManagement::DesignAtVersion do let!(:version_a) do create(:design_version, designs: [design_a]) end + let!(:version_b) do create(:design_version, designs: [design_b]) end + let!(:version_mod) do create(:design_version, modified_designs: [design_a, design_b]) end + let!(:version_c) do create(:design_version, deleted_designs: [design_a]) end + let!(:version_d) do create(:design_version, deleted_designs: [design_b]) end + let!(:version_e) do create(:design_version, designs: [design_a]) end @@ -296,9 +301,11 @@ RSpec.describe DesignManagement::DesignAtVersion do let!(:version_a) do create(:design_version, designs: create_list(:design, 3, issue: issue)) end + let!(:version_b) do create(:design_version, designs: create_list(:design, 1, issue: issue)) end + let!(:version_c) do create(:design_version, designs: create_list(:design, 1, issue: issue_b)) end @@ -346,10 +353,12 @@ RSpec.describe DesignManagement::DesignAtVersion do let!(:version_a) do create(:design_version, designs: create_list(:design, 3, issue: issue)) end + let!(:version_b) do create(:design_version, designs: create_list(:design, 2, issue: issue)) end # 1 version, with 3 designs on issue B, so 1*3 = 3 + let!(:version_c) do create(:design_version, designs: create_list(:design, 3, issue: issue_b)) end diff --git a/spec/models/design_management/design_collection_spec.rb b/spec/models/design_management/design_collection_spec.rb index c5e290da759..de766d5ce09 100644 --- a/spec/models/design_management/design_collection_spec.rb +++ b/spec/models/design_management/design_collection_spec.rb @@ -34,6 +34,15 @@ RSpec.describe DesignManagement::DesignCollection do collection.find_or_create_design!(filename: 'world.jpg') end.not_to exceed_query_limit(1) end + + it 'inserts the design after any existing designs' do + design1 = collection.find_or_create_design!(filename: 'design1.jpg') + design1.update!(relative_position: 100) + + design2 = collection.find_or_create_design!(filename: 'design2.jpg') + + expect(collection.designs.ordered(issue.project)).to eq([design1, design2]) + end end describe "#versions" do diff --git a/spec/models/design_management/design_spec.rb b/spec/models/design_management/design_spec.rb index 345147390c0..2c129f883b9 100644 --- a/spec/models/design_management/design_spec.rb +++ b/spec/models/design_management/design_spec.rb @@ -11,6 +11,11 @@ RSpec.describe DesignManagement::Design do let_it_be(:design3) { create(:design, :with_versions, issue: issue, versions_count: 1) } let_it_be(:deleted_design) { create(:design, :with_versions, deleted: true) } + it_behaves_like 'a class that supports relative positioning' do + let(:factory) { :design } + let(:default_params) { { issue: issue } } + end + describe 'relations' do it { is_expected.to belong_to(:project) } it { is_expected.to belong_to(:issue) } @@ -21,7 +26,7 @@ RSpec.describe DesignManagement::Design do end describe 'validations' do - subject(:design) { build(:design) } + subject(:design) { build(:design, issue: issue) } it { is_expected.to be_valid } it { is_expected.to validate_presence_of(:project) } @@ -147,6 +152,45 @@ RSpec.describe DesignManagement::Design do end end + describe '.ordered' do + before_all do + design1.update!(relative_position: 2) + design2.update!(relative_position: 1) + design3.update!(relative_position: nil) + deleted_design.update!(relative_position: nil) + end + + it 'sorts by relative position and ID in ascending order' do + expect(described_class.ordered(issue.project)).to eq([design2, design1, design3, deleted_design]) + end + + context 'when the :reorder_designs feature is enabled for the project' do + before do + stub_feature_flags(reorder_designs: issue.project) + end + + it 'sorts by relative position and ID in ascending order' do + expect(described_class.ordered(issue.project)).to eq([design2, design1, design3, deleted_design]) + end + end + + context 'when the :reorder_designs feature is disabled' do + before do + stub_feature_flags(reorder_designs: false) + end + + it 'sorts by ID in ascending order' do + expect(described_class.ordered(issue.project)).to eq([design1, design2, design3, deleted_design]) + end + end + end + + describe '.in_creation_order' do + it 'sorts by ID in ascending order' do + expect(described_class.in_creation_order).to eq([design1, design2, design3, deleted_design]) + end + end + describe '.with_filename' do it 'returns correct design when passed a single filename' do expect(described_class.with_filename(design1.filename)).to eq([design1]) @@ -181,7 +225,7 @@ RSpec.describe DesignManagement::Design do end describe '#visible_in?' do - let_it_be(:issue) { create(:issue) } + let_it_be(:issue) { create(:issue, project: issue.project) } # It is expensive to re-create complex histories, so we do it once, and then # assert that we can establish visibility at any given version. @@ -237,7 +281,7 @@ RSpec.describe DesignManagement::Design do describe '#status' do context 'the design is new' do - subject { build(:design) } + subject { build(:design, issue: issue) } it { is_expected.to have_attributes(status: :new) } end @@ -257,7 +301,7 @@ RSpec.describe DesignManagement::Design do describe '#deleted?' do context 'the design is new' do - let(:design) { build(:design) } + let(:design) { build(:design, issue: issue) } it 'is falsy' do expect(design).not_to be_deleted @@ -281,7 +325,7 @@ RSpec.describe DesignManagement::Design do end context 'the design has been deleted, but was then re-created' do - let(:design) { create(:design, :with_versions, versions_count: 1, deleted: true) } + let(:design) { create(:design, :with_versions, issue: issue, versions_count: 1, deleted: true) } it 'is falsy' do restore_designs(design) @@ -299,7 +343,7 @@ RSpec.describe DesignManagement::Design do end it "is true when there are no versions" do - expect(build(:design)).to be_new_design + expect(build(:design, issue: issue)).to be_new_design end it 'is false for deleted designs' do @@ -336,7 +380,7 @@ RSpec.describe DesignManagement::Design do describe "#full_path" do it "builds the full path for a design" do - design = build(:design, filename: "hello.jpg") + design = build(:design, issue: issue, filename: "hello.jpg") expected_path = "#{DesignManagement.designs_directory}/issue-#{design.issue.iid}/hello.jpg" expect(design.full_path).to eq(expected_path) @@ -359,15 +403,13 @@ RSpec.describe DesignManagement::Design do let(:versions_count) { 1 } it 'builds diff refs based on the empty tree if there was only one version' do - design = create(:design, :with_file, versions_count: 1) - expect(design.diff_refs.base_sha).to eq(Gitlab::Git::BLANK_SHA) expect(design.diff_refs.head_sha).to eq(design.diff_refs.head_sha) end end it 'has no diff ref if new' do - design = build(:design) + design = build(:design, issue: issue) expect(design.diff_refs).to be_nil end @@ -375,7 +417,7 @@ RSpec.describe DesignManagement::Design do describe '#repository' do it 'is a design repository' do - design = build(:design) + design = build(:design, issue: issue) expect(design.repository).to be_a(DesignManagement::Repository) end @@ -383,7 +425,7 @@ RSpec.describe DesignManagement::Design do describe '#note_etag_key' do it 'returns a correct etag key' do - design = create(:design) + design = design1 expect(design.note_etag_key).to eq( ::Gitlab::Routing.url_helpers.designs_project_issue_path(design.project, design.issue, { vueroute: design.filename }) @@ -392,47 +434,26 @@ RSpec.describe DesignManagement::Design do end describe '#user_notes_count', :use_clean_rails_memory_store_caching do - let_it_be(:design) { create(:design, :with_file) } - - subject { design.user_notes_count } - # Note: Cache invalidation tests are in `design_user_notes_count_service_spec.rb` - it 'returns a count of user-generated notes' do - create(:diff_note_on_design, noteable: design) - - is_expected.to eq(1) - end - - it 'does not count notes on other designs' do - second_design = create(:design, :with_file) - create(:diff_note_on_design, noteable: second_design) + common_attrs = { issue: issue, project: issue.project, author: issue.project.creator } + design, second_design = create_list(:design, 2, :with_file, issue: issue) + create(:diff_note_on_design, **common_attrs, noteable: design) + create(:diff_note_on_design, **common_attrs, system: true, noteable: design) + create(:diff_note_on_design, **common_attrs, noteable: second_design) - is_expected.to eq(0) - end - - it 'does not count system notes' do - create(:diff_note_on_design, system: true, noteable: design) - - is_expected.to eq(0) + expect(design.user_notes_count).to eq(1) end end describe '#after_note_changed' do - subject { build(:design) } + it 'calls #delete_cache on DesignUserNotesCountService for non-system notes' do + design = design1 - it 'calls #delete_cache on DesignUserNotesCountService' do - expect_next_instance_of(DesignManagement::DesignUserNotesCountService) do |service| - expect(service).to receive(:delete_cache) - end + expect(design.send(:user_notes_count_service)).to receive(:delete_cache).once - subject.after_note_changed(build(:note)) - end - - it 'does not call #delete_cache on DesignUserNotesCountService when passed a system note' do - expect(DesignManagement::DesignUserNotesCountService).not_to receive(:new) - - subject.after_note_changed(build(:note, :system)) + design.after_note_changed(build(:note, project: issue.project)) + design.after_note_changed(build(:note, :system, project: issue.project)) end end @@ -516,14 +537,14 @@ RSpec.describe DesignManagement::Design do with_them do let(:filename) { "my-file.#{ext}" } - let(:design) { build(:design, filename: filename) } + let(:design) { build(:design, issue: issue, filename: filename) } let(:url) { url_for_design(design) } let(:captures) { described_class.link_reference_pattern.match(url)&.named_captures } it 'matches the URL' do expect(captures).to include( 'url_filename' => filename, - 'issue' => design.issue.iid.to_s, + 'issue' => issue.iid.to_s, 'namespace' => design.project.namespace.to_param, 'project' => design.project.name ) @@ -565,4 +586,25 @@ RSpec.describe DesignManagement::Design do end end end + + describe '#immediately_before' do + let_it_be(:design) { create(:design, issue: issue, relative_position: 100) } + let_it_be(:next_design) { create(:design, issue: issue, relative_position: 200) } + + it 'is true when there is no element positioned between this item and the next' do + expect(design.immediately_before?(next_design)).to be true + end + + it 'is false when there is an element positioned between this item and the next' do + create(:design, issue: issue, relative_position: 150) + + expect(design.immediately_before?(next_design)).to be false + end + + it 'is false when the next design is to the left of this design' do + further_left = create(:design, issue: issue, relative_position: 50) + + expect(design.immediately_before?(further_left)).to be false + end + end end |