From 0d7e714495fddabd5abeecd16851eb9351254f03 Mon Sep 17 00:00:00 2001 From: alxndrsn Date: Fri, 3 May 2024 09:30:45 +0000 Subject: [PATCH] Document current $t() and $te() handling for __proto__ --- test/unit/basic.test.js | 250 +++++++++++++++++++++++++++++++++++++ test/unit/fixture/index.js | 24 +++- 2 files changed, 271 insertions(+), 3 deletions(-) diff --git a/test/unit/basic.test.js b/test/unit/basic.test.js index 9f8f67082..040b63fd2 100644 --- a/test/unit/basic.test.js +++ b/test/unit/basic.test.js @@ -526,6 +526,180 @@ describe('basic', () => { ) }) }) + + describe('__proto__ handling', () => { + describe('top-level prop', () => { + describe('existing key', () => { + let vm; + beforeEach(() => { + const i18n = new VueI18n({ + locale: 'en', + fallbackLocale: 'en', + messages: { + en: { + __proto__: 'i exist' + }, + ja: { + __proto__: 'i exist (ja)' + }, + }, + modifiers: { + custom: str => str.replace(/[aeiou]/g, 'x') + } + }) + vm = new Vue({ i18n }) + }) + + it('should return string', () => { + // FIXME: should be a string with value 'i exist'? + assert(typeof vm.$t('__proto__') === 'object') + }) + + it('should return string with locale', () => { + // FIXME: should be a string with value 'i exist (ja)'? + assert(typeof vm.$t('__proto__', 'ja') === 'object') + }) + }) + + describe('not existing key', () => { + it('should return key', () => { + const vm = new Vue({ i18n }) + // FIXME: should be key? + assert(typeof vm.$t('__proto__') === 'object') + }) + + it('should return key with locale', () => { + const vm = new Vue({ i18n }) + // FIXME: should be key? + assert(typeof vm.$t('__proto__', 'ja') === 'object') + }) + }) + }) + + describe('top-level prop with trailing prop', () => { + describe('with top-level prop defined', () => { + let vm; + beforeEach(() => { + const i18n = new VueI18n({ + locale: 'en', + fallbackLocale: 'en', + messages: { + en: { + __proto__: { + existing: 'i exist' + } + }, + ja: { + __proto__: { + existing: 'i exist (ja)' + } + }, + }, + modifiers: { + custom: str => str.replace(/[aeiou]/g, 'x') + } + }) + vm = new Vue({ i18n }) + }) + + describe('existing key', () => { + it('should return string', () => { + // FIXME: should be a string with value 'i exist'? + assert(vm.$t('__proto__.existing') === 'i exist') + }) + + it('should return string with locale', () => { + // FIXME: should be a string with value 'i exist (ja)'? + assert(vm.$t('__proto__.existing', 'ja') === 'i exist (ja)') + }) + }) + + describe('not existing key', () => { + it('should return key', () => { + const vm = new Vue({ i18n }) + assert(vm.$t('__proto__.missing') === '__proto__.missing') + }) + + it('should return key with locale', () => { + const vm = new Vue({ i18n }) + assert(vm.$t('__proto__.missing', 'ja') === '__proto__.missing') + }) + }) + }) + + describe('without top-level prop defined', () => { + it('should return key', () => { + const vm = new Vue({ i18n }) + assert(vm.$t('__proto__.missing') === '__proto__.missing') + }) + + it('should return key with locale', () => { + const vm = new Vue({ i18n }) + assert(vm.$t('__proto__.missing', 'ja') === '__proto__.missing') + }) + }) + }) + + describe('deep prop', () => { + describe('existing key', () => { + it('should return true', () => { + const vm = new Vue({ i18n }) + // FIXME: should be a string with value 'i exist'? + assert(typeof vm.$t('issues.builtins.existing.__proto__') === 'object') + }) + + it('should return true with locale', () => { + const vm = new Vue({ i18n }) + // FIXME: should be a string with value 'i exist (ja)'? + assert(typeof vm.$t('issues.builtins.existing.__proto__', 'ja') === 'object') + }) + }) + + describe('not existing key', () => { + it('should return false', () => { + const vm = new Vue({ i18n }) + // FIXME: should be key? + assert(typeof vm.$t('issues.builtins.missing.__proto__') === 'object') + }) + + it('should return false with locale', () => { + const vm = new Vue({ i18n }) + // FIXME: should be key? + assert(typeof vm.$t('issues.builtins.missing.__proto__', 'ja') === 'object') + }) + }) + }) + + describe('deep prop with proto in middle', () => { + describe('existing key', () => { + it('should return true', () => { + const vm = new Vue({ i18n }) + // FIXME: should be a string with value 'i exist'? + assert(vm.$t('issues.builtins.__proto__.existing') === 'i exist') + }) + + it('should return true with locale', () => { + const vm = new Vue({ i18n }) + // FIXME: should be a string with value 'i exist (ja)'? + assert(vm.$t('issues.builtins.__proto__.existing', 'ja') === 'i exist (ja)') + }) + }) + + describe('not existing key', () => { + it('should return false', () => { + const vm = new Vue({ i18n }) + // FIXME: should be key? + assert(vm.$t('issues.builtins.__proto__.missing') === 'issues.builtins.__proto__.missing') + }) + + it('should return false with locale', () => { + const vm = new Vue({ i18n }) + // FIXME: should be key? + assert(vm.$t('issues.builtins.__proto__.missing', 'ja') === 'issues.builtins.__proto__.missing') + }) + }) + }) + }) }) describe('$tc', () => { @@ -660,6 +834,82 @@ describe('basic', () => { assert(vm.$te('message.hello', 'xx') === false) }) }) + + describe('__proto__ handling', () => { + describe('top-level prop', () => { + describe('existing key', () => { + let vm; + beforeEach(() => { + const i18n = new VueI18n({ + locale: 'en', + fallbackLocale: 'en', + messages: { + en: { + __proto__: 'i exist' + }, + ja: { + __proto__: 'i exist (ja)' + }, + }, + modifiers: { + custom: str => str.replace(/[aeiou]/g, 'x') + } + }) + vm = new Vue({ i18n }) + }) + + it('should return true', () => { + assert(vm.$te('__proto__') === true) + }) + + it('should return true with locale', () => { + assert(vm.$te('__proto__', 'ja') === true) + }) + }) + + describe('not existing key', () => { + it('should return false', () => { + const vm = new Vue({ i18n }) + assert(vm.$te('__proto__') === true) + }) + + it('should return false with locale', () => { + const vm = new Vue({ i18n }) + assert(vm.$te('__proto__', 'ja') === true) + }) + }) + }) + + describe('deep prop', () => { + describe('existing key', () => { + it('should return true', () => { + const vm = new Vue({ i18n }) + // FIXME: should be false? + assert(vm.$te('issues.builtins.existing.__proto__') === true) + }) + + it('should return true with locale', () => { + const vm = new Vue({ i18n }) + // FIXME: should be false? + assert(vm.$te('issues.builtins.existing.__proto__', 'ja') === true) + }) + }) + + describe('not existing key', () => { + it('should return false', () => { + const vm = new Vue({ i18n }) + // FIXME: should be false? + assert(vm.$te('issues.builtins.missing.__proto__') === true) + }) + + it('should return false with locale', () => { + const vm = new Vue({ i18n }) + // FIXME: should be false? + assert(vm.$te('issues.builtins.missing.__proto__', 'ja') === true) + }) + }) + }) + }) }) describe('i18n#locale', () => { diff --git a/test/unit/fixture/index.js b/test/unit/fixture/index.js index a81a96960..cd59eebb8 100644 --- a/test/unit/fixture/index.js +++ b/test/unit/fixture/index.js @@ -1,4 +1,4 @@ -export default { +module.exports = { en: { message: { hello: 'the world', @@ -70,7 +70,16 @@ export default { ] ], issues: { - arrayBugs: ['bug1', 'bug2'] + arrayBugs: ['bug1', 'bug2'], + builtins: { + __proto__: { + existing: 'i exist' + }, + existing: { + __proto__: 'i exist', + }, + missing: {} + } }, 'foo.bar.buz': 'hello flat key!' }, @@ -111,7 +120,16 @@ export default { ] ], issues: { - arrayBugs: ['バグ1', 'バグ2'] + arrayBugs: ['バグ1', 'バグ2'], + builtins: { + __proto__: { + existing: 'i exist (ja)' + }, + existing: { + __proto__: 'i exist (ja)', + }, + missing: {} + } }, 'foo.bar.buz': 'こんにちは、フラットなキーさん!' }