mirror of
https://github.com/cupcakearmy/svelte-i18n.git
synced 2024-11-16 09:59:58 +01:00
test: 💍 add tests for config and utils
This commit is contained in:
parent
817adb6e4e
commit
e56bfbd333
@ -7,7 +7,7 @@ import {
|
||||
CallExpression,
|
||||
Identifier,
|
||||
} from 'estree'
|
||||
import resolvePath from 'object-resolve-path'
|
||||
import delve from 'dlv'
|
||||
import { walk } from 'estree-walker'
|
||||
import { Ast } from 'svelte/types/compiler/interfaces'
|
||||
import { parse } from 'svelte/compiler'
|
||||
@ -209,7 +209,7 @@ export function extractMessages(
|
||||
} else {
|
||||
if (
|
||||
overwrite === false &&
|
||||
typeof resolvePath(accumulator, message.meta.id) !== 'undefined'
|
||||
typeof delve(accumulator, message.meta.id) !== 'undefined'
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
@ -2,9 +2,20 @@ import { getClientLocale } from './includes/utils'
|
||||
import { ConfigureOptions } from './types'
|
||||
import { $locale } from './stores/locale'
|
||||
|
||||
let fallbackLocale: string = null
|
||||
let loadingDelay = 200
|
||||
const formats: any = {
|
||||
interface Formats {
|
||||
number: Record<string, any>
|
||||
date: Record<string, any>
|
||||
time: Record<string, any>
|
||||
}
|
||||
|
||||
interface Options {
|
||||
fallbackLocale: string
|
||||
initialLocale: string
|
||||
formats: Formats
|
||||
loadingDelay: number
|
||||
}
|
||||
|
||||
export const defaultFormats: Formats = {
|
||||
number: {
|
||||
scientific: { notation: 'scientific' },
|
||||
engineering: { notation: 'engineering' },
|
||||
@ -35,33 +46,44 @@ const formats: any = {
|
||||
},
|
||||
}
|
||||
|
||||
export function getFallbackLocale() {
|
||||
return fallbackLocale
|
||||
export const defaultOptions: Options = {
|
||||
fallbackLocale: null,
|
||||
initialLocale: null,
|
||||
loadingDelay: 200,
|
||||
formats: defaultFormats,
|
||||
}
|
||||
|
||||
export function getLoadingDelay() {
|
||||
return loadingDelay
|
||||
}
|
||||
const options: Options = defaultOptions
|
||||
|
||||
export function getFormats() {
|
||||
return formats
|
||||
export function getOptions() {
|
||||
return options
|
||||
}
|
||||
|
||||
export function configure(opts: ConfigureOptions) {
|
||||
fallbackLocale = opts.fallbackLocale
|
||||
const fallbackLocale = (options.fallbackLocale = opts.fallbackLocale)
|
||||
|
||||
if (opts.initialLocale) {
|
||||
$locale.set(getClientLocale(opts.initialLocale) || fallbackLocale)
|
||||
} else {
|
||||
$locale.set(fallbackLocale)
|
||||
}
|
||||
const initialLocale = opts.initialLocale
|
||||
? typeof opts.initialLocale === 'string'
|
||||
? opts.initialLocale
|
||||
: getClientLocale(opts.initialLocale) || fallbackLocale
|
||||
: fallbackLocale
|
||||
|
||||
$locale.set(initialLocale)
|
||||
options.initialLocale = initialLocale
|
||||
|
||||
if (opts.formats) {
|
||||
if ('number' in opts.formats)
|
||||
Object.assign(formats.number, opts.formats.number)
|
||||
if ('date' in opts.formats) Object.assign(formats.date, opts.formats.date)
|
||||
if ('time' in opts.formats) Object.assign(formats.time, opts.formats.time)
|
||||
if ('number' in opts.formats) {
|
||||
Object.assign(options.formats.number, opts.formats.number)
|
||||
}
|
||||
if ('date' in opts.formats) {
|
||||
Object.assign(options.formats.date, opts.formats.date)
|
||||
}
|
||||
if ('time' in opts.formats) {
|
||||
Object.assign(options.formats.time, opts.formats.time)
|
||||
}
|
||||
}
|
||||
|
||||
if (loadingDelay != null) loadingDelay = loadingDelay
|
||||
if (opts.loadingDelay != null) {
|
||||
options.loadingDelay = opts.loadingDelay
|
||||
}
|
||||
}
|
||||
|
@ -16,15 +16,13 @@ export function lower(str: string) {
|
||||
return str.toLocaleLowerCase()
|
||||
}
|
||||
|
||||
const getFromURL = (urlPart: string, key: string) => {
|
||||
const keyVal = urlPart
|
||||
.substr(1)
|
||||
.split('&')
|
||||
.find(i => i.indexOf(key) === 0)
|
||||
const getFromQueryString = (queryString: string, key: string) => {
|
||||
const keyVal = queryString.split('&').find(i => i.indexOf(`${key}=`) === 0)
|
||||
|
||||
if (keyVal) {
|
||||
return keyVal.split('=').pop()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const getFirstMatch = (base: string, pattern: RegExp) => {
|
||||
@ -42,7 +40,8 @@ export const getClientLocale = ({
|
||||
}: GetClientLocaleOptions) => {
|
||||
let locale
|
||||
|
||||
if (typeof window === 'undefined') return fallback
|
||||
// istanbul ignore next
|
||||
if (typeof window === 'undefined') return null
|
||||
|
||||
if (hostname) {
|
||||
locale = getFirstMatch(window.location.hostname, hostname)
|
||||
@ -61,18 +60,12 @@ export const getClientLocale = ({
|
||||
}
|
||||
|
||||
if (search) {
|
||||
locale =
|
||||
typeof search === 'string'
|
||||
? getFromURL(window.location.search, search)
|
||||
: getFirstMatch(window.location.search, search)
|
||||
locale = getFromQueryString(window.location.search.substr(1), search)
|
||||
if (locale) return locale
|
||||
}
|
||||
|
||||
if (hash) {
|
||||
locale =
|
||||
typeof hash === 'string'
|
||||
? getFromURL(window.location.hash, hash)
|
||||
: getFirstMatch(window.location.hash, hash)
|
||||
locale = getFromQueryString(window.location.hash.substr(1), hash)
|
||||
if (locale) return locale
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
import { writable } from 'svelte/store'
|
||||
|
||||
import { flushQueue, hasLocaleQueue } from '../includes/loaderQueue'
|
||||
import { getClientLocale } from '../includes/utils'
|
||||
import { GetClientLocaleOptions } from '../types'
|
||||
import { getOptions } from '../configs'
|
||||
|
||||
import { getClosestAvailableLocale } from './dictionary'
|
||||
import { setFallbackLocale, getFallbackLocale } from '../configs'
|
||||
|
||||
let current: string
|
||||
const $locale = writable(null)
|
||||
@ -25,8 +23,10 @@ export function isRelatedLocale(localeA: string, localeB: string) {
|
||||
export function getFallbackOf(locale: string) {
|
||||
const index = locale.lastIndexOf('-')
|
||||
if (index > 0) return locale.slice(0, index)
|
||||
if (getFallbackLocale() && !isRelatedLocale(locale, getFallbackLocale())) {
|
||||
return getFallbackLocale()
|
||||
|
||||
const { fallbackLocale } = getOptions()
|
||||
if (fallbackLocale && !isRelatedLocale(locale, fallbackLocale)) {
|
||||
return fallbackLocale
|
||||
}
|
||||
return null
|
||||
}
|
||||
@ -36,8 +36,9 @@ export function getRelatedLocalesOf(locale: string): string[] {
|
||||
.split('-')
|
||||
.map((_, i, arr) => arr.slice(0, i + 1).join('-'))
|
||||
|
||||
if (getFallbackLocale() && !isRelatedLocale(locale, getFallbackLocale())) {
|
||||
return locales.concat(getRelatedLocalesOf(getFallbackLocale()))
|
||||
const { fallbackLocale } = getOptions()
|
||||
if (fallbackLocale && !isRelatedLocale(locale, fallbackLocale)) {
|
||||
return locales.concat(getRelatedLocalesOf(fallbackLocale))
|
||||
}
|
||||
return locales
|
||||
}
|
||||
|
@ -50,16 +50,15 @@ export interface MessagesLoader {
|
||||
|
||||
export interface GetClientLocaleOptions {
|
||||
navigator?: boolean
|
||||
hash?: string | RegExp
|
||||
search?: string | RegExp
|
||||
default?: string
|
||||
hash?: string
|
||||
search?: string
|
||||
pathname?: RegExp
|
||||
hostname?: RegExp
|
||||
}
|
||||
|
||||
export interface ConfigureOptions {
|
||||
fallbackLocale: string
|
||||
initialLocale?: GetClientLocaleOptions
|
||||
initialLocale?: string | GetClientLocaleOptions
|
||||
formats?: Partial<Formats>
|
||||
loadingDelay?: number
|
||||
}
|
||||
|
@ -1,14 +1,65 @@
|
||||
import { get } from 'svelte/store'
|
||||
|
||||
import {
|
||||
getFallbackLocale,
|
||||
getLoadingDelay,
|
||||
getFormats,
|
||||
configure,
|
||||
getOptions,
|
||||
defaultOptions,
|
||||
defaultFormats,
|
||||
} from '../../src/client/configs'
|
||||
import { $locale } from '../../src/client/stores/locale'
|
||||
|
||||
beforeEach(() => {
|
||||
configure(defaultOptions)
|
||||
})
|
||||
|
||||
test('configures the fallback locale', () => {
|
||||
expect(getFallbackLocale()).toBe(null)
|
||||
expect(getOptions().fallbackLocale).toBe(null)
|
||||
configure({
|
||||
fallbackLocale: 'en',
|
||||
})
|
||||
expect(getFallbackLocale()).toBe('en')
|
||||
expect(getOptions().fallbackLocale).toBe('en')
|
||||
})
|
||||
|
||||
test('configures the initial locale by string', () => {
|
||||
configure({
|
||||
fallbackLocale: 'pt',
|
||||
initialLocale: 'en',
|
||||
})
|
||||
expect(getOptions().initialLocale).toBe('en')
|
||||
expect(get($locale)).toBe('en')
|
||||
})
|
||||
|
||||
test('configures the initial locale by client heuristics', () => {
|
||||
delete window.location
|
||||
window.location = {
|
||||
search: '?lang=en-US&foo',
|
||||
pathname: '/',
|
||||
hostname: 'example.com',
|
||||
hash: '',
|
||||
} as any
|
||||
|
||||
configure({
|
||||
fallbackLocale: 'pt',
|
||||
initialLocale: {
|
||||
search: 'lang',
|
||||
},
|
||||
})
|
||||
expect(getOptions().initialLocale).toBe('en-US')
|
||||
expect(get($locale)).toBe('en-US')
|
||||
})
|
||||
|
||||
test('adds custom formats for time, date and number values', () => {
|
||||
const customFormats = require('../fixtures/formats.json')
|
||||
|
||||
configure({
|
||||
fallbackLocale: 'en',
|
||||
formats: customFormats,
|
||||
})
|
||||
expect(getOptions().formats).toMatchObject(defaultFormats)
|
||||
expect(getOptions().formats).toMatchObject(customFormats)
|
||||
})
|
||||
|
||||
test('sets the minimum delay to set the loading store value', () => {
|
||||
configure({ fallbackLocale: 'en', loadingDelay: 300 })
|
||||
expect(getOptions().loadingDelay).toBe(300)
|
||||
})
|
||||
|
@ -99,47 +99,6 @@
|
||||
// })
|
||||
|
||||
// describe('utilities', () => {
|
||||
// describe('get locale', () => {
|
||||
// beforeEach(() => {
|
||||
// delete window.location
|
||||
// window.location = {
|
||||
// pathname: '/',
|
||||
// hostname: 'example.com',
|
||||
// hash: '',
|
||||
// search: '',
|
||||
// } as any
|
||||
// })
|
||||
|
||||
// it('should get the locale based on the passed hash parameter', () => {
|
||||
// window.location.hash = '#locale=en-US&lang=pt-BR'
|
||||
// expect(getClientLocale({ hash: 'lang' })).toBe('pt-BR')
|
||||
// })
|
||||
|
||||
// it('should get the locale based on the passed search parameter', () => {
|
||||
// window.location.search = '?locale=en-US&lang=pt-BR'
|
||||
// expect(getClientLocale({ search: 'lang' })).toBe('pt-BR')
|
||||
// })
|
||||
|
||||
// it('should get the locale based on the navigator language', () => {
|
||||
// expect(getClientLocale({ navigator: true })).toBe(
|
||||
// window.navigator.language
|
||||
// )
|
||||
// })
|
||||
|
||||
// it('should get the default locale', () => {
|
||||
// expect(getClientLocale({ default: 'pt' })).toBe('pt')
|
||||
// })
|
||||
|
||||
// it('should get the fallback locale', () => {
|
||||
// window.location.pathname = '/en-US/foo/'
|
||||
// expect(getClientLocale({ pathname: /^\/(.*?)\// })).toBe('en-US')
|
||||
// })
|
||||
|
||||
// it('should get the fallback locale', () => {
|
||||
// window.location.hostname = 'pt.example.com'
|
||||
// expect(getClientLocale({ hostname: /^(.*?)\./ })).toBe('pt')
|
||||
// })
|
||||
// })
|
||||
|
||||
// describe('format utils', () => {
|
||||
// beforeAll(async () => {
|
||||
@ -184,31 +143,6 @@
|
||||
// })
|
||||
|
||||
// describe('custom formats', () => {
|
||||
// beforeAll(async () => {
|
||||
// await locale.set('pt-BR')
|
||||
// })
|
||||
|
||||
// it('should have default number custom formats', () => {
|
||||
// expect(customFormats.number).toMatchObject({
|
||||
// scientific: { notation: 'scientific' },
|
||||
// engineering: { notation: 'engineering' },
|
||||
// compactLong: { notation: 'compact', compactDisplay: 'long' },
|
||||
// compactShort: { notation: 'compact', compactDisplay: 'short' },
|
||||
// })
|
||||
// })
|
||||
|
||||
// it('should allow to add custom formats', () => {
|
||||
// addCustomFormats({
|
||||
// number: {
|
||||
// usd: { style: 'currency', currency: 'USD' },
|
||||
// },
|
||||
// })
|
||||
|
||||
// expect(customFormats.number).toMatchObject({
|
||||
// usd: { style: 'currency', currency: 'USD' },
|
||||
// })
|
||||
// })
|
||||
|
||||
// it('should format messages with custom formats', async () => {
|
||||
// addCustomFormats({
|
||||
// number: {
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
$locale,
|
||||
isRelatedLocale,
|
||||
} from '../../src/client/stores/locale'
|
||||
import { getFallbackLocale, configure } from '../../src/client/configs'
|
||||
import { getOptions, configure } from '../../src/client/configs'
|
||||
|
||||
beforeEach(() => {
|
||||
configure({ fallbackLocale: undefined })
|
||||
@ -17,7 +17,7 @@ beforeEach(() => {
|
||||
|
||||
test('sets and gets the fallback locale', () => {
|
||||
configure({ fallbackLocale: 'en' })
|
||||
expect(getFallbackLocale()).toBe('en')
|
||||
expect(getOptions().fallbackLocale).toBe('en')
|
||||
})
|
||||
|
||||
test('checks if a locale is a fallback locale of another locale', () => {
|
||||
@ -104,7 +104,7 @@ test('gets the current locale', () => {
|
||||
test('if no initial locale is set, set the locale to the fallback', () => {
|
||||
configure({ fallbackLocale: 'pt' })
|
||||
expect(get($locale)).toBe('pt')
|
||||
expect(getFallbackLocale()).toBe('pt')
|
||||
expect(getOptions().fallbackLocale).toBe('pt')
|
||||
})
|
||||
|
||||
test('if no initial locale was found, set to the fallback locale', () => {
|
||||
@ -115,5 +115,5 @@ test('if no initial locale was found, set to the fallback locale', () => {
|
||||
},
|
||||
})
|
||||
expect(get($locale)).toBe('en')
|
||||
expect(getFallbackLocale()).toBe('en')
|
||||
expect(getOptions().fallbackLocale).toBe('en')
|
||||
})
|
||||
|
65
test/client/utils.test.ts
Normal file
65
test/client/utils.test.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import {
|
||||
getClientLocale,
|
||||
capital,
|
||||
title,
|
||||
upper,
|
||||
lower,
|
||||
} from '../../src/client/includes/utils'
|
||||
|
||||
describe('getting client locale', () => {
|
||||
beforeEach(() => {
|
||||
delete window.location
|
||||
window.location = {
|
||||
pathname: '/',
|
||||
hostname: 'example.com',
|
||||
hash: '',
|
||||
search: '',
|
||||
} as any
|
||||
})
|
||||
|
||||
test('gets the locale based on the passed hash parameter', () => {
|
||||
window.location.hash = '#locale=en-US&lang=pt-BR'
|
||||
expect(getClientLocale({ hash: 'lang' })).toBe('pt-BR')
|
||||
})
|
||||
|
||||
test('gets the locale based on the passed search parameter', () => {
|
||||
window.location.search = '?locale=en-US&lang=pt-BR'
|
||||
expect(getClientLocale({ search: 'lang' })).toBe('pt-BR')
|
||||
})
|
||||
|
||||
test('gets the locale based on the navigator language', () => {
|
||||
expect(getClientLocale({ navigator: true })).toBe(window.navigator.language)
|
||||
})
|
||||
|
||||
test('gets the locale based on the pathname', () => {
|
||||
window.location.pathname = '/en-US/foo/'
|
||||
expect(getClientLocale({ pathname: /^\/(.*?)\// })).toBe('en-US')
|
||||
})
|
||||
|
||||
test('gets the locale base on the hostname', () => {
|
||||
window.location.hostname = 'pt.example.com'
|
||||
expect(getClientLocale({ hostname: /^(.*?)\./ })).toBe('pt')
|
||||
})
|
||||
|
||||
test('returns null if no locale was found', () => {
|
||||
expect(getClientLocale({ search: 'lang' })).toBe(null)
|
||||
})
|
||||
})
|
||||
|
||||
describe('string utilities', () => {
|
||||
test('transforms a string into capital case', () => {
|
||||
expect(capital('lowercase string')).toMatch('Lowercase string')
|
||||
})
|
||||
|
||||
test('transforms a string into title case', () => {
|
||||
expect(title('lowercase string')).toMatch('Lowercase String')
|
||||
})
|
||||
|
||||
test('transforms a string into uppercase', () => {
|
||||
expect(upper('lowercase string')).toMatch('LOWERCASE STRING')
|
||||
})
|
||||
|
||||
test('transforms a string into lowercase', () => {
|
||||
expect(lower('UPPERCASE STRING')).toMatch('uppercase string')
|
||||
})
|
||||
})
|
12
test/fixtures/formats.json
vendored
Normal file
12
test/fixtures/formats.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"number": {
|
||||
"usd": { "style": "currency", "currency": "USD" },
|
||||
"brl": { "style": "currency", "currency": "BRL" }
|
||||
},
|
||||
"date": {
|
||||
"customDate": { "year": "numeric", "era": "short" }
|
||||
},
|
||||
"time": {
|
||||
"customTime": { "hour": "2-digit", "minute": "2-digit" }
|
||||
}
|
||||
}
|
@ -1928,6 +1928,11 @@ diff-sequences@^24.9.0:
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
|
||||
integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
|
||||
|
||||
dlv@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
|
||||
integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
|
||||
|
||||
doctrine@1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
|
||||
|
Loading…
Reference in New Issue
Block a user