Skip to content

Commit

Permalink
fix: imporve getNavigatorLanguages more cache strictly (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
kazupon authored Sep 24, 2023
1 parent 81cbb8e commit f37bb40
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 52 deletions.
17 changes: 17 additions & 0 deletions build.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { defineBuildConfig } from 'unbuild'

export default defineBuildConfig({
declaration: true,
replace: {
'import.meta.vitest': undefined,
},
rollup: {
emitCJS: true,
inlineDependencies: true,
Expand All @@ -21,4 +24,18 @@ export default defineBuildConfig({
},
],
externals: ['h3'],
hooks: {
'rollup:options': (_ctx, options) => {
// deno-lint-ignore no-explicit-any
;(options.plugins as any).push({
name: 'workaround-strip-in-source-test',
transform(code: string, _id: string) {
return {
code: code.replace(/import.meta.vitest/g, 'false'),
map: null,
}
},
})
},
},
})
2 changes: 2 additions & 0 deletions src/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ declare namespace NodeJS {
LANGUAGE?: string
}
}

declare let __TEST__: boolean
50 changes: 1 addition & 49 deletions src/node.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { afterEach, beforeEach, describe, expect, test } from 'vitest'
import { describe, expect, test } from 'vitest'
import supertest from 'supertest'
import {
getAcceptLanguage,
getAcceptLanguages,
getAcceptLocale,
getAcceptLocales,
getCookieLocale,
getNavigatorLanguage,
getNavigatorLanguages,
setCookieLocale,
} from './node.ts'
import { createServer, IncomingMessage, OutgoingMessage } from 'node:http'
Expand Down Expand Up @@ -246,49 +244,3 @@ describe('setCookieLocale', () => {
.toThrowError(/locale is invalid: j/)
})
})

describe('getNavigatorLanguages', () => {
let orgEnv = {}
beforeEach(() => {
orgEnv = process.env
})
afterEach(() => {
process.env = orgEnv
})

test('basic', () => {
process.env.LC_ALL = 'en-GB'
process.env.LC_MESSAGES = 'en-US'
process.env.LANG = 'ja-JP'
process.env.LANGUAGE = 'en'

const values = [
'en-GB',
'en-US',
'ja-JP',
'en',
]
expect(getNavigatorLanguages()).toEqual(values)
expect(getNavigatorLanguages()).toEqual(values)
})
})

describe('getNavigatorLanguage', () => {
let orgEnv = {}
beforeEach(() => {
orgEnv = process.env
})
afterEach(() => {
process.env = orgEnv
})

test('basic', () => {
process.env.LC_ALL = 'en-GB'
process.env.LC_MESSAGES = 'en-US'
process.env.LANG = 'ja-JP'
process.env.LANGUAGE = 'en'

expect(getNavigatorLanguage()).toEqual('en-GB')
expect(getNavigatorLanguage()).toEqual('en-GB')
})
})
111 changes: 109 additions & 2 deletions src/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ let navigatorLanguages: string[] | undefined
* @returns {Array<string>} {@link https://datatracker.ietf.org/doc/html/rfc4646#section-2.1 | BCP 47 language tags}, if you can't get the language tag, return an empty array.
*/
export function getNavigatorLanguages(): readonly string[] {
if (navigatorLanguages) {
if (navigatorLanguages && navigatorLanguages.length > 0) {
return navigatorLanguages
}

Expand All @@ -235,7 +235,65 @@ export function getNavigatorLanguages(): readonly string[] {
return navigatorLanguages = [...langs].filter(Boolean)
}

let navigatorLanguage: string | undefined
/**
* in-source testing for `getNavigatorLanguages`
*/
if (import.meta.vitest) {
const { describe, test, expect, afterEach, vi } = import.meta.vitest

describe('getNavigatorLanguages', () => {
afterEach(() => {
vi.resetAllMocks()
navigatorLanguages = undefined
})

test('basic', () => {
vi.spyOn(process, 'env', 'get').mockReturnValue({
LC_ALL: 'en-GB',
LC_MESSAGES: 'en-US',
LANG: 'ja-JP',
LANGUAGE: 'en',
})

const values = [
'en-GB',
'en-US',
'ja-JP',
'en',
]
expect(getNavigatorLanguages()).toEqual(values)
// cache checking
expect(navigatorLanguages).toEqual(values)
})

test('duplicate language', () => {
vi.spyOn(process, 'env', 'get').mockReturnValue({
LC_ALL: 'en-US',
LC_MESSAGES: 'en-US',
LANG: 'ja-JP',
LANGUAGE: 'ja-JP',
})

const values = [
'en-US',
'ja-JP',
]
expect(getNavigatorLanguages()).toEqual(values)
// cache checking
expect(navigatorLanguages).toEqual(values)
})

test('language nothing', () => {
const mockEnv = vi.spyOn(process, 'env', 'get').mockReturnValue({})
expect(getNavigatorLanguages()).toEqual([])
expect(navigatorLanguages).toEqual([])
expect(getNavigatorLanguages()).toEqual([])
expect(mockEnv).toHaveBeenCalledTimes(2)
})
})
}

let navigatorLanguage = ''

/**
* get navigator languages
Expand All @@ -249,3 +307,52 @@ export function getNavigatorLanguage(): string {
return navigatorLanguage ||
(navigatorLanguage = getNavigatorLanguages()[0] || '')
}

/**
* in-source testing for `getNavigatorLanguage`
*/
if (import.meta.vitest) {
const { describe, test, expect, afterEach, vi } = import.meta.vitest

describe('getNavigatorLanguage', () => {
afterEach(() => {
vi.resetAllMocks()
navigatorLanguages = undefined
navigatorLanguage = ''
})

test('basic', () => {
vi.spyOn(process, 'env', 'get').mockReturnValue({
LC_ALL: 'en-GB',
LC_MESSAGES: 'en-US',
LANG: 'ja-JP',
LANGUAGE: 'en',
})

expect(getNavigatorLanguage()).toEqual('en-GB')
// cache checking
expect(navigatorLanguage).toEqual('en-GB')
})

test('duplicate language', () => {
vi.spyOn(process, 'env', 'get').mockReturnValue({
LC_ALL: 'en-US',
LC_MESSAGES: 'en-US',
LANG: 'ja-JP',
LANGUAGE: 'ja-JP',
})

expect(getNavigatorLanguage()).toEqual('en-US')
// cache checking
expect(navigatorLanguage).toEqual('en-US')
})

test('language nothing', () => {
const mockEnv = vi.spyOn(process, 'env', 'get').mockReturnValue({})
expect(getNavigatorLanguage()).toBe('')
expect(navigatorLanguage).toBe('')
expect(getNavigatorLanguage()).toBe('')
expect(mockEnv).toHaveBeenCalledTimes(2)
})
})
}
4 changes: 3 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
"types": [
"vitest/importMeta"
], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
"allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
Expand Down
7 changes: 7 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from 'vitest/config'

export default defineConfig({
test: {
includeSource: ['src/**/*.{js,ts}'],
},
})

0 comments on commit f37bb40

Please sign in to comment.