diff --git a/test/test_http_range.rb b/test/test_http_range.rb new file mode 100644 index 0000000..043a378 --- /dev/null +++ b/test/test_http_range.rb @@ -0,0 +1,82 @@ +require 'minitest/autorun' +require 'prism' +require 'tmpdir' + +class HttpRangeTest < Minitest::Test + def test_no_header_returns_nil + assert_nil Prism::HttpRange.parse(nil, 100) + end + + def test_non_bytes_unit_is_ignored + assert_nil Prism::HttpRange.parse('items=0-1', 100) + end + + def test_multi_range_is_ignored_not_unsatisfiable + assert_nil Prism::HttpRange.parse('bytes=0-10,20-30', 100) + end + + def test_simple_start_end + result = Prism::HttpRange.parse('bytes=0-9', 100) + assert_equal 0, result.start + assert_equal 9, result.finish + assert_equal 10, result.length + end + + def test_open_ended_range_clamps_to_file_size + result = Prism::HttpRange.parse('bytes=90-', 100) + assert_equal 90, result.start + assert_equal 99, result.finish + assert_equal 10, result.length + end + + def test_end_beyond_file_size_is_clamped_not_rejected + result = Prism::HttpRange.parse('bytes=0-999', 100) + assert_equal 99, result.finish + end + + def test_suffix_range_returns_last_n_bytes + result = Prism::HttpRange.parse('bytes=-10', 100) + assert_equal 90, result.start + assert_equal 99, result.finish + assert_equal 10, result.length + end + + def test_suffix_range_larger_than_file_clamps_to_whole_file + result = Prism::HttpRange.parse('bytes=-1000', 100) + assert_equal 0, result.start + assert_equal 99, result.finish + end + + def test_start_beyond_file_size_is_unsatisfiable + assert_equal :unsatisfiable, Prism::HttpRange.parse('bytes=100-200', 100) + end + + def test_start_after_end_is_unsatisfiable + assert_equal :unsatisfiable, Prism::HttpRange.parse('bytes=50-10', 100) + end + + def test_empty_start_and_end_is_unsatisfiable + assert_equal :unsatisfiable, Prism::HttpRange.parse('bytes=-', 100) + end + + def test_garbage_spec_is_unsatisfiable + assert_equal :unsatisfiable, Prism::HttpRange.parse('bytes=abc-def', 100) + end + + def test_zero_length_suffix_is_unsatisfiable + assert_equal :unsatisfiable, Prism::HttpRange.parse('bytes=-0', 100) + end + + def test_empty_file_is_always_unsatisfiable + assert_equal :unsatisfiable, Prism::HttpRange.parse('bytes=0-0', 0) + end + + def test_read_slice_returns_only_the_requested_bytes + Dir.mktmpdir do |dir| + path = File.join(dir, 'data.bin') + File.binwrite(path, '0123456789') + slice = Prism::HttpRange.parse('bytes=2-5', 10) + assert_equal '2345', Prism::HttpRange.read_slice(path, slice) + end + end +end diff --git a/test/test_i18n.rb b/test/test_i18n.rb new file mode 100644 index 0000000..cec3fa9 --- /dev/null +++ b/test/test_i18n.rb @@ -0,0 +1,90 @@ +require 'minitest/autorun' +require 'prism' +require 'tmpdir' + +class I18nModuleTest < Minitest::Test + def setup + Prism::I18n.reset! + Prism::I18n.store_translations(:en, 'hello' => 'Hello') + Prism::I18n.store_translations(:pl, 'hello' => 'Czesc') + end + + def teardown + Prism::I18n.reset! + end + + def test_default_locale_is_en_out_of_the_box + assert_equal :en, Prism::I18n.default_locale + end + + def test_locale_reads_and_writes_current_locale + assert_equal :en, Prism::I18n.locale + Prism::I18n.locale = :pl + assert_equal :pl, Prism::I18n.locale + end + + def test_t_and_l_are_aliases + assert_equal Prism::I18n.translate('hello', locale: :en), Prism::I18n.t('hello', locale: :en) + time = Time.utc(2026, 1, 1) + assert_equal Prism::I18n.localize(time, locale: :en), Prism::I18n.l(time, locale: :en) + end + + def test_translate_uses_current_locale_by_default + Prism::I18n.locale = :pl + assert_equal 'Czesc', Prism::I18n.t('hello') + end + + def test_with_locale_is_scoped_and_restores_previous_value + Prism::I18n.locale = :en + Prism::I18n.with_locale(:pl) do + assert_equal 'Czesc', Prism::I18n.t('hello') + end + assert_equal :en, Prism::I18n.locale + end + + def test_with_locale_nests_correctly + Prism::I18n.with_locale(:en) do + Prism::I18n.with_locale(:pl) do + assert_equal :pl, Prism::I18n.locale + end + assert_equal :en, Prism::I18n.locale + end + end + + def test_available_locales_reflects_stored_translations + assert_equal [:en, :pl], Prism::I18n.available_locales.sort + end + + def test_load_translations_reads_every_json_file_under_load_path + Dir.mktmpdir do |dir| + File.write(File.join(dir, 'fr.json'), '{"hello": "Bonjour"}') + Prism::I18n.load_path << dir + Prism::I18n.load_translations! + assert_equal 'Bonjour', Prism::I18n.t('hello', locale: :fr) + end + end + + def test_best_locale_from_accept_picks_exact_match_by_q_value + header = 'fr;q=0.5, pl;q=0.9, en;q=0.1' + assert_equal :pl, Prism::I18n.best_locale_from_accept(header) + end + + def test_best_locale_from_accept_matches_primary_subtag + assert_equal :en, Prism::I18n.best_locale_from_accept('en-US,en;q=0.8') + end + + def test_best_locale_from_accept_returns_nil_when_nothing_available + assert_nil Prism::I18n.best_locale_from_accept('de,es;q=0.5') + end + + def test_best_locale_from_accept_returns_nil_for_blank_header + assert_nil Prism::I18n.best_locale_from_accept('') + assert_nil Prism::I18n.best_locale_from_accept(nil) + end + + def test_changing_default_locale_invalidates_cached_translator + assert_equal 'Hello', Prism::I18n.t('hello', locale: :en) + Prism::I18n.default_locale = :pl + assert_equal 'Czesc', Prism::I18n.t('hello') + end +end