1
0
mirror of https://github.com/meineerde/rackstash.git synced 2025-10-17 14:01:01 +00:00
rackstash/spec/rackstash/fields/array_spec.rb

409 lines
11 KiB
Ruby

# frozen_string_literal: true
#
# Copyright 2017 Holger Just
#
# This software may be modified and distributed under the terms
# of the MIT license. See the LICENSE.txt file for details.
require 'spec_helper'
require 'rackstash/fields/array'
describe Rackstash::Fields::Array do
let(:array) { described_class.new }
describe '#+' do
it 'returns the addition of elements' do
array[0] = 'existing'
expect(array + ['existing', -> { 'new' }, [:nested]])
.to contain_exactly('existing', 'existing', 'new', ['nested'])
.and be_a(described_class)
end
it 'returns a new Array' do
expect(array + [:foo]).to be_a(described_class)
expect(array + [:foo]).not_to equal array
end
end
describe '#-' do
it 'returns the subtraction of elements' do
array[0] = 'foo'
array[1] = 'bar'
expect(array - [-> { :bar }, ['foo']]).to contain_exactly 'foo'
end
it 'returns a new Array' do
expect(array - [:foo]).to be_a(described_class).and be_empty
expect(array - [:foo]).not_to equal array
end
end
describe '#|' do
it 'returns the union of elements' do
array[0] = 'existing'
expect(array | ['new', :existing, -> { 123 }])
.to contain_exactly 'existing', 'new', 123
end
it 'returns a new Array' do
expect(array | [:foo]).to be_a(described_class)
expect(array | [:foo]).not_to equal array
end
end
describe '#&' do
it 'returns the intersection of elements' do
array[0] = 'existing'
expect(array & [:existing, 'new'])
.to contain_exactly 'existing'
end
it 'returns a new Array' do
expect(array & [:foo]).to be_a(described_class).and be_empty
expect(array & [:foo]).not_to equal array
end
end
describe '#[]' do
before do
array[0] = 'value'
array[1] = 'foo'
array[2] = 'bar'
array[3] = 'baz'
end
it 'returns a set value' do
expect(array[0]).to eql 'value'
end
it 'returns an array from start, end' do
expect(array[1, 3]).to be_a described_class
expect(array[1, 3].to_ary).to eql %w[foo bar baz]
expect(array[2, 0].to_ary).to eql []
expect(array[2, 1].to_ary).to eql %w[bar]
expect(array[2, 5].to_ary).to eql %w[bar baz]
end
it 'returns an array from a range' do
expect(array[1..3]).to be_a described_class
expect(array[1..3].to_ary).to eql %w[foo bar baz]
expect(array[2..4].to_ary).to eql %w[bar baz]
expect(array[2..-1].to_ary).to eql %w[bar baz]
end
it 'returns nil if a value was not set' do
expect(array[5]).to be_nil
expect(array[5, 2]).to be_nil
expect(array[2, -1]).to be_nil
expect(array[5..9]).to be_nil
end
end
describe '#[]=' do
it 'normalizes values' do
expect(array).to receive(:normalize).with('value').and_return('normalized')
array[0] = 'value'
expect(array[0]).to eql 'normalized'
end
it 'can set values on a range' do
array.concat(%w[hello world with flowers and unicorns])
array[1..4] = %w[super duper]
expect(array.as_json).to eql %w[hello super duper unicorns]
end
it 'can set values from start, length' do
array.concat(%w[hello world with flowers and unicorns])
array[1, 4] = %w[shiny and sparkling]
expect(array.as_json).to eql %w[hello shiny and sparkling unicorns]
end
end
describe '#<<' do
it 'normalized the value' do
expect(array).to receive(:normalize).with('value').twice.and_return('normalized')
array << 'value'
expect(array[0]).to eql 'normalized'
expect(array[1]).to be nil
array << 'value'
expect(array[0]).to eql 'normalized'
expect(array[1]).to eql 'normalized'
end
it 'can append only one value' do
expect { array.<< 'foo', 'bar' }.to raise_error ArgumentError
end
it 'returns the array' do
expect(array << 'value').to equal array
end
end
describe '#as_json' do
before do
array[0] = 'value'
array[1] = { 'key' => 'nested value', number: 42 }
array[2] = ['v1', :v2]
end
it 'returns a simple array' do
expect(array.as_json).to be_instance_of ::Array
expect(array.as_json.length).to eql 3
end
it 'returns a nested hash' do
expect(array[1]).to be_a Rackstash::Fields::Hash
expect(array.as_json[1]).to be_a Hash
expect(array.as_json[1]).to eql 'key' => 'nested value', 'number' => 42
end
it 'returns a nested array' do
expect(array[2]).to be_a described_class
expect(array.as_json[2]).to be_instance_of ::Array
expect(array.as_json[2]).to eql %w[v1 v2]
end
it 'returns a new copy each time' do
expect(array.as_json).to eql array.as_json
expect(array.as_json).not_to equal array.as_json
expect(array.as_json[1]).to eql array.as_json[1]
expect(array.as_json[1]).not_to equal array.as_json[1]
expect(array.as_json[2]).to eql array.as_json[2]
expect(array.as_json[2]).not_to equal array.as_json[2]
end
it 'can not change the raw value' do
as_json = array.as_json
as_json[3] = 'foo'
expect(array[3]).to be_nil
end
it 'can use to_ary as an alias' do
expect(array.to_ary).to eql array.as_json
end
it 'can use to_a as an alias' do
expect(array.to_a).to eql array.as_json
end
end
describe '#clear' do
it 'clears the array' do
array[0] = 'beep'
array.clear
expect(array[0]).to be_nil
end
it 'returns the array' do
array[0] = 'bar'
expect(array.clear).to equal array
end
end
describe '#concat' do
it 'contacts an array' do
array[0] = 'first'
ary = ['foo', 'bar']
expect(array).to receive(:normalize).with(ary, anything).ordered.and_call_original
expect(array).to receive(:normalize).with('foo', anything).ordered.and_call_original
expect(array).to receive(:normalize).with('bar', anything).ordered.and_call_original
expect(array.concat(ary)).to equal array
expect(array[0]).to eql 'first'
expect(array[1]).to eql 'foo'
expect(array[1]).to be_frozen
expect(array[2]).to eql 'bar'
expect(array[2]).to be_frozen
end
it 'refuses to concat an arbitrary value' do
expect { array.concat(:foo) }.to raise_error TypeError
expect { array.concat(42) }.to raise_error TypeError
expect { array.concat(false) }.to raise_error TypeError
expect { array.concat(nil) }.to raise_error TypeError
end
it 'resolves nested procs' do
expect(array.concat(-> { [-> { :foo }] })).to contain_exactly 'foo'
end
it 'resolves nested procs with a custom scope' do
expect(
array.concat(-> { [self, -> { self.to_s.upcase }] }, scope: :stuff)
).to contain_exactly 'stuff', 'STUFF'
end
end
describe '#empty?' do
it 'returns true of there are any tags' do
expect(array.empty?).to be true
array[0] = 'foo'
expect(array.empty?).to be false
array.clear
expect(array.empty?).to be true
end
end
describe '#length' do
it 'returns the length of the array' do
expect(array.length).to eql 0
array[0] = 'first'
expect(array.length).to eql 1
array.clear
expect(array.length).to eql 0
end
it 'can use size as an alias' do
expect(array.size).to eql 0
array[0] = 'first'
expect(array.size).to eql 1
end
end
describe '#merge' do
it 'returns the union of elements' do
array[0] = 'existing'
expect(array.merge(['new', :existing, -> { 123 }]))
.to contain_exactly('existing', 'new', 123)
.and be_a(described_class)
end
it 'returns a new Array' do
expect(array.merge([:foo])).to be_a(described_class)
expect(array.merge([:foo])).not_to equal array
end
it 'resolves nested procs with a custom scope' do
expect(
array.merge(-> { [self, -> { self.to_s.upcase }] }, scope: :stuff)
).to contain_exactly 'stuff', 'STUFF'
end
end
describe '#merge!' do
it 'sets the union of elements to self' do
array[0] = 'existing'
expect(array.merge!(['new', :existing, -> { 123 }]))
.to contain_exactly 'existing', 'new', 123
end
it 'returns self' do
expect(array.merge!([:foo])).to equal array
end
it 'resolves nested procs with a custom scope' do
expect(
array.merge!(-> { [self, -> { self.to_s.upcase }] }, scope: :stuff)
).to contain_exactly 'stuff', 'STUFF'
end
end
describe '#pop' do
it 'returns nothing from an empty array' do
expect(array.pop).to be_nil
expect(array.pop(42)).to be_instance_of(Array).and be_empty
end
it 'returns and removes the last element' do
array << 'foo' << 'bar'
expect(array.pop).to eql 'bar'
expect(array[0]).to eql 'foo'
end
it 'returns and removes at most n elements' do
array << 'foo' << 'bar' << 'baz'
expect(array.pop(2)).to eql ['bar', 'baz']
expect(array[0]).to eql 'foo'
end
end
describe '#push' do
it 'can append multiple values' do
expect(array.push('value', 'value2')).to equal array
expect(array[0]).to eql 'value'
expect(array[1]).to eql 'value2'
end
it 'appends arrays as is' do
value = ['hello']
array.push value
expect(array[0]).to be_a described_class
expect(array[0].to_a).to eql value
end
it 'can use append as an alias' do
expect(array.append('foo')).to equal array
expect(array[0]).to eql 'foo'
end
end
describe '#unshift' do
it 'prepends objects' do
array[0] = 'first'
array.unshift('foo', 'bar')
expect(array[0]).to eql 'foo'
expect(array[1]).to eql 'bar'
expect(array[2]).to eql 'first'
end
it 'normalizes values with the scope' do
array.unshift -> { self + 3 }, scope: 2
expect(array[0]).to eql 5
end
end
describe '#shift' do
before do
array[0] = 'value'
array[1] = 'foo'
array[2] = 'bar'
array[3] = 'baz'
end
it 'shift a single value' do
expect(array.shift).to eql 'value'
expect(array[0]).to eql 'foo'
end
it 'shift multiple values' do
expect(array.shift(3))
.to be_instance_of(described_class)
.and contain_exactly('value', 'foo', 'bar')
expect(array[0]).to eql 'baz'
end
end
describe 'Converter' do
it 'creates a new array' do
raw = [Time.now, 'foo']
array = Rackstash::Fields::Array(raw)
expect(array).to be_a described_class
expect(array[0]).to be_a String
expect(array[1]).to eql 'foo'
end
end
end