I18n с помощью Svelte и тестов Jest

Мне нужно создать приложение на английском, французском и польском языках, поэтому я хочу установить и настроить эти три языка в моем приложении Svelte.

Я создал свое приложение и установил тесты.

Я буду использовать svelte-i18n

npm i svelte-i18n
Войти в полноэкранный режим Выйти из полноэкранного режима

Пришло время сконфигурировать этот пакет. Файл main.js перед конфигурацией выглядит следующим образом:

import './app.css'
import App from './App.svelte'

const app = new App({
  target: document.getElementById('app')
})

export default app
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь я добавляю импорт svelte-i18n:

import './app.css'
import App from './App.svelte'
import { addMessages, init } from 'svelte-i18n'

addMessages('en', {
  hello: 'Hello word!' 
}) // this is my key that I will use after in my App page.

init({
  initialLocale: 'en',
  fallbackLocale: 'en'
}); // here I inicialise and  configure a local language

const app = new App({
  target: document.getElementById('app')
})

export default app
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь я импортирую i18n в App.svelte следующим образом:

<script>
  import { _ } from 'svelte-i18n'
</script>

<main>
  <h1>{$_('hello')}</h1>
</main>
Войти в полноэкранный режим Выйти из полноэкранного режима

В браузере это работает очень хорошо, но тесты не удались. Я разберусь с этим позже. На данный момент я добавляю еще один язык в main.js:

import './app.css'
import App from './App.svelte'
import { addMessages, init } from 'svelte-i18n'

addMessages('en', {
  hello: 'Hello word!' 
})

addMessages('fr', {
  hello: 'Salut tout le monde!' 
})

addMessages('pl', {
  hello: 'Witajcie w naszej bajce!' 
})

init({
  initialLocale: 'fr',
  fallbackLocale: 'en'
});

const app = new App({
  target: document.getElementById('app')
})

export default app
Вход в полноэкранный режим Выход из полноэкранного режима

Таким образом, когда вы меняете локальный язык, ваш текст в браузере также изменится.
Как я уже говорил, тесты не работают, поэтому я их исправлю.
Прежде всего, я создаю папку locale в папке src

mkdir locale
cd locale
touch i18n.js
Вхожу в полноэкранный режим Выйти из полноэкранного режима

Из main.js я вырезал эту часть кода:

import { addMessages, init } from 'svelte-i18n'

addMessages('en', {
  hello: 'Hello word!' 
})

addMessages('fr', {
  hello: 'Salut tout le monde!' 
})

addMessages('pl', {
  hello: 'Witajcie w naszej bajce!' 
})

init({
  initialLocale: 'fr',
  fallbackLocale: 'en'
});
Вход в полноэкранный режим Выход из полноэкранного режима

вставляю его в i18n.js и импортирую этот файл в main.js:

import './locale/i18n'
Войти в полноэкранный режим Выйти из полноэкранного режима

Перевод работает в браузере.
Я импортирую этот файл также в файл App.spec.js:

import '../src/locale/i18n'
Войти в полноэкранный режим Выйти из полноэкранного режима

и тесты становятся зелеными, когда локальным языком является английский.

Чтобы иметь все языки в одном файле, я создаю JSON файл для каждого языка:


, а в i18n.js импортирую все эти файлы:

import { addMessages, init } from 'svelte-i18n';
import en from './en.json';
import fr from './fr.json';
import pl from './pl.json';

addMessages('en', en)

addMessages('fr', fr)

addMessages('pl', pl)

init({
  initialLocale: 'en',
  fallbackLocale: 'en'
});
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь я проверяю, хорошо ли отображается перевод

App.spec.js:

/**
 * @jest-environment jsdom
 */

 import App from "../src/App.svelte";
 import { render, screen } from "@testing-library/svelte";
 import '../src/locale/i18n'
 import en from '../src/locale/en.json' //here I import a json files 
 import fr from '../src/locale/fr.json'
 import pl from '../src/locale/pl.json'

 // I modify a little bit a teste by adding description tag 
 describe("App Page", () =>{
   describe("Layout", () =>{
    it("has Hello header", () =>{
      render(App);
      const header = screen.getAllByText("Hello word!");
      expect(header).toBeTruthy()
    });
   });
   describe("i18n", () =>{
     it("displays text in English", () =>{
       render(App);
       expect(screen.queryByRole('heading', {level: 1, name: en.hello})).toBeInDocument; /here I use from json file key and its value
     });
     it("displays text in French", () =>{
      render(App);
      expect(screen.queryByRole('heading', {level: 1, name: fr.hello})).toBeInDocument;
    });
    it("displays text in Polish", () =>{
      render(App);
      expect(screen.queryByRole('heading', {level: 1, name: pl.hello})).toBeInDocument;
    });
   })
 })
