diff --git a/apps/mobile/src/components/home/section-header.mounted.test.tsx b/apps/mobile/src/components/home/section-header.mounted.test.tsx index eb2332ac5a..27d2c11a80 100644 --- a/apps/mobile/src/components/home/section-header.mounted.test.tsx +++ b/apps/mobile/src/components/home/section-header.mounted.test.tsx @@ -77,7 +77,7 @@ describe('SectionHeader mounted layout', () => { expect(label.props.adjustsFontSizeToFit).not.toBe(true); expect(label.children).toEqual(['Live now']); // The tracked class stays for the Latin design; the RTL letter-spacing - // reset applies to Arabic-script copy only, so this Latin label keeps its + // reset applies to RTL-script copy only, so this Latin label keeps its // tracking (see lib/rtl-text.ts and text.rtl-labels.mounted.test.tsx). if (isRTL) { expect(label.props.style).toContainEqual({ writingDirection: 'rtl' }); @@ -105,6 +105,7 @@ describe('SectionHeader mounted layout', () => { expect(text.props.numberOfLines).toBeUndefined(); expect(text.props.allowFontScaling).not.toBe(false); expect(text.props.maxFontSizeMultiplier).toBeUndefined(); + expect(text.props.adjustsFontSizeToFit).not.toBe(true); expect(text.children).toEqual(['See all']); }); diff --git a/apps/mobile/src/components/ui/text.mounted.test.tsx b/apps/mobile/src/components/ui/text.mounted.test.tsx index a7534aca0e..3a506f52c5 100644 --- a/apps/mobile/src/components/ui/text.mounted.test.tsx +++ b/apps/mobile/src/components/ui/text.mounted.test.tsx @@ -161,3 +161,24 @@ describe('Text eyebrow letterspacing', () => { } }); }); + +describe('Text mono variant in an RTL interface', () => { + // The mono variant carries a font that ships no RTL-script glyphs, so RTL + // copy loses the family in RTL while a Latin run such as a session id keeps + // it. + it('drops the mono family for an Arabic mono variant in RTL', () => { + i18nManager.isRTL = true; + const classes = hostClasses( + mount(createElement(Text, { variant: 'mono' }, 'الجلسات الجارية الآن')) + ); + + expect(classes.some(name => name.startsWith('font-mono'))).toBe(false); + }); + + it('keeps the mono family for a session id in RTL', () => { + i18nManager.isRTL = true; + const classes = hostClasses(mount(createElement(Text, { variant: 'mono' }, 'ses_9f2c1a7b'))); + + expect(classes).toContain('font-mono-medium'); + }); +}); diff --git a/apps/mobile/src/lib/rtl-text.test.ts b/apps/mobile/src/lib/rtl-text.test.ts index 935b690a21..6d586d2939 100644 --- a/apps/mobile/src/lib/rtl-text.test.ts +++ b/apps/mobile/src/lib/rtl-text.test.ts @@ -7,6 +7,7 @@ import { JOINED_SCRIPT, NATURAL_LETTER_SPACING, textLetterSpacing, + withoutMonoFamily, } from './rtl-text'; // `rtl-text` imports `I18nManager` for its direction helpers; the real module @@ -54,6 +55,31 @@ describe('hasRtlScript', () => { it('leaves Latin copy alone', () => { expect(hasRtlScript('Live now')).toBe(false); }); + + // The script detection the RTL label treatment was first built on: a plain + // string, a mixed array, and a nested element all reach the copy, so a label + // that mixes scripts counts as RTL script. + it('detects an Arabic string', () => { + expect(hasRtlScript('الجلسات الجارية الآن')).toBe(true); + }); + + it('detects Arabic inside a mixed array of strings', () => { + expect(hasRtlScript(['LIVE NOW', 'عرض الكل'])).toBe(true); + }); + + it('checks every item of an array', () => { + expect(hasRtlScript(['LIVE', 'NOW'])).toBe(false); + }); + + it('recurses into a nested element', () => { + expect(hasRtlScript(createElement('Text', null, 'استكشاف'))).toBe(true); + }); + + it('is false for a number, a boolean and null', () => { + expect(hasRtlScript(42)).toBe(false); + expect(hasRtlScript(true)).toBe(false); + expect(hasRtlScript(null)).toBe(false); + }); }); describe('JOINED_SCRIPT', () => { @@ -110,6 +136,22 @@ describe('containsJoinedScript', () => { }); }); +describe('withoutMonoFamily', () => { + it('drops the mono family and preserves the remaining order', () => { + expect(withoutMonoFamily('font-mono-medium text-[10px] uppercase text-muted-foreground')).toBe( + 'text-[10px] uppercase text-muted-foreground' + ); + }); + + it('drops a variant-prefixed mono family', () => { + expect(withoutMonoFamily('dark:font-mono-semibold text-sm')).toBe('text-sm'); + }); + + it('keeps an unrelated token that merely starts with font-mono', () => { + expect(withoutMonoFamily('font-mono-bold text-sm')).toBe('font-mono-bold text-sm'); + }); +}); + describe('textLetterSpacing', () => { it('returns the natural spacing for a joined script', () => { expect(textLetterSpacing('الرئيسية')).toBe(NATURAL_LETTER_SPACING);