在Cypress Vue组件测试中获取URL参数

问题描述 投票:0回答:1

为了测试 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
    })
  })
})
vuejs3 vue-component cypress
1个回答
0
投票

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
)影响的行为。


阅读“
Cypress 环境变量

”,您还可以尝试将 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 }); });

© www.soinside.com 2019 - 2024. All rights reserved.