Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions __tests__/components.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { describe, test, expect } from 'vitest';
import { describe, test, expect, afterEach } from 'vitest';
import { mount } from '@vue/test-utils';
import { createRouter, createMemoryHistory } from 'vue-router';
import AppHeader from '../src/components/AppHeader.vue';
import { i18n, setLocale } from '../src/plugins/i18n';

function createTestRouter() {
return createRouter({
Expand All @@ -13,18 +14,46 @@ function createTestRouter() {
});
}

const stubs = {
'v-btn': { template: '<button type="button" class="lang-toggle"><slot /></button>' }
};

afterEach(() => {
setLocale('ja');
});

describe('AppHeader', () => {
test('renders navigation links', async () => {
const router = createTestRouter();
router.push('/');
await router.isReady();

const wrapper = mount(AppHeader, {
global: { plugins: [router] }
global: { plugins: [router, i18n], stubs }
});

expect(wrapper.findAll('li').length).toBeGreaterThan(0);
expect(wrapper.text()).toContain('ホーム');
expect(wrapper.text()).toContain('プロフィール');
});

test('toggles language between ja and en', async () => {
const router = createTestRouter();
router.push('/');
await router.isReady();

const wrapper = mount(AppHeader, {
global: { plugins: [router, i18n], stubs }
});

expect(wrapper.text()).toContain('ホーム');
expect(wrapper.text()).not.toContain('Home');

await wrapper.find('.lang-toggle').trigger('click');

expect(wrapper.text()).toContain('Home');
expect(wrapper.text()).toContain('Profile');
expect(wrapper.text()).toContain('日本語');
expect(wrapper.text()).not.toContain('ホーム');
});
});
57 changes: 29 additions & 28 deletions __tests__/pages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ProjectsPage from '../src/pages/ProjectsPage.vue';
import UserCareer from '../src/pages/UserCareer.vue';
import UserContact from '../src/pages/UserContact.vue';
import UserProfile from '../src/pages/UserProfile.vue';
import { i18n } from '../src/plugins/i18n';

function createTestRouter() {
return createRouter({
Expand Down Expand Up @@ -48,13 +49,13 @@ describe('HomePage', () => {
await router.isReady();

const wrapper = mount(HomePage, {
global: { plugins: [router] }
global: { plugins: [router, i18n] }
});

expect(wrapper.find('.hero').exists()).toBe(true);
expect(wrapper.find('.hero-badge').text()).toBe('Portfolio');
expect(wrapper.find('.hero-badge').text()).toBe('ポートフォリオ');
expect(wrapper.find('.accent').text()).toBe('こめっと');
expect(wrapper.find('.hero-sub').text()).toBe('Software Engineer');
expect(wrapper.find('.hero-sub').text()).toBe('ソフトウェアエンジニア');
});

test('renders CTA buttons', async () => {
Expand All @@ -63,7 +64,7 @@ describe('HomePage', () => {
await router.isReady();

const wrapper = mount(HomePage, {
global: { plugins: [router] }
global: { plugins: [router, i18n] }
});

const buttons = wrapper.findAll('button');
Expand All @@ -78,7 +79,7 @@ describe('HomePage', () => {
await router.isReady();

const wrapper = mount(HomePage, {
global: { plugins: [router] }
global: { plugins: [router, i18n] }
});

const pushSpy = vi.spyOn(router, 'push');
Expand All @@ -92,7 +93,7 @@ describe('HomePage', () => {
await router.isReady();

const wrapper = mount(HomePage, {
global: { plugins: [router] }
global: { plugins: [router, i18n] }
});

const pushSpy = vi.spyOn(router, 'push');
Expand All @@ -108,7 +109,7 @@ describe('NotFoundPage', () => {
await router.isReady();

const wrapper = mount(NotFoundPage, {
global: { plugins: [router] }
global: { plugins: [router, i18n] }
});

expect(wrapper.find('#not-found').exists()).toBe(true);
Expand All @@ -122,7 +123,7 @@ describe('NotFoundPage', () => {
await router.isReady();

const wrapper = mount(NotFoundPage, {
global: { plugins: [router] }
global: { plugins: [router, i18n] }
});

const button = wrapper.find('.btn-primary');
Expand All @@ -138,11 +139,11 @@ describe('UserCareer', () => {
await router.isReady();

const wrapper = mount(UserCareer, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

expect(wrapper.find('#contact').exists()).toBe(true);
expect(wrapper.text()).toContain('Career');
expect(wrapper.text()).toContain('経歴');
expect(wrapper.text()).toContain('職務経歴について');
});

Expand All @@ -152,7 +153,7 @@ describe('UserCareer', () => {
await router.isReady();

const wrapper = mount(UserCareer, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

const items = wrapper.findAll('.v-timeline-item');
Expand All @@ -170,7 +171,7 @@ describe('UserCareer', () => {
await router.isReady();

const wrapper = mount(UserCareer, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

expect(wrapper.text()).toContain('情報工学科');
Expand All @@ -185,11 +186,11 @@ describe('UserContact', () => {
await router.isReady();

const wrapper = mount(UserContact, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

expect(wrapper.find('#contact').exists()).toBe(true);
expect(wrapper.text()).toContain('Contact');
expect(wrapper.text()).toContain('お問い合わせ');
});

test('renders email information', async () => {
Expand All @@ -198,7 +199,7 @@ describe('UserContact', () => {
await router.isReady();

const wrapper = mount(UserContact, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

expect(wrapper.text()).toContain('Email');
Expand All @@ -214,13 +215,13 @@ describe('UserProfile', () => {
await router.isReady();

const wrapper = mount(UserProfile, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

expect(wrapper.find('#profile').exists()).toBe(true);
expect(wrapper.text()).toContain('Profile');
expect(wrapper.text()).toContain('Comet / こめっと');
expect(wrapper.text()).toContain('Software Engineer');
expect(wrapper.text()).toContain('プロフィール');
expect(wrapper.text()).toContain('こめっと');
expect(wrapper.text()).toContain('ソフトウェアエンジニア');
});

test('renders external links', async () => {
Expand All @@ -229,7 +230,7 @@ describe('UserProfile', () => {
await router.isReady();

const wrapper = mount(UserProfile, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

const links = wrapper.findAll('a');
Expand All @@ -245,7 +246,7 @@ describe('UserProfile', () => {
await router.isReady();

const wrapper = mount(UserProfile, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

expect(wrapper.text()).toContain('技術選定');
Expand All @@ -261,7 +262,7 @@ describe('UserProfile', () => {
await router.isReady();

const wrapper = mount(UserProfile, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

expect(wrapper.text()).toContain('基本情報技術者試験');
Expand All @@ -278,7 +279,7 @@ describe('UserProfile', () => {
await router.isReady();

const wrapper = mount(UserProfile, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

const links = wrapper.findAll('a');
Expand All @@ -296,11 +297,11 @@ describe('ProjectsPage', () => {
await router.isReady();

const wrapper = mount(ProjectsPage, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

expect(wrapper.find('#projects').exists()).toBe(true);
expect(wrapper.text()).toContain('Projects');
expect(wrapper.text()).toContain('プロジェクト');
});

test('renders backoff-util project card', async () => {
Expand All @@ -309,7 +310,7 @@ describe('ProjectsPage', () => {
await router.isReady();

const wrapper = mount(ProjectsPage, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

expect(wrapper.text()).toContain('backoff-util');
Expand All @@ -322,7 +323,7 @@ describe('ProjectsPage', () => {
await router.isReady();

const wrapper = mount(ProjectsPage, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

const hrefs = wrapper.findAll('a').map((l) => l.attributes('href'));
Expand All @@ -336,7 +337,7 @@ describe('ProjectsPage', () => {
await router.isReady();

const wrapper = mount(ProjectsPage, {
global: { plugins: [router], stubs: vuetifyStubs }
global: { plugins: [router, i18n], stubs: vuetifyStubs }
});

const links = wrapper.findAll('a');
Expand Down
10 changes: 9 additions & 1 deletion e2e/smoke.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { test, expect } from '@playwright/test';

// i18n 導入後、デフォルト言語は日本語。テストは英語 UI を前提としているため、
// ページ読み込み前に localStorage へ locale を設定して英語モードで開始する。
test.beforeEach(async ({ page }) => {
await page.addInitScript(() => {
localStorage.setItem('locale', 'en');
});
});

for (const { path, name } of [
{ path: '/', name: 'Home' },
{ path: '/profile', name: 'Profile' },
Expand Down Expand Up @@ -31,5 +39,5 @@ test('navigates via header links', async ({ page }) => {

test('renders 404 for unknown route', async ({ page }) => {
await page.goto('/#/unknown-page');
await expect(page.getByText('ページが見つかりません')).toBeVisible();
await expect(page.getByText('Page Not Found')).toBeVisible();
});
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aecomet.github.io",
"version": "8.13.0",
"version": "9.0.0",
"description": "My portfolio.",
"scripts": {
"dev": "vite",
Expand Down Expand Up @@ -44,6 +44,7 @@
"dependencies": {
"@mdi/js": "^7.4.47",
"vue": "^3.5.41",
"vue-i18n": "^11.4.8",
"vue-router": "^5.2.0",
"vuetify": "^4.1.8"
}
Expand Down
Loading
Loading