diff options
Diffstat (limited to 'spec/lib/api/helpers/caching_spec.rb')
-rw-r--r-- | spec/lib/api/helpers/caching_spec.rb | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/spec/lib/api/helpers/caching_spec.rb b/spec/lib/api/helpers/caching_spec.rb new file mode 100644 index 00000000000..a8cd061e123 --- /dev/null +++ b/spec/lib/api/helpers/caching_spec.rb @@ -0,0 +1,139 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe API::Helpers::Caching do + subject(:instance) { Class.new.include(described_class).new } + + describe "#present_cached" do + let_it_be(:project) { create(:project) } + let_it_be(:user) { create(:user) } + + let(:presenter) { API::Entities::Todo } + + let(:kwargs) do + { + with: presenter, + project: project + } + end + + subject do + instance.present_cached(presentable, **kwargs) + end + + before do + # We have to stub #body as it's a Grape method + # unavailable in the module by itself + expect(instance).to receive(:body) do |data| + data + end + + allow(instance).to receive(:current_user) { user } + end + + context "single object" do + let_it_be(:presentable) { create(:todo, project: project) } + + it { is_expected.to be_a(Gitlab::Json::PrecompiledJson) } + + it "uses the presenter" do + expect(presenter).to receive(:represent).with(presentable, project: project) + + subject + end + + it "is valid JSON" do + parsed = Gitlab::Json.parse(subject.to_s) + + expect(parsed).to be_a(Hash) + expect(parsed["id"]).to eq(presentable.id) + end + + it "fetches from the cache" do + expect(instance.cache).to receive(:fetch).with("#{presentable.cache_key}:#{user.cache_key}", expires_in: described_class::DEFAULT_EXPIRY).once + + subject + end + + context "when a cache context is supplied" do + before do + kwargs[:cache_context] = -> (todo) { todo.project.cache_key } + end + + it "uses the context to augment the cache key" do + expect(instance.cache).to receive(:fetch).with("#{presentable.cache_key}:#{project.cache_key}", expires_in: described_class::DEFAULT_EXPIRY).once + + subject + end + end + + context "when expires_in is supplied" do + it "sets the expiry when accessing the cache" do + kwargs[:expires_in] = 7.days + + expect(instance.cache).to receive(:fetch).with("#{presentable.cache_key}:#{user.cache_key}", expires_in: 7.days).once + + subject + end + end + end + + context "for a collection of objects" do + let_it_be(:presentable) { Array.new(5).map { create(:todo, project: project) } } + + it { is_expected.to be_an(Gitlab::Json::PrecompiledJson) } + + it "uses the presenter" do + presentable.each do |todo| + expect(presenter).to receive(:represent).with(todo, project: project) + end + + subject + end + + it "is valid JSON" do + parsed = Gitlab::Json.parse(subject.to_s) + + expect(parsed).to be_an(Array) + + presentable.each_with_index do |todo, i| + expect(parsed[i]["id"]).to eq(todo.id) + end + end + + it "fetches from the cache" do + keys = presentable.map { |todo| "#{todo.cache_key}:#{user.cache_key}" } + + expect(instance.cache).to receive(:fetch_multi).with(*keys, expires_in: described_class::DEFAULT_EXPIRY).once.and_call_original + + subject + end + + context "when a cache context is supplied" do + before do + kwargs[:cache_context] = -> (todo) { todo.project.cache_key } + end + + it "uses the context to augment the cache key" do + keys = presentable.map { |todo| "#{todo.cache_key}:#{project.cache_key}" } + + expect(instance.cache).to receive(:fetch_multi).with(*keys, expires_in: described_class::DEFAULT_EXPIRY).once.and_call_original + + subject + end + end + + context "expires_in is supplied" do + it "sets the expiry when accessing the cache" do + keys = presentable.map { |todo| "#{todo.cache_key}:#{user.cache_key}" } + kwargs[:expires_in] = 7.days + + expect(instance.cache).to receive(:fetch_multi).with(*keys, expires_in: 7.days).once.and_call_original + + subject + end + end + end + end +end |