module OpenUI::Rails::Testing::IdempotencyStoreContract
Reusable Minitest contract for idempotency adapters. Include this module in a test case that defines build_store and advance_store_clock(seconds). Each test needs an empty store and a controllable shared clock.
Public Instance Methods
test_claim_distinguishes_pending_from_completed()
click to toggle source
# File lib/openui/rails/testing/idempotency_store_contract.rb, line 10 def test_claim_distinguishes_pending_from_completed store = build_store status, value, digest, token = store.claim("key", ttl: 60, digest: "original") assert_equal :claimed, status assert_nil value assert_equal "original", digest refute_empty token assert_equal [ :pending, nil, "original", token ], store.claim("key", ttl: 60, digest: "changed") store.record("key", "saved", claim_token: token) assert_equal [ :replay, "saved", "original", token ], store.claim("key", ttl: 60, digest: "changed") end
test_completed_nil_and_false_replay()
click to toggle source
# File lib/openui/rails/testing/idempotency_store_contract.rb, line 22 def test_completed_nil_and_false_replay store = build_store [ nil, false ].each_with_index do |value, index| key = "nullable-#{index}" token = store.claim(key, ttl: 60, digest: "d").last store.record(key, value, claim_token: token) assert_equal [ :replay, value, "d", token ], store.claim(key, ttl: 60, digest: "d") end end
test_expired_owner_cannot_record()
click to toggle source
# File lib/openui/rails/testing/idempotency_store_contract.rb, line 40 def test_expired_owner_cannot_record store = build_store token = store.claim("key", ttl: 10, digest: "old").last advance_store_clock(10) store.record("key", "late", claim_token: token) status, value, _, replacement = store.claim("key", ttl: 60, digest: "new") assert_equal :claimed, status assert_nil value refute_equal token, replacement end
test_json_results_round_trip()
click to toggle source
# File lib/openui/rails/testing/idempotency_store_contract.rb, line 32 def test_json_results_round_trip store = build_store value = { "list" => [ 1, 2.5, true, false, nil, "你好" ], "nested" => { "ok" => true } } token = store.claim("key", ttl: 60, digest: "d").last store.record("key", value, claim_token: token) assert_equal value, store.claim("key", ttl: 60, digest: "d")[1] end
test_replaced_owner_cannot_overwrite()
click to toggle source
# File lib/openui/rails/testing/idempotency_store_contract.rb, line 51 def test_replaced_owner_cannot_overwrite store = build_store old = store.claim("key", ttl: 10, digest: "old").last advance_store_clock(11) token = store.claim("key", ttl: 60, digest: "new").last store.record("key", "new result", claim_token: token) store.record("key", "old result", claim_token: old) assert_equal [ :replay, "new result", "new", token ], store.claim("key", ttl: 60, digest: "new") end
test_ttl_must_be_positive_and_finite()
click to toggle source
# File lib/openui/rails/testing/idempotency_store_contract.rb, line 70 def test_ttl_must_be_positive_and_finite store = build_store [ 0, -1, Float::INFINITY, Float::NAN, "60", nil ].each do |ttl| assert_raises(OpenUI::Rails::ConfigurationError) { store.claim("key", ttl: ttl, digest: "d") } end end
test_wrong_token_and_unknown_key_do_not_complete_a_claim()
click to toggle source
# File lib/openui/rails/testing/idempotency_store_contract.rb, line 61 def test_wrong_token_and_unknown_key_do_not_complete_a_claim store = build_store token = store.claim("key", ttl: 60, digest: "d").last store.record("missing", "value", claim_token: token) store.record("key", "value", claim_token: "wrong") assert_equal :pending, store.claim("key", ttl: 60, digest: "d").first assert_equal :claimed, store.claim("missing", ttl: 60, digest: "d").first end