2019-10-12 21:52:04 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
require 'spec_helper'
|
|
|
|
|
2020-07-28 23:09:34 +05:30
|
|
|
RSpec.describe Gitlab::Ci::Variables::Collection::Item do
|
2018-11-08 19:23:39 +05:30
|
|
|
let(:variable_key) { 'VAR' }
|
|
|
|
let(:variable_value) { 'something' }
|
|
|
|
let(:expected_value) { variable_value }
|
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
let(:variable) do
|
2019-07-07 11:18:12 +05:30
|
|
|
{ key: variable_key, value: variable_value, public: true, masked: false }
|
2018-05-09 12:01:36 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
describe '.new' do
|
2018-11-08 19:23:39 +05:30
|
|
|
context 'when unknown keyword is specified' do
|
|
|
|
it 'raises error' do
|
|
|
|
expect { described_class.new(key: variable_key, value: 'abc', files: true) }
|
2021-01-29 00:20:46 +05:30
|
|
|
.to raise_error ArgumentError, 'unknown keyword: :files'
|
2018-11-08 19:23:39 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when required keywords are not specified' do
|
|
|
|
it 'raises error' do
|
|
|
|
expect { described_class.new(key: variable_key) }
|
2021-01-29 00:20:46 +05:30
|
|
|
.to raise_error ArgumentError, 'missing keyword: :value'
|
2018-11-08 19:23:39 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
shared_examples 'creates variable' do
|
|
|
|
subject { described_class.new(key: variable_key, value: variable_value) }
|
|
|
|
|
|
|
|
it 'saves given value' do
|
|
|
|
expect(subject[:key]).to eq variable_key
|
|
|
|
expect(subject[:value]).to eq expected_value
|
2021-04-17 20:07:23 +05:30
|
|
|
expect(subject.value).to eq expected_value
|
2018-11-08 19:23:39 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
shared_examples 'raises error for invalid type' do
|
|
|
|
it do
|
|
|
|
expect { described_class.new(key: variable_key, value: variable_value) }
|
2019-02-15 15:39:39 +05:30
|
|
|
.to raise_error ArgumentError, /`#{variable_key}` must be of type String or nil value, while it was:/
|
2018-11-08 19:23:39 +05:30
|
|
|
end
|
2018-05-09 12:01:36 +05:30
|
|
|
end
|
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
it_behaves_like 'creates variable'
|
|
|
|
|
|
|
|
context "when it's nil" do
|
|
|
|
let(:variable_value) { nil }
|
|
|
|
let(:expected_value) { nil }
|
|
|
|
|
|
|
|
it_behaves_like 'creates variable'
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when it's an empty string" do
|
|
|
|
let(:variable_value) { '' }
|
|
|
|
let(:expected_value) { '' }
|
|
|
|
|
|
|
|
it_behaves_like 'creates variable'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when provided value is not a string' do
|
|
|
|
[1, false, [], {}, Object.new].each do |val|
|
|
|
|
context "when it's #{val}" do
|
|
|
|
let(:variable_value) { val }
|
|
|
|
|
|
|
|
it_behaves_like 'raises error for invalid type'
|
|
|
|
end
|
|
|
|
end
|
2018-05-09 12:01:36 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-04-17 20:07:23 +05:30
|
|
|
describe '#depends_on' do
|
|
|
|
let(:item) { Gitlab::Ci::Variables::Collection::Item.new(**variable) }
|
|
|
|
|
|
|
|
subject { item.depends_on }
|
|
|
|
|
|
|
|
context 'table tests' do
|
|
|
|
using RSpec::Parameterized::TableSyntax
|
|
|
|
|
|
|
|
where do
|
|
|
|
{
|
|
|
|
"no variable references": {
|
|
|
|
variable: { key: 'VAR', value: 'something' },
|
|
|
|
expected_depends_on: nil
|
|
|
|
},
|
|
|
|
"simple variable reference": {
|
|
|
|
variable: { key: 'VAR', value: 'something_$VAR2' },
|
|
|
|
expected_depends_on: %w(VAR2)
|
|
|
|
},
|
|
|
|
"complex expansion": {
|
|
|
|
variable: { key: 'VAR', value: 'something_${VAR2}_$VAR3' },
|
|
|
|
expected_depends_on: %w(VAR2 VAR3)
|
|
|
|
},
|
|
|
|
"complex expansion in raw variable": {
|
|
|
|
variable: { key: 'VAR', value: 'something_${VAR2}_$VAR3', raw: true },
|
|
|
|
expected_depends_on: nil
|
|
|
|
},
|
|
|
|
"complex expansions for Windows": {
|
|
|
|
variable: { key: 'variable3', value: 'key%variable%%variable2%' },
|
|
|
|
expected_depends_on: %w(variable variable2)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it 'contains referenced variable names' do
|
|
|
|
is_expected.to eq(expected_depends_on)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
describe '.fabricate' do
|
|
|
|
it 'supports using a hash' do
|
|
|
|
resource = described_class.fabricate(variable)
|
|
|
|
|
|
|
|
expect(resource).to be_a(described_class)
|
|
|
|
expect(resource).to eq variable
|
|
|
|
end
|
|
|
|
|
2018-11-18 11:00:15 +05:30
|
|
|
it 'supports using a hash with stringified values' do
|
|
|
|
variable = { 'key' => 'VARIABLE', 'value' => 'my value' }
|
|
|
|
|
|
|
|
resource = described_class.fabricate(variable)
|
|
|
|
|
|
|
|
expect(resource).to eq(key: 'VARIABLE', value: 'my value')
|
|
|
|
end
|
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
it 'supports using an active record resource' do
|
|
|
|
variable = create(:ci_variable, key: 'CI_VAR', value: '123')
|
|
|
|
resource = described_class.fabricate(variable)
|
|
|
|
|
|
|
|
expect(resource).to be_a(described_class)
|
2019-07-07 11:18:12 +05:30
|
|
|
expect(resource).to eq(key: 'CI_VAR', value: '123', public: false, masked: false)
|
2018-05-09 12:01:36 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'supports using another collection item' do
|
|
|
|
item = described_class.new(**variable)
|
|
|
|
|
|
|
|
resource = described_class.fabricate(item)
|
|
|
|
|
|
|
|
expect(resource).to be_a(described_class)
|
|
|
|
expect(resource).to eq variable
|
|
|
|
expect(resource.object_id).not_to eq item.object_id
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#==' do
|
|
|
|
it 'compares a hash representation of a variable' do
|
|
|
|
expect(described_class.new(**variable) == variable).to be true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#[]' do
|
|
|
|
it 'behaves like a hash accessor' do
|
|
|
|
item = described_class.new(**variable)
|
|
|
|
|
|
|
|
expect(item[:key]).to eq 'VAR'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-04-17 20:07:23 +05:30
|
|
|
describe '#raw' do
|
|
|
|
it 'returns false when :raw is not specified' do
|
|
|
|
item = described_class.new(**variable)
|
|
|
|
|
|
|
|
expect(item.raw).to eq false
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when :raw is specified as true' do
|
|
|
|
let(:variable) do
|
|
|
|
{ key: variable_key, value: variable_value, public: true, masked: false, raw: true }
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns true' do
|
|
|
|
item = described_class.new(**variable)
|
|
|
|
|
|
|
|
expect(item.raw).to eq true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
describe '#to_runner_variable' do
|
|
|
|
context 'when variable is not a file-related' do
|
|
|
|
it 'returns a runner-compatible hash representation' do
|
|
|
|
runner_variable = described_class
|
|
|
|
.new(**variable)
|
|
|
|
.to_runner_variable
|
|
|
|
|
|
|
|
expect(runner_variable).to eq variable
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when variable is file-related' do
|
|
|
|
it 'appends file description component' do
|
|
|
|
runner_variable = described_class
|
|
|
|
.new(key: 'VAR', value: 'value', file: true)
|
|
|
|
.to_runner_variable
|
|
|
|
|
|
|
|
expect(runner_variable)
|
2019-07-07 11:18:12 +05:30
|
|
|
.to eq(key: 'VAR', value: 'value', public: true, file: true, masked: false)
|
2018-05-09 12:01:36 +05:30
|
|
|
end
|
|
|
|
end
|
2021-04-17 20:07:23 +05:30
|
|
|
|
|
|
|
context 'when variable is raw' do
|
|
|
|
it 'does not export raw value when it is false' do
|
|
|
|
runner_variable = described_class
|
|
|
|
.new(key: 'VAR', value: 'value', raw: false)
|
|
|
|
.to_runner_variable
|
|
|
|
|
|
|
|
expect(runner_variable)
|
|
|
|
.to eq(key: 'VAR', value: 'value', public: true, masked: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'exports raw value when it is true' do
|
|
|
|
runner_variable = described_class
|
|
|
|
.new(key: 'VAR', value: 'value', raw: true)
|
|
|
|
.to_runner_variable
|
|
|
|
|
|
|
|
expect(runner_variable)
|
|
|
|
.to eq(key: 'VAR', value: 'value', public: true, raw: true, masked: false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when referencing a variable' do
|
|
|
|
it '#depends_on contains names of dependencies' do
|
|
|
|
runner_variable = described_class.new(key: 'CI_VAR', value: '${CI_VAR_2}-123-$CI_VAR_3')
|
|
|
|
|
|
|
|
expect(runner_variable.depends_on).to eq(%w(CI_VAR_2 CI_VAR_3))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when assigned the raw attribute' do
|
|
|
|
it 'retains a true raw attribute' do
|
|
|
|
runner_variable = described_class.new(key: 'CI_VAR', value: '123', raw: true)
|
|
|
|
|
|
|
|
expect(runner_variable).to eq(key: 'CI_VAR', value: '123', public: true, masked: false, raw: true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not retain a false raw attribute' do
|
|
|
|
runner_variable = described_class.new(key: 'CI_VAR', value: '123', raw: false)
|
|
|
|
|
|
|
|
expect(runner_variable).to eq(key: 'CI_VAR', value: '123', public: true, masked: false)
|
|
|
|
end
|
|
|
|
end
|
2018-05-09 12:01:36 +05:30
|
|
|
end
|
|
|
|
end
|