Skip to content

Commit

Permalink
Allow the language selector to detect autonym by exonym (#883)
Browse files Browse the repository at this point in the history
* add API call to get language code

* get an array of lang codes and filter from that

* simplify response handling and improve api constant name

* debounce api requests

* don't make api calls with empty inputs

* Mock svg import files in jest tests

* add test skeleton

* add test

---------

Co-authored-by: gtzatchkova <guergana.tzatchkova@wikimedia.de>
  • Loading branch information
chukarave and guergana committed Mar 5, 2024
1 parent 843d74f commit dc16ab6
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 8 deletions.
3 changes: 2 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ module.exports = {
"transform": {
".*\\.(vue)$": "<rootDir>/node_modules/@vue/vue3-jest",
"^.+\\.js$": "<rootDir>/node_modules/babel-jest",
"^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest"
"^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest",
'.+\\.svg$': '<rootDir>/tests/Vue/helpers/jest-svg-component-transformer.js'
},
// (Optional) This file helps you later for global settings
"setupFilesAfterEnv": [
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"@inertiajs/inertia-vue3": "^0.6.0",
"date-fns": "^3.3.1",
"lodash": "^4.17.21",
"lodash.debounce": "^4.0.8",
"pinia": "^2.1.7",
"ress": "^5.0.2",
"vue": "^3.3.8",
Expand Down
30 changes: 25 additions & 5 deletions resources/js/Components/LanguageSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,16 @@ import LanguageSelectorOptionsMenu from "./LanguageSelectorOptionsMenu.vue";
import LanguageSelectorInput from "./LanguageSelectorInput.vue";
import Language from '../types/Language';
import closeUrlSvg from '../../img/close.svg';
import axios from 'axios';
import {ref, computed} from "vue";
import type {Ref} from 'vue';
import languageData from "@wikimedia/language-data";
import debounce from "lodash.debounce";
const searchInput: Ref<string> = ref('');
const highlightedIndex: Ref<number> = ref(-1);
const closeUrl = ref(closeUrlSvg);
const apiLanguageCodes = ref(['']);
const input = ref<InstanceType<typeof LanguageSelectorInput> | null>(null);
Expand All @@ -63,17 +65,35 @@ const languages = computed<Language[]>(() => {
});
const shownLanguages = computed<Language[]>(() => {
return languages.value.filter((language) =>
language.code.startsWith(searchInput.value.toLowerCase()) ||
language.autonym.toLowerCase().includes(searchInput.value.toLowerCase()),
);
return languages.value.filter((language) =>
language.code.startsWith(searchInput.value.toLowerCase()) ||
language.autonym.toLowerCase().includes(searchInput.value.toLowerCase()) ||
apiLanguageCodes.value.includes(language.code)
)
});
function onInput(searchedLanguage: string): void {
searchInput.value = searchedLanguage;
if (searchInput.value) {
debouncedApiLanguageSearch(searchInput.value);
}
highlightedIndex.value = 0;
}
const debouncedApiLanguageSearch = debounce(async (debouncedInputValue: string) => {
await axios.get(
'https://www.wikidata.org/w/api.php?action=languagesearch&format=json&formatversion=2',
{
params: {
search: debouncedInputValue,
origin: '*' // avoid CORS console errors
}
}).then((response) => {
apiLanguageCodes.value = Object.keys(response.data.languagesearch);
});
}, 200);
function onSelect(languageCode: string): void {
emit('select', languageCode);
}
Expand Down
44 changes: 44 additions & 0 deletions tests/Vue/Components/LanguageSelector.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { mount } from '@vue/test-utils';
import LanguageSelector from '@/Components/LanguageSelector.vue';
import { createI18n } from 'vue-banana-i18n';

const i18n = createI18n({
messages: {},
locale: 'en',
wikilinks: true
});

describe('LanguageSelector.vue', () => {
it('suggests the relevant language upon input', async () => {
const wrapper = mount(LanguageSelector, {
global: {
plugins: [i18n],
}});

const input = wrapper.find('input');

expect(input.exists()).toBe(true);

await input.setValue('deu');
const listItems = await wrapper.findAll('.languageSelector__options-menu__languages-list__item');

expect(listItems.at(0).text()).toContain('Deutsch');
});

it('suggests the relevant language upon RTL input', async () => {
const wrapper = mount(LanguageSelector, {
global: {
plugins: [i18n],
}});

const input = wrapper.find('input');

expect(input.exists()).toBe(true);

await input.setValue('עב');
const listItems = await wrapper.findAll('.languageSelector__options-menu__languages-list__item');

expect(listItems.at(0).text()).toContain('עברית');
});

});
12 changes: 12 additions & 0 deletions tests/Vue/helpers/jest-svg-component-transformer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = {
process(sourceText, sourcePath) {
const mockComponent = {
name: sourcePath,
template: sourceText
}

return {
code: `module.exports = ${JSON.stringify(mockComponent)};`
}
}
}

0 comments on commit dc16ab6

Please sign in to comment.