generated from Seekra/repository-template
Compare commits
19 Commits
918d6768e8
...
27f696247d
| Author | SHA1 | Date | |
|---|---|---|---|
|
27f696247d
|
|||
|
3a07b0482f
|
|||
|
88634e10cd
|
|||
|
98cc6b7556
|
|||
|
0bb0f23347
|
|||
|
02af96a07d
|
|||
|
a6194bb874
|
|||
|
d6700d6965
|
|||
|
54ffaf73e3
|
|||
|
ebe21f7f4d
|
|||
|
37515268d7
|
|||
|
c919263c36
|
|||
|
592eb7222f
|
|||
|
98579b726b
|
|||
|
4e6c94afc8
|
|||
|
f2f7e9e23c
|
|||
|
08949d5bb4
|
|||
|
65153db414
|
|||
|
58e4640965
|
+2
-1
@@ -17,10 +17,11 @@
|
||||
"vue-router": "^5.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"@vitejs/plugin-vue": "^6.0.6",
|
||||
"jsdom": "^29.1.1",
|
||||
"vite": "^8.0.10",
|
||||
"vite-plugin-html": "^3.2.2",
|
||||
"vitest": "^4.1.7"
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -42,15 +42,18 @@ watch(colorScheme, val => updateColorScheme(val))
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.main-content {
|
||||
#app-wrapper {
|
||||
--main-content-padding-x: 30px;
|
||||
--main-content-padding-y: 40px;
|
||||
--main-content-padding: var(--main-content-padding-y) var(--main-content-padding-x);
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 48rem) {
|
||||
.main-content {
|
||||
#app-wrapper {
|
||||
--main-content-padding-x: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import NavbarSearchBarWrapper from './NavbarSearchBarWrapper.vue';
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 18px 40px;
|
||||
padding: 18px var(--main-content-padding-x);
|
||||
height: 42px;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright 2026 Seekra
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { expect, test, describe, vi, beforeEach } from 'vitest';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import LanguageSwitchButton from '../LanguageSwitchButton.vue';
|
||||
import { loadLanguage } from '@/i18n';
|
||||
|
||||
vi.mock('@/i18n', () => ({
|
||||
loadLanguage: vi.fn(() => Promise.resolve()),
|
||||
LANGUAGES_RTL: ['ar', 'he'],
|
||||
SUPPORTED_LANGUAGES: ['en', 'de', 'ar']
|
||||
}));
|
||||
|
||||
vi.mock('vue-i18n', () => ({
|
||||
useI18n: () => ({
|
||||
t: (key) => key,
|
||||
locale: { value: 'de' }
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('@/features/icons/components/Icon.vue', () => ({
|
||||
default: {
|
||||
name: 'Icon',
|
||||
template: '<span>Icon</span>'
|
||||
}
|
||||
}));
|
||||
|
||||
describe('LanguageSwitchButton.vue', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
localStorage.clear();
|
||||
document.documentElement.lang = '';
|
||||
document.documentElement.dir = '';
|
||||
});
|
||||
|
||||
test('renders correctly with initial state closed', () => {
|
||||
const wrapper = mount(LanguageSwitchButton);
|
||||
|
||||
expect(wrapper.find('.language-button').exists()).toBe(true);
|
||||
expect(wrapper.find('.language-dropdown').exists()).toBe(false);
|
||||
expect(wrapper.find('.language-button').attributes('aria-expanded')).toBe('false');
|
||||
});
|
||||
|
||||
test('opens the dropdown when language button is clicked', async () => {
|
||||
const wrapper = mount(LanguageSwitchButton);
|
||||
const button = wrapper.find('.language-button');
|
||||
|
||||
await button.trigger('click');
|
||||
|
||||
expect(wrapper.find('.language-dropdown').exists()).toBe(true);
|
||||
expect(button.attributes('aria-expanded')).toBe('true');
|
||||
});
|
||||
|
||||
const languageTestCases = [
|
||||
{ code: 'en', expectedDir: 'ltr' },
|
||||
{ code: 'de', expectedDir: 'ltr' },
|
||||
{ code: 'ar', expectedDir: 'rtl' }
|
||||
];
|
||||
|
||||
test.for(languageTestCases)('selectLanguage($code) sets localStorage, html attributes and changes layout direction to $expectedDir', async ({ code, expectedDir }) => {
|
||||
const wrapper = mount(LanguageSwitchButton);
|
||||
|
||||
await wrapper.find('.language-button').trigger('click');
|
||||
|
||||
const options = wrapper.findAll('.language-dropdown li');
|
||||
const optionToClick = options.find(opt => opt.text().includes(code));
|
||||
|
||||
await optionToClick.trigger('click');
|
||||
|
||||
expect(loadLanguage).toHaveBeenCalledWith(code);
|
||||
expect(localStorage.getItem('locale')).toBe(code);
|
||||
expect(document.documentElement.lang).toBe(code);
|
||||
expect(document.documentElement.dir).toBe(expectedDir);
|
||||
expect(wrapper.find('.language-dropdown').exists()).toBe(false);
|
||||
});
|
||||
|
||||
test('closes the dropdown when clicking outside the component', async () => {
|
||||
const wrapper = mount(LanguageSwitchButton, {
|
||||
attachTo: document.body
|
||||
});
|
||||
|
||||
await wrapper.find('.language-button').trigger('click');
|
||||
expect(wrapper.find('.language-dropdown').exists()).toBe(true);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
const externalDiv = document.createElement('div');
|
||||
document.body.appendChild(externalDiv);
|
||||
|
||||
const clickEvent = new MouseEvent('click', { bubbles: true });
|
||||
externalDiv.dispatchEvent(clickEvent);
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(wrapper.find('.language-dropdown').exists()).toBe(false);
|
||||
|
||||
wrapper.unmount();
|
||||
externalDiv.remove();
|
||||
});
|
||||
});
|
||||
@@ -67,9 +67,10 @@ const submitSearch = function () {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.slogan{
|
||||
margin: 0;
|
||||
.slogan {
|
||||
margin-top: 1rem;
|
||||
font-size: small;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
|
||||
Reference in New Issue
Block a user