# frozen_string_literal: true require "test_helper" class AcceptLanguageTest < Minitest::Test def assert_language(item, expect = {}) assert_equal expect[:code], item.code, "failed code comparison" if expect[:region] assert_equal expect[:region], item.region, "failed region comparison" else assert_nil item.region, "region should be nil; got #{item.region.inspect} instead" end assert_equal expect[:quality], item.quality, "failed quality comparison" end test "returns full language" do language = Browser::AcceptLanguage.new("en-GB") assert_equal "en-GB", language.full end test "returns language name" do language = Browser::AcceptLanguage.new("en-GB") assert_equal "English/United Kingdom", language.name language = Browser::AcceptLanguage.new("en") assert_equal "English", language.name end test "returns nil for unknown languages" do language = Browser::AcceptLanguage.new("unknown") assert_nil language.name end test "returns code" do language = Browser::AcceptLanguage.new("en-GB") assert_equal "en", language.code end test "returns formatted code" do %w[EN-GB En-GB eN-GB].each do |locale| language = Browser::AcceptLanguage.new(locale) assert_equal "en", language.code end end test "returns region" do language = Browser::AcceptLanguage.new("en-GB") assert_equal "GB", language.region end test "returns formatted region" do %w[en-gb en-Gb en-gB].each do |locale| language = Browser::AcceptLanguage.new(locale) assert_equal "GB", language.region end end test "returns nil for language without region" do language = Browser::AcceptLanguage.new("en") assert_nil language.region end test "parses language with quality" do language = Browser::AcceptLanguage.new("en-GB;q=0.8") assert_language language, code: "en", region: "GB", quality: 0.8 end test "parses language without quality" do language = Browser::AcceptLanguage.new("en-GB") assert_language language, code: "en", region: "GB", quality: 1.0 end test "parses language without region" do language = Browser::AcceptLanguage.new("en") assert_language language, code: "en", region: nil, quality: 1.0 end test "ignores multi-part region" do language = Browser::AcceptLanguage.new("az-AZ-Cyrl") assert_language language, code: "az", region: "AZ", quality: 1.0 end test "parses multi-language set" do result = Browser::AcceptLanguage.parse("fr-CA,fr;q=0.8") assert_equal 2, result.count assert_language result[0], code: "fr", region: "CA", quality: 1.0 assert_language result[1], code: "fr", region: nil, quality: 0.8 end test "parses wildcard" do result = Browser::AcceptLanguage.parse("fr-CA,*;q=0.8") assert_language result[0], code: "fr", region: "CA", quality: 1.0 assert_language result[1], code: "*", region: nil, quality: 0.8 end test "parses complex set" do accept_language = "fr-CA,fr;q=0.8,en-US;q=0.6,en;q=0.4,*;q=0.1" result = Browser::AcceptLanguage.parse(accept_language) assert_language result[0], code: "fr", region: "CA", quality: 1.0 assert_language result[1], code: "fr", region: nil, quality: 0.8 assert_language result[2], code: "en", region: "US", quality: 0.6 assert_language result[3], code: "en", region: nil, quality: 0.4 assert_language result[4], code: "*", region: nil, quality: 0.1 end test "handles random white spaces" do accept_language = "fr-CA, fr;q=0.8, en-US;q=0.6,en;q=0.4, *;q=0.1" result = Browser::AcceptLanguage.parse(accept_language) assert_language result[0], code: "fr", region: "CA", quality: 1.0 assert_language result[1], code: "fr", region: nil, quality: 0.8 assert_language result[2], code: "en", region: "US", quality: 0.6 assert_language result[3], code: "en", region: nil, quality: 0.4 assert_language result[4], code: "*", region: nil, quality: 0.1 end test "sorts based on quality" do accept_language = "fr-CA,fr;q=0.2,en-US;q=0.6,en;q=0.4,*;q=0.5" result = Browser::AcceptLanguage.parse(accept_language) assert_language result[0], code: "fr", region: "CA", quality: 1.0 assert_language result[1], code: "en", region: "US", quality: 0.6 assert_language result[2], code: "*", region: nil, quality: 0.5 assert_language result[3], code: "en", region: nil, quality: 0.4 assert_language result[4], code: "fr", region: nil, quality: 0.2 end test "sorts the same quality in a descending priority" do accept_language = "fr-CA,fr;q=0.2,en-US;q=0.2,en" result = Browser::AcceptLanguage.parse(accept_language) assert_language result[0], code: "fr", region: "CA", quality: 1.0 assert_language result[1], code: "en", region: nil, quality: 1.0 assert_language result[2], code: "fr", region: nil, quality: 0.2 assert_language result[3], code: "en", region: "US", quality: 0.2 end test "rejects quality values equals to zero (#241)" do result = Browser::AcceptLanguage.parse("de-DE,ru;q=0.9,de;q=0.8,en;q=0.") assert_equal 3, result.size assert_language result[0], code: "de", region: "DE", quality: 1.0 assert_language result[1], code: "ru", region: nil, quality: 0.9 assert_language result[2], code: "de", region: nil, quality: 0.8 end test "handles invalid quality values that look like a number" do accept_language = "fr-CH, fr;q=0.9, en;q=0.8, de;q=0..7, *;q=0.5" result = Browser::AcceptLanguage.parse(accept_language) assert_equal 5, result.size assert_language result[3], code: "de", region: nil, quality: 0.7 end test "sets default quality value for invalid strings" do result = Browser::AcceptLanguage.parse(";q=0.0.0.0") assert_equal 0.1, result[0].quality # rubocop:disable Minitest/AssertInDelta end end