Войти в полноэкранный режим Выход из полноэкранного режима

На данный момент все работает по умолчанию, но я хочу сменить язык, поэтому мне нужно создать маленькую кнопку для переключения между языками.

В тестах я добавляю эти 2 теста:

it("displays text in French after clic a FR btn", async () =>{
      render(App);
      const frBtn = screen.getByText('FR');
      await userEvent.click(frBtn);
      expect(screen.queryByRole('heading', {level: 1, name: fr.hello})).toBeInDocument;
    });
    it("displays text in Polish after clic a PL btn", async () =>{
      render(App);
      const plBtn = screen.getByText('PL');
      await userEvent.click(plBtn);
      expect(screen.queryByRole('heading', {level: 1, name: pl.hello})).toBeInDocument;
    });
Войти в полноэкранный режим Выход из полноэкранного режима

Эти тесты корректны, но это не работает, потому что мне нужно импортировать пользовательское событие из библиотеки, которую я установил ранее.

import userEvent from '@testing-library/user-event'
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь тесты не работают, потому что в App.svelte у меня нет ни одного элемента, на который можно было бы нажать. Поэтому я создаю 3 языковых элемента и добавляю к ним on:click. Мне также нужно импортировать локаль из i18n. Теперь App.svelte выглядит следующим образом:

<script>
  import { _, locale } from 'svelte-i18n'
</script>

<main>
  <h1>{$_('hello')}</h1>
  <span on:click = {() => locale.set("en")}>EN</span>
  <span on:click = {() => locale.set("fr")}>FR</span>
  <span on:click = {() => locale.set("pl")} >PL</span>
</main>
Войти в полноэкранный режим Выход из полноэкранного режима

Теперь все работает, но мне нужно знать, работает ли кнопка EN также хорошо, как и другие, поэтому я создал еще один тест:

it("displays text in English after click from PL btn", async() =>{
      render(App);
      const plBtn = screen.getByText('PL');
      await userEvent.click(plBtn);

      const enBtn = screen.getByText('EN');
      await userEvent.click(enBtn);
      expect(screen.queryByRole('heading', {level: 1, name: en.hello})).toBeInDocument;
    });
Войти в полноэкранный режим Выход из полноэкранного режима

Так что весь App.spec.js выглядит следующим образом:

/**
 * @jest-environment jsdom
 */

 import App from "../src/App.svelte";
 import { render, screen } from "@testing-library/svelte";
 import userEvent from '@testing-library/user-event'
 import '../src/locale/i18n'
 import en from '../src/locale/en.json'
 import fr from '../src/locale/fr.json'
 import pl from '../src/locale/pl.json'


 describe("App Page", () =>{
   describe("Layout", () =>{
    it("has Hello header", () =>{
      render(App);
      const header = screen.getAllByText("Hello word!");
      expect(header).toBeTruthy()
    });
   });
   describe("i18n", () =>{
     it("displays text in English by default", () =>{
       render(App);
       expect(screen.queryByRole('heading', {level: 1, name: en.hello})).toBeInDocument;
     });
     it("displays text in French after clic a FR btn", async () =>{
      render(App);
      const frBtn = screen.getByText('FR');
      await userEvent.click(frBtn);
      expect(screen.queryByRole('heading', {level: 1, name: fr.hello})).toBeInDocument;
    });
    it("displays text in Polish after clic a PL btn", async () =>{
      render(App);
      const plBtn = screen.getByText('PL');
      await userEvent.click(plBtn);
      expect(screen.queryByRole('heading', {level: 1, name: pl.hello})).toBeInDocument;
    });
    it("displays text in English after click from PL btn", async() =>{
      render(App);
      const plBtn = screen.getByText('PL');
      await userEvent.click(plBtn);

      const enBtn = screen.getByText('EN');
      await userEvent.click(enBtn);
      expect(screen.queryByRole('heading', {level: 1, name: en.hello})).toBeInDocument;
    });
   })
 })
Войти в полноэкранный режим Выйти из полноэкранного режима

Когда я запускаю тесты, все зеленые.

Оцените статью
devanswers.ru
Добавить комментарий