diff --git a/Rakefile b/Rakefile index 56237d2..57c50c3 100644 --- a/Rakefile +++ b/Rakefile @@ -5,7 +5,7 @@ require "rake/testtask" Rake::TestTask.new(:test) do |t| t.libs << "test" - t.test_files = FileList["test/test_*.rb"] + t.test_files = FileList["test/spec_*.rb"] end task default: :test diff --git a/lib/nack.rb b/lib/nack.rb index 598cf7b..ecb346f 100644 --- a/lib/nack.rb +++ b/lib/nack.rb @@ -1,3 +1,4 @@ # frozen_string_literal: true require_relative "nack/version" +require_relative "nack/utils" diff --git a/lib/nack/utils.rb b/lib/nack/utils.rb new file mode 100644 index 0000000..695ba3f --- /dev/null +++ b/lib/nack/utils.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Nack + module Utils + module_function + + def no_entity_body?(status) + (100..199).cover?(status) || status == 204 || status == 304 + end + + def get_header(pairs, name) + pairs.assoc(name)&.last + end + + def set_header(pairs, name, value) + pairs.reject! { |key, _| key == name } + pairs << [name, value] + pairs + end + + def delete_header(pairs, name) + pairs.reject! { |key, _| key == name } + pairs + end + + def body_size(body) + case body + when nil then 0 + when IO::Buffer then body.size + else body.to_s.bytesize + end + end + end +end diff --git a/nack.gemspec b/nack.gemspec index 3bd56d3..64e6b4a 100644 --- a/nack.gemspec +++ b/nack.gemspec @@ -28,4 +28,5 @@ Gem::Specification.new do |spec| spec.add_development_dependency "bundler" spec.add_development_dependency "rake" spec.add_development_dependency "minitest" + spec.add_development_dependency "minitest-global_expectations" end diff --git a/test/helper.rb b/test/helper.rb index 2e49dfb..ae7390c 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -3,4 +3,4 @@ $LOAD_PATH.unshift(File.expand_path("../lib", __dir__)) require "nack" -require "minitest/autorun" +require "minitest/global_expectations/autorun" diff --git a/test/spec_utils.rb b/test/spec_utils.rb new file mode 100644 index 0000000..1e6a4b9 --- /dev/null +++ b/test/spec_utils.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require_relative "helper" + +describe Nack::Utils do + it "knows which statuses forbid an entity body" do + Nack::Utils.no_entity_body?(100).must_equal true + Nack::Utils.no_entity_body?(199).must_equal true + Nack::Utils.no_entity_body?(204).must_equal true + Nack::Utils.no_entity_body?(304).must_equal true + Nack::Utils.no_entity_body?(200).must_equal false + Nack::Utils.no_entity_body?(404).must_equal false + end + + it "returns the first value for a header name" do + pairs = [["content-type", "text/html"], ["x-a", "1"], ["x-a", "2"]] + Nack::Utils.get_header(pairs, "content-type").must_equal "text/html" + Nack::Utils.get_header(pairs, "x-a").must_equal "1" + Nack::Utils.get_header(pairs, "missing").must_be_nil + end + + it "replaces all occurrences when setting a header" do + pairs = [["b", "2"], ["a", "1"], ["b", "3"]] + Nack::Utils.set_header(pairs, "b", "9") + pairs.must_equal [["a", "1"], ["b", "9"]] + end + + it "appends when setting a header not yet present" do + pairs = [["a", "1"]] + Nack::Utils.set_header(pairs, "b", "2") + pairs.must_equal [["a", "1"], ["b", "2"]] + end + + it "removes all occurrences when deleting a header" do + pairs = [["a", "1"], ["a", "2"], ["b", "3"]] + Nack::Utils.delete_header(pairs, "a") + pairs.must_equal [["b", "3"]] + end + + it "measures body size in bytes" do + Nack::Utils.body_size(nil).must_equal 0 + Nack::Utils.body_size("hello").must_equal 5 + Nack::Utils.body_size("héllo").must_equal 6 + Nack::Utils.body_size(IO::Buffer.for("abc")).must_equal 3 + end +end