summaryrefslogtreecommitdiff
path: root/spec/support/shared_examples/models/concerns/integrations/reset_secret_fields_shared_examples.rb
blob: 873f858e4328cc230c413db40b671f1509cfb5dd (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
# frozen_string_literal: true

RSpec.shared_examples Integrations::ResetSecretFields do
  describe '#exposing_secrets_fields' do
    it 'returns an array of strings' do
      expect(integration.exposing_secrets_fields).to be_a(Array)
      expect(integration.exposing_secrets_fields).to all(be_a(String))
    end
  end

  describe '#reset_secret_fields?' do
    let(:exposing_fields) { integration.exposing_secrets_fields }

    it 'returns false if no exposing field has changed' do
      exposing_fields.each do |field|
        allow(integration).to receive("#{field}_changed?").and_return(false)
      end

      expect(integration.send(:reset_secret_fields?)).to be(false)
    end

    it 'returns true if any exposing field has changed' do
      exposing_fields.each do |field|
        allow(integration).to receive("#{field}_changed?").and_return(true)

        other_exposing_fields = exposing_fields.without(field)
        other_exposing_fields.each do |other_field|
          allow(integration).to receive("#{other_field}_changed?").and_return(false)
        end

        expect(integration.send(:reset_secret_fields?)).to be(true)
      end
    end
  end

  describe 'validation callback' do
    before do
      # Store a value in each password field
      integration.secret_fields.each do |field|
        integration.public_send("#{field}=", 'old value')
      end

      # Treat values as persisted
      integration.reset_updated_properties
      integration.instance_variable_set('@old_data_fields', nil) if integration.supports_data_fields?
    end

    context 'when an exposing field has changed' do
      let(:exposing_field) { integration.exposing_secrets_fields.first }

      before do
        integration.public_send("#{exposing_field}=", 'new value')
      end

      it 'clears all secret fields' do
        integration.valid?

        integration.secret_fields.each do |field|
          expect(integration.public_send(field)).to be_nil
          expect(integration.properties[field]).to be_nil if integration.properties.present?
          expect(integration.data_fields[field]).to be_nil if integration.supports_data_fields?
        end
      end

      context 'when a secret field has been updated' do
        let(:secret_field) { integration.secret_fields.first }
        let(:other_secret_fields) { integration.secret_fields.without(secret_field) }
        let(:new_value) { 'new value' }

        before do
          integration.public_send("#{secret_field}=", new_value)
        end

        it 'does not clear this secret field' do
          integration.valid?

          expect(integration.public_send(secret_field)).to eq('new value')

          other_secret_fields.each do |field|
            expect(integration.public_send(field)).to be_nil
          end
        end

        context 'when a secret field has been updated with the same value' do
          let(:new_value) { 'old value' }

          it 'does not clear this secret field' do
            integration.valid?

            expect(integration.public_send(secret_field)).to eq('old value')

            other_secret_fields.each do |field|
              expect(integration.public_send(field)).to be_nil
            end
          end
        end
      end
    end

    context 'when no exposing field has changed' do
      it 'does not clear any secret fields' do
        integration.valid?

        integration.secret_fields.each do |field|
          expect(integration.public_send(field)).to eq('old value')
        end
      end
    end
  end
end