Files
Portfolio/tests/unit/components.test.ts

101 lines
4.4 KiB
TypeScript

import { mount } from '@vue/test-utils';
import { describe, expect, it } from 'vitest';
import ContactDestination from '@/components/ContactDestination.vue';
import InfrastructureDiagram from '@/components/InfrastructureDiagram.vue';
import ProjectCaseStudy from '@/components/ProjectCaseStudy.vue';
import ToolkitGrid from '@/components/ToolkitGrid.vue';
import type { ContactContent, InfrastructureCaseStudy, PublicProject, ToolkitGroup } from '@/content/types';
const infrastructure: InfrastructureCaseStudy = {
id: 'safe-infrastructure',
title: 'Secure self-hosted platform and lifecycle',
summary: 'A compact infrastructure case study.',
bands: [
{ id: 'ingress-tls', title: 'Ingress and TLS', summary: 'Managed encrypted ingress.' },
{ id: 'identity-access', title: 'Identity and access', summary: 'Protected service access.' },
],
};
const privateProject: PublicProject = {
id: 'private-work',
title: 'Private self-hosted medication tracker',
visibility: 'private',
maturity: 'active',
summary: 'A private application.',
problem: 'A recurring workflow needs reliable tracking.',
contribution: 'Designed and maintained the application.',
technicalDecisions: ['Used a synchronised client and server design.'],
outcome: 'The work remains private.',
assetIds: [],
};
const publicProject: PublicProject = {
...privateProject,
id: 'public-work',
title: 'Footy Tracker',
visibility: 'public',
url: 'https://github.com/example/footy-tracker',
};
describe('semantic section components', () => {
it('gives the infrastructure graphic an accessible name, description, caption, and visible text equivalent', () => {
const wrapper = mount(InfrastructureDiagram, { props: { infrastructure } });
const svg = wrapper.get('svg');
expect(svg.attributes('role')).toBe('img');
expect(svg.attributes('aria-labelledby')).toContain('safe-infrastructure-diagram-title');
expect(svg.attributes('aria-describedby')).toContain('safe-infrastructure-diagram-description');
expect(wrapper.get('figcaption').text()).toContain('Secure self-hosted platform and lifecycle');
expect(wrapper.get('[data-testid="infrastructure-text-equivalent"]').text()).toContain('Ingress and TLS');
expect(wrapper.get('[data-testid="infrastructure-text-equivalent"]').text()).toContain('Identity and access');
});
it('does not turn private project content into a link container', () => {
const wrapper = mount(ProjectCaseStudy, { props: { project: privateProject } });
expect(wrapper.get('article').findAll('a')).toHaveLength(0);
expect(wrapper.get('h3').text()).toBe('Private self-hosted medication tracker');
});
it('uses a safe external link only for a public project with an approved URL', () => {
const wrapper = mount(ProjectCaseStudy, { props: { project: publicProject } });
const link = wrapper.get('article a');
expect(link.attributes('href')).toBe('https://github.com/example/footy-tracker');
expect(link.attributes('target')).toBe('_blank');
expect(link.attributes('rel')).toBe('noopener noreferrer');
});
it('announces every toolkit technology once while hiding the decorative icon placeholder', () => {
const groups: readonly ToolkitGroup[] = [{
title: 'Systems & delivery',
technologies: [{ name: 'Linux' }],
}];
const wrapper = mount(ToolkitGrid, { props: { groups } });
const tile = wrapper.get('[data-testid="toolkit-technology"]');
expect(tile.text()).toBe('Linux');
expect(tile.get('[aria-hidden="true"]').attributes('aria-hidden')).toBe('true');
expect(tile.findAll('[aria-label="Linux"]').length).toBe(0);
});
it('renders a visible mailto contact and safe verified social links', () => {
const contact: ContactContent = {
email: 'hello@example.test',
cvMessage: 'For a current CV or role-specific information, contact me directly.',
social: [{ service: 'GitHub', url: 'https://github.com/example' }],
};
const wrapper = mount(ContactDestination, {
props: {
contact,
identity: { name: 'Luca Pîslaru', role: 'System Administrator & Full-Stack Developer' },
},
});
expect(wrapper.get('a[href="mailto:hello@example.test"]').text()).toBe('hello@example.test');
const social = wrapper.get('a[href="https://github.com/example"]');
expect(social.text()).toBe('GitHub');
expect(social.attributes('rel')).toBe('noopener noreferrer');
});
});