Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove unused export for useLocale (and update tests) #826

Merged
merged 2 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion adapter/src/utils/useLocale.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
setMomentLocale,
} from './localeUtils.js'

export const useLocale = ({ userSettings, configDirection }) => {
const useLocale = ({ userSettings, configDirection }) => {
const [result, setResult] = useState({
locale: undefined,
direction: undefined,
Expand Down
195 changes: 80 additions & 115 deletions adapter/src/utils/useLocale.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { useDataQuery } from '@dhis2/app-runtime'
import i18n from '@dhis2/d2-i18n'
import { renderHook, act } from '@testing-library/react-hooks'
import { renderHook } from '@testing-library/react-hooks'
import moment from 'moment'
import { useLocale } from './useLocale.js'
import { useCurrentUserLocale } from './useLocale.js'

// NOTE ABOUT MOCKS:
// Note about mocks:
// Luckily, `await import(`moment/locale/${locale}`)` as used in
// `setMomentLocale` in `localeUtils.js` works the same in the Jest environment
// as in the real world, so it doesn't need mocking

// NB: To keep tests simpler, useDataQuery will be considered synchronous,
// and loading logic isn't tested
jest.mock('@dhis2/app-runtime', () => ({
...jest.requireActual('@dhis2/app-runtime'),
useDataQuery: jest.fn(),
}))

jest.mock('@dhis2/d2-i18n', () => {
return {
setDefaultNamespace: jest.fn(),
Expand Down Expand Up @@ -37,26 +45,19 @@ jest.mock('moment', () => ({
defineLocale: jest.fn(),
}))

jest.spyOn(document.documentElement, 'setAttribute')

afterEach(() => {
jest.clearAllMocks()
})

test('happy path initial load with en language', () => {
const defaultUserSettings = { keyUiLocale: 'en' }
const { result, rerender } = renderHook((newProps) => useLocale(newProps), {
initialProps: defaultUserSettings,
})

expect(result.current.locale).toBe(undefined)
expect(result.current.direction).toBe(undefined)

act(() => {
rerender({
userSettings: defaultUserSettings,
configDirection: undefined,
})
test('happy path initial load with en language', async () => {
useDataQuery.mockReturnValue({
data: { userSettings: { keyUiLocale: 'en' } },
})
const { result } = renderHook(() => useCurrentUserLocale())

expect(result.current.loading).toBe(false)
expect(result.current.locale.baseName).toBe('en')
expect(result.current.direction).toBe('ltr')
expect(i18n.changeLanguage).toHaveBeenCalledWith('en')
Expand All @@ -65,20 +66,25 @@ test('happy path initial load with en language', () => {
// moment.locale doesn't need to get called if the language is 'en'...
// but it's asynchronous anyway. See following tests
expect(moment.locale).not.toHaveBeenCalled()
expect(document.documentElement.setAttribute).toHaveBeenCalledWith(
'dir',
'ltr'
)
expect(document.documentElement.setAttribute).toHaveBeenCalledWith(
'lang',
'en'
)
})

describe('formerly problematic locales', () => {
// For pt_BR (Portuguese in Brazil), before fixes:
// 1. i18n.dir didn't work because it needs a BCP47-formatted string
// 2. The Moment locale didn't work, because it uses another format
test('pt_BR locale', async () => {
const userSettings = { keyUiLocale: 'pt_BR' }
const { result, waitFor } = renderHook(() =>
useLocale({
userSettings,
configDirection: undefined,
})
)
useDataQuery.mockReturnValue({
data: { userSettings: { keyUiLocale: 'pt_BR' } },
})
const { result, waitFor } = renderHook(() => useCurrentUserLocale())

expect(result.current.direction).toBe('ltr')
// Notice different locale formats
Expand All @@ -100,13 +106,10 @@ describe('formerly problematic locales', () => {
// 3. The Moment locale didn't work, both because of formatting and failing to
// fall back to simpler locales
test('ar_EG locale', async () => {
const userSettings = { keyUiLocale: 'ar_EG' }
const { result, waitFor } = renderHook(() =>
useLocale({
userSettings,
configDirection: undefined,
})
)
useDataQuery.mockReturnValue({
data: { userSettings: { keyUiLocale: 'ar_EG' } },
})
const { result, waitFor } = renderHook(() => useCurrentUserLocale())

expect(result.current.direction).toBe('rtl')
expect(result.current.locale.baseName).toBe('ar-EG')
Expand All @@ -121,13 +124,10 @@ describe('formerly problematic locales', () => {
// 1. i18n.dir didn't work because it needs a BCP47-formatted string
// 2. Moment locales didn't work due to formatting and lack of fallback
test('uz_UZ_Cyrl locale', async () => {
const userSettings = { keyUiLocale: 'uz_UZ_Cyrl' }
const { result, waitFor } = renderHook(() =>
useLocale({
userSettings,
configDirection: undefined,
})
)
useDataQuery.mockReturnValue({
data: { userSettings: { keyUiLocale: 'uz_UZ_Cyrl' } },
})
const { result, waitFor } = renderHook(() => useCurrentUserLocale())

expect(result.current.direction).toBe('ltr')
expect(result.current.locale.baseName).toBe('uz-Cyrl-UZ')
Expand All @@ -138,13 +138,10 @@ describe('formerly problematic locales', () => {
})
// Similar for UZ Latin -- notice difference in the Moment locale
test('uz_UZ_Latn locale', async () => {
const userSettings = { keyUiLocale: 'uz_UZ_Latn' }
const { result, waitFor } = renderHook(() =>
useLocale({
userSettings,
configDirection: undefined,
})
)
useDataQuery.mockReturnValue({
data: { userSettings: { keyUiLocale: 'uz_UZ_Latn' } },
})
const { result, waitFor } = renderHook(() => useCurrentUserLocale())

expect(result.current.direction).toBe('ltr')
expect(result.current.locale.baseName).toBe('uz-Latn-UZ')
Expand All @@ -164,16 +161,12 @@ describe('other userSettings cases', () => {
})

test('proposed keyUiLanguageTag property is used (preferrentially)', async () => {
const userSettings = {
keyUiLocale: 'en',
keyUiLanguageTag: 'pt-BR',
}
const { result, waitFor } = renderHook(() =>
useLocale({
userSettings,
configDirection: undefined,
})
)
useDataQuery.mockReturnValue({
data: {
userSettings: { keyUiLocale: 'en', keyUiLanguageTag: 'pt-BR' },
},
})
const { result, waitFor } = renderHook(() => useCurrentUserLocale())

expect(result.current.direction).toBe('ltr')
expect(result.current.locale.baseName).toBe('pt-BR')
Expand All @@ -184,13 +177,10 @@ describe('other userSettings cases', () => {
})

test('keyUiLocale is missing from user settings for some reason (should fall back to browser language)', async () => {
const userSettings = {}
const { result, waitFor } = renderHook(() =>
useLocale({
userSettings,
configDirection: undefined,
})
)
useDataQuery.mockReturnValue({
data: { userSettings: {} },
})
const { result, waitFor } = renderHook(() => useCurrentUserLocale())

expect(result.current.direction).toBe('rtl')
expect(result.current.locale.baseName).toBe('ar-EG')
Expand All @@ -201,13 +191,10 @@ describe('other userSettings cases', () => {
})

test('keyUiLocale is nonsense (should fall back to browser language)', async () => {
const userSettings = { keyUiLocale: 'shouldCauseError' }
const { result, waitFor } = renderHook(() =>
useLocale({
userSettings,
configDirection: undefined,
})
)
useDataQuery.mockReturnValue({
data: { userSettings: { keyUiLocale: 'shouldCauseError' } },
})
const { result, waitFor } = renderHook(() => useCurrentUserLocale())

expect(result.current.direction).toBe('rtl')
expect(result.current.locale.baseName).toBe('ar-EG')
Expand All @@ -219,16 +206,11 @@ describe('other userSettings cases', () => {
})

describe('config direction is respected for the document direction', () => {
jest.spyOn(document.documentElement, 'setAttribute')

test('ltr is the default and is used even for rtl languages', async () => {
const userSettings = { keyUiLocale: 'ar' }
const { result } = renderHook(() =>
useLocale({
userSettings,
configDirection: undefined,
})
)
useDataQuery.mockReturnValue({
data: { userSettings: { keyUiLocale: 'ar' } },
})
const { result } = renderHook(() => useCurrentUserLocale())

expect(result.current.direction).toBe('rtl')
expect(document.documentElement.setAttribute).toHaveBeenCalledWith(
Expand All @@ -238,13 +220,10 @@ describe('config direction is respected for the document direction', () => {
})

test('rtl will be used for the document if configured, even for an ltr language', () => {
const userSettings = { keyUiLocale: 'en' }
const { result } = renderHook(() =>
useLocale({
userSettings,
configDirection: 'rtl',
})
)
useDataQuery.mockReturnValue({
data: { userSettings: { keyUiLocale: 'en' } },
})
const { result } = renderHook(() => useCurrentUserLocale('rtl'))

expect(result.current.direction).toBe('ltr')
expect(document.documentElement.setAttribute).toHaveBeenCalledWith(
Expand All @@ -254,13 +233,10 @@ describe('config direction is respected for the document direction', () => {
})

test('if auto is used, document dir will match the language dir (ltr)', () => {
const userSettings = { keyUiLocale: 'en' }
const { result } = renderHook(() =>
useLocale({
userSettings,
configDirection: 'auto',
})
)
useDataQuery.mockReturnValue({
data: { userSettings: { keyUiLocale: 'en' } },
})
const { result } = renderHook(() => useCurrentUserLocale('auto'))

expect(result.current.direction).toBe('ltr')
expect(document.documentElement.setAttribute).toHaveBeenCalledWith(
Expand All @@ -270,13 +246,10 @@ describe('config direction is respected for the document direction', () => {
})

test('if auto is used, document dir will match the language dir (ltr)', () => {
const userSettings = { keyUiLocale: 'ar' }
const { result } = renderHook(() =>
useLocale({
userSettings,
configDirection: 'auto',
})
)
useDataQuery.mockReturnValue({
data: { userSettings: { keyUiLocale: 'ar' } },
})
const { result } = renderHook(() => useCurrentUserLocale('auto'))

expect(result.current.direction).toBe('rtl')
expect(document.documentElement.setAttribute).toHaveBeenCalledWith(
Expand All @@ -286,13 +259,10 @@ describe('config direction is respected for the document direction', () => {
})

test('nonstandard config directions fall back to ltr', () => {
const userSettings = { keyUiLocale: 'ar' }
const { result } = renderHook(() =>
useLocale({
userSettings,
configDirection: 'whoopslol',
})
)
useDataQuery.mockReturnValue({
data: { userSettings: { keyUiLocale: 'ar' } },
})
const { result } = renderHook(() => useCurrentUserLocale('whoopslol'))

expect(result.current.direction).toBe('rtl')
expect(document.documentElement.setAttribute).toHaveBeenCalledWith(
Expand All @@ -303,15 +273,10 @@ describe('config direction is respected for the document direction', () => {
})

test('document `lang` attribute is set', () => {
jest.spyOn(document.documentElement, 'setAttribute')
const userSettings = { keyUiLocale: 'pt-BR' }

renderHook(() =>
useLocale({
userSettings,
configDirection: undefined,
})
)
useDataQuery.mockReturnValue({
data: { userSettings: { keyUiLocale: 'pt_BR' } },
})
renderHook(() => useCurrentUserLocale())

expect(document.documentElement.setAttribute).toHaveBeenCalledWith(
'lang',
Expand Down
Loading