Lingua-Text

 view release on metacpan or  search on metacpan

t/integration.t  view on Meta::CPAN

	# Capture stringify results (avoid void-context lint warnings).
	# First call: cache primed with zz_ZZ, now LANG=en_US -> cache miss
	my $r1 = "$t";    # slow path: detect() may be called
	# Second and third: env unchanged -> cache hit -> detect() NOT called
	my $r2 = "$t";
	my $r3 = "$t";

	my @calls = $spy->();
	cmp_ok(scalar @calls, '<=', 1,
		'detect() called at most once for repeated stringifies with same LANG');

	diag "detect() call count: " . scalar(@calls) if $ENV{TEST_VERBOSE};

	# Now change LANG: cache must be invalidated, detect() called again
	$ENV{LANG} = $FR_LOCALE;
	my $r4 = "$t";    # cache miss -> detect() called once more
	my @calls2 = $spy->();
	cmp_ok(scalar @calls2, '>=', 1,
		'detect() called again after LANG changes (cache invalidation)');

	restore_all();
};

# ---------------------------------------------------------------------------
# 11. Object::Configure integration: injected non-language keys coexist with
#     language translations without corrupting the public API.
#
# Object::Configure injects keys ('logger', 'Database__Abstraction',
# 'config_path') into new()'s params.  These are not ISO 639-1 codes, so
# encode() skips them and the AUTOLOAD accessor returns undef for them.
# The language translations must remain intact and accessible.
# ---------------------------------------------------------------------------
subtest 'Object::Configure integration -- injected keys do not corrupt API' => sub {
	local %ENV;

	my $t = Lingua::Text->new(en => $EN_TEXT, fr => $FR_TEXT);

	# The language translations must be accessible regardless of injected keys
	is($t->en(), $EN_TEXT,  'en translation accessible despite injected keys');
	is($t->fr(), $FR_TEXT, 'fr translation accessible despite injected keys');

	# AUTOLOAD guard: 2-letter rule blocks access to 'logger' via method name.
	# 'logger' is 6 chars so the /^[a-z]{2}$/ gate returns undef silently.
	ok(!defined($t->logger_test()), 'AUTOLOAD: 6-char name rejected silently');

	# encode() must NOT corrupt the injected objects (security V2 guard)
	$t->encode();
	is($t->en(), $EN_TEXT, 'en unchanged after encode() (ASCII, no entity needed)');
	is($t->fr(), $FR_TEXT, 'fr unchanged after encode() (ASCII French, no entity needed)');

	# Verify encode() with non-ASCII in presence of injected keys
	my $t2 = Lingua::Text->new(fr => $ETUDE);
	$t2->encode();
	is($t2->fr(), $ETUDE_E, 'fr entity-encoded correctly despite injected keys');
};

# ---------------------------------------------------------------------------
# 12. Locale detection integration: full env-var precedence chain
#
# POD DESCRIPTION: detection uses LANGUAGE, LC_ALL, LC_MESSAGES, LANG
# in that priority order.  This test drives the full detection cascade.
# ---------------------------------------------------------------------------
subtest 'locale detection -- precedence chain' => sub {
	mock 'I18N::LangTags::Detect::detect' => sub { () };    # disable HTTP path

	# LANG lowest priority: used when others absent
	{
		local %ENV;
		$ENV{LANG} = $FR_LOCALE;
		my $t = Lingua::Text->new(en => $EN_TEXT, fr => $FR_TEXT);
		is("$t", $FR_TEXT, 'LANG=fr_FR: stringify returns French');
	}

	# LC_MESSAGES overrides LANG
	{
		local %ENV;
		$ENV{LANG}        = $FR_LOCALE;    # lower priority
		$ENV{LC_MESSAGES} = $DE_LOCALE;    # higher priority
		my $t = Lingua::Text->new(en => $EN_TEXT, fr => $FR_TEXT, de => $DE_TEXT);
		is("$t", $DE_TEXT, 'LC_MESSAGES overrides LANG');
	}

	# LC_ALL overrides LC_MESSAGES
	{
		local %ENV;
		$ENV{LC_MESSAGES} = $DE_LOCALE;    # lower priority
		$ENV{LC_ALL}      = $FR_LOCALE;    # higher priority
		my $t = Lingua::Text->new(en => $EN_TEXT, fr => $FR_TEXT, de => $DE_TEXT);
		is("$t", $FR_TEXT, 'LC_ALL overrides LC_MESSAGES');
	}

	# LANGUAGE (colon-separated list) overrides LC_ALL
	{
		local %ENV;
		$ENV{LC_ALL}    = $FR_LOCALE;      # lower priority
		$ENV{LANGUAGE}  = 'de:en';         # higher priority -- first valid tag wins
		my $t = Lingua::Text->new(en => $EN_TEXT, fr => $FR_TEXT, de => $DE_TEXT);
		is("$t", $DE_TEXT, 'LANGUAGE overrides LC_ALL');
	}

	# POSIX C locale maps to English
	{
		local %ENV;
		$ENV{LANG} = 'C';
		my $t = Lingua::Text->new(en => $EN_TEXT, fr => $FR_TEXT);
		is("$t", $EN_TEXT, 'POSIX C locale maps to English');
	}

	# POSIX C.UTF-8 variant also maps to English
	{
		local %ENV;
		$ENV{LANG} = 'C.UTF-8';
		my $t = Lingua::Text->new(en => $EN_TEXT, fr => $FR_TEXT);
		is("$t", $EN_TEXT, 'POSIX C.UTF-8 locale maps to English');
	}

	restore_all();
};

# ---------------------------------------------------------------------------
# 13. Cross-locale object sharing: same object queried from multiple locales



( run in 0.842 second using v1.01-cache-2.11-cpan-e7c6538aa59 )