summaryrefslogtreecommitdiff
path: root/spec/support/shared_examples/models/concerns/blob_replicator_strategy_shared_examples.rb
blob: 76339837351dc317d3d8f54cbc32d9c0ead99f52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# frozen_string_literal: true

# Include these shared examples in specs of Replicators that include
# BlobReplicatorStrategy.
#
# A let variable called model_record should be defined in the spec. It should be
# a valid, unpersisted instance of the model class.
#
RSpec.shared_examples 'a blob replicator' do
  include EE::GeoHelpers

  let_it_be(:primary) { create(:geo_node, :primary) }
  let_it_be(:secondary) { create(:geo_node) }

  subject(:replicator) { model_record.replicator }

  before do
    stub_current_geo_node(primary)
  end

  describe '#handle_after_create_commit' do
    it 'creates a Geo::Event' do
      expect do
        replicator.handle_after_create_commit
      end.to change { ::Geo::Event.count }.by(1)

      expect(::Geo::Event.last.attributes).to include(
        "replicable_name" => replicator.replicable_name, "event_name" => "created", "payload" => { "model_record_id" => replicator.model_record.id })
    end

    it 'schedules the checksum calculation if needed' do
      expect(Geo::BlobVerificationPrimaryWorker).to receive(:perform_async)
      expect(replicator).to receive(:needs_checksum?).and_return(true)

      replicator.handle_after_create_commit
    end

    it 'does not schedule the checksum calculation if feature flag is disabled' do
      stub_feature_flags(geo_self_service_framework: false)

      expect(Geo::BlobVerificationPrimaryWorker).not_to receive(:perform_async)
      allow(replicator).to receive(:needs_checksum?).and_return(true)

      replicator.handle_after_create_commit
    end
  end

  describe '#calculate_checksum!' do
    it 'calculates the checksum' do
      model_record.save!

      replicator.calculate_checksum!

      expect(model_record.reload.verification_checksum).not_to be_nil
      expect(model_record.reload.verified_at).not_to be_nil
    end

    it 'saves the error message and increments retry counter' do
      model_record.save!

      allow(model_record).to receive(:calculate_checksum!) do
        raise StandardError.new('Failure to calculate checksum')
      end

      replicator.calculate_checksum!

      expect(model_record.reload.verification_failure).to eq 'Failure to calculate checksum'
      expect(model_record.verification_retry_count).to be 1
    end
  end

  describe '#consume_created_event' do
    it 'invokes Geo::BlobDownloadService' do
      service = double(:service)

      expect(service).to receive(:execute)
      expect(::Geo::BlobDownloadService).to receive(:new).with(replicator: replicator).and_return(service)

      replicator.consume_event_created
    end
  end

  describe '#carrierwave_uploader' do
    it 'is implemented' do
      expect do
        replicator.carrierwave_uploader
      end.not_to raise_error
    end
  end

  describe '#model' do
    let(:invoke_model) { replicator.class.model }

    it 'is implemented' do
      expect do
        invoke_model
      end.not_to raise_error
    end

    it 'is a Class' do
      expect(invoke_model).to be_a(Class)
    end

    # For convenience (and reliability), instead of asking developers to include shared examples on each model spec as well
    context 'replicable model' do
      it 'defines #replicator' do
        expect(model_record).to respond_to(:replicator)
      end

      it 'invokes replicator.handle_after_create_commit on create' do
        expect(replicator).to receive(:handle_after_create_commit)

        model_record.save!
      end
    end
  end
end