为了测试 i18n 语言选择 Vue 组件,我想检查决定设置哪种语言的逻辑是否有效。要编写 Cypress 测试来查看是否选择了存储在 localeStorage 中的语言而不是通过 URL 提供的
lang
参数,我需要获取 URL 参数,如何检查?
代码示例:
LocaleSwitcher.js
...
let appLanguage
...
if (typeof localStorage.currentLanguage !== 'undefined' && getAvailableLocales().includes(localStorage.currentLanguage)) {
//if it has a local language stored use this one
appLanguage = localStorage.currentLanguage
} else {
//get value of url param 'lang'
const urlLang = (new URL(location.href).searchParams.get('lang') || '').toLowerCase()
//get browser lang or return default lang
const userAgentLang = ((navigator.language || navigator.languages[0]).split('-')[0] || import.meta.env.VITE_DEFAULT_LANGUAGE).toLowerCase()
//if there is a ?lang= set in url and it is 2 char long
if (urlLang !== null && urlLang.length === 2) {
if (getAvailableLocales().includes(urlLang)) {
appLanguage = urlLang
} else if (getAvailableLocales().includes(userAgentLang)) {
appLanguage = userAgentLang
}
//if no language is set or available use the standaard
} else if (getAvailableLocales().includes(userAgentLang)) {
appLanguage = userAgentLang
} else {
//if no language is set or available use the standaard
appLanguage = import.meta.env.VITE_DEFAULT_LANGUAGE
}
}
//set the language and store it
proxy.$i18n.locale = appLanguage
localStorage.currentLanguage = appLanguage
}
...
<template>
<div data-testid="localeSwitcher">
<span v-if="getAvailableLocales().length > 1">
<span v-for="(locale, i) in getAvailableLocales()" :key="`locale-${locale}`">
<span v-if="i != 0" :class="'has-text-' + businessInfoStore.titleTextColor"> | </span>
<!-- :data-current-locale is for Cypress testing purpuses -->
<a @click="setLocale(locale)" :data-testid="locale.toUpperCase()" :data-current-locale="$i18n.locale === locale ? 'true' : 'false'" :class="[{ 'has-text-weight-bold' : ($i18n.locale === locale)}, 'has-text-' + businessInfoStore.linkTextColor]">
{{ locale.toUpperCase() }}
</a>
</span>
</span>
</div>
</template>
__test__/LocaleSwitcher.js
import LocaleSwitcher from '../LocaleSwitcher.vue'
import { createI18n } from 'vue-i18n'
import { mount } from '@cypress/vue'
import en from '../../locales/en.json'
import de from '../../locales/de.json'
import nl from '../../locales/nl.json'
describe('Test the LocaleSwitcher Languages selected',() => {
beforeEach(() => {
const availableMessages = { en, de, nl }
//load available languages
const i18n = createI18n({
legacy: false,
fallbackLocale: nl,
locale: nl,
globalInjection: true,
messages: availableMessages
})
//mount component with the new i18n object
cy.mount(LocaleSwitcher, { global: { plugins : [ i18n ]}})
})
it('Click first lang and check if ?LANG= is set correct', () => {
cy.get('[data-testid="DE"]').click()
cy.get('[data-current-locale="true"]').should('have.length', 1)
cy.get('[data-current-locale="true"]').should('contain', 'DE')
cy.location().should((loc) => {
expect(loc.search).to.contain('lang=de') <---- this is the url of the window not the component
})
})
})
Cypress 测试通常在 test runner 环境中运行,而不是直接在可以作为组件初始化过程的一部分操作 URL 查询字符串的上下文中运行。
由于您正在 Vue 组件测试和 Cypress 的生态系统中工作,因此由于测试运行程序的“隔离”环境,直接操作
window.location
或以影响 Vue 组件初始化行为的方式模拟它可能并不简单或有效(请参阅这个问题以获取说明)。
您可以尝试调整您的组件,使其在这些条件下更具可测试性:向组件引入一个 prop,允许您直接传递初始 URL 或语言参数。这一更改使组件对全局 location.href
的依赖更加明确,并允许您在测试期间控制它。
修改您的LocaleSwitcher.js
以接受初始 URL 的 prop 或直接接受
lang
参数。如果提供了道具,请使用它;否则,默认为 location.href
。props: {
initialUrl: String
},
...
const url = this.initialUrl ? new URL(this.initialUrl) : new URL(location.href);
const urlLang = url.searchParams.get('lang') || '').toLowerCase();
...
在测试中挂载组件时传递模拟 URL 或语言参数:
// Mount component with the new i18n object and initialUrl prop
cy.mount(LocaleSwitcher, {
propsData: {
initialUrl: 'http://example.com/?lang=de' // Simulate URL with query string
},
global: {
plugins: [i18n]
}
})
这应该允许您通过在测试中传递各种
initialUrl
prop 值来模拟不同的 URL 条件,从而促进基于 URL 参数的组件行为测试,而无需依赖于实际的浏览器环境或 Cypress 的
cy.location()
。但是......它需要修改组件的实现以用于测试目的,这可能并不总是可取的。
尽管如此,它确实提供了一种受控方法来测试受全局对象(如组件测试设置的限制内的location.href
)影响的行为。
”,您还可以尝试将 baseUrl
与动态路径一起使用。如果您的组件的行为受到 URL 中的路径或查询参数的影响,您可以使用
Cypress 的
baseUrl
配置为您的测试设置基本 URL,然后导航到测试中的特定路径或 URL:
// cypress.config.js
module.exports = defineConfig({
// other configurations
env: {
// Define environment-specific variables here
},
baseUrl: 'http://localhost:3000', // Adjust this to your app's base URL
});
// In your test
describe('LocaleSwitcher Component Tests', () => {
it('should react to lang query parameter', () => {
// Assuming your component reads from the URL when mounted
cy.visit('/your-component-path?lang=de');
// Your test assertions
});
});