import { describe, it, expect } from 'vitest';
import { mount } from '@vue/test-utils';
import { createPinia } from 'pinia';
import { createRouter, createMemoryHistory } from 'vue-router';
import ConceptRdfView from '../components/ConceptRdfView.vue';
import { Concept } from 'glossarist';
import { CONCEPT_FIXTURES } from './__fixtures__/concepts';
function makeConcept(): Concept {
return Concept.fromJSON({
id: '3.1.1',
uri: 'https://glossarist.org/test/concept/3.1.1',
status: 'valid',
localizations: {
eng: {
language_code: 'eng',
entry_status: 'valid',
terms: [
{ type: 'expression', designation: 'atomic data unit', normative_status: 'preferred' },
{ type: 'expression', designation: 'ADU', normative_status: 'admitted' },
],
definition: [{ content: 'A data unit that cannot be subdivided.' }],
notes: [{ content: 'Note here.' }],
},
},
});
}
async function mountRdfView() {
const router = createRouter({
history: createMemoryHistory(),
routes: [{ path: '/', name: 'home', component: { template: '
' } }],
});
const wrapper = mount(ConceptRdfView, {
global: {
plugins: [createPinia(), router],
},
props: {
concept: makeConcept(),
registerId: 'test',
conceptUriValue: 'https://glossarist.org/test/concept/3.1.1',
},
});
await router.isReady();
return wrapper;
}
async function openRdfSourcePanel(wrapper: ReturnType) {
const toggle = wrapper.find('button.w-full');
await toggle.trigger('click');
}
async function mountFixture(uri: string, concept: Concept) {
const router = createRouter({
history: createMemoryHistory(),
routes: [{ path: '/', name: 'home', component: { template: '' } }],
});
const wrapper = mount(ConceptRdfView, {
global: { plugins: [createPinia(), router] },
props: { concept, registerId: 'fixtures', conceptUriValue: uri },
});
await router.isReady();
await openRdfSourcePanel(wrapper);
return wrapper;
}
// Contract tests for the migrated view. The view delegates RDF emission
// to glossarist-js via useRdfDocument. These tests verify the view still
// renders, the panel still opens, and RDF is produced — without coupling
// to the specific turtle format details (which are tested in glossarist-js's
// own suite).
describe('ConceptRdfView — Turtle emission contract', () => {
it('declares @prefix gloss: and skos: and skosxl:', async () => {
const wrapper = await mountRdfView();
await openRdfSourcePanel(wrapper);
const text = wrapper.find('pre').text();
expect(text).toContain('@prefix gloss: ');
expect(text).toContain('@prefix skos: ');
expect(text).toContain('@prefix skosxl: ');
});
it('uses skosxl: consistently (no stray xl: references)', async () => {
const wrapper = await mountRdfView();
await openRdfSourcePanel(wrapper);
const text = wrapper.find('pre').text();
expect(text).not.toMatch(/\bxl:/);
expect(text).toContain('skosxl:Label');
expect(text).toContain('skosxl:literalForm');
});
it('emits skosxl:prefLabel and skos:prefLabel both', async () => {
const wrapper = await mountRdfView();
await openRdfSourcePanel(wrapper);
const text = wrapper.find('pre').text();
// glossarist-js emits the skosxl:prefLabel link (object may be bnode or URI)
expect(text).toMatch(/skosxl:prefLabel\s+/);
// And the direct SKOS literal
expect(text).toMatch(/skos:prefLabel "atomic data unit"@eng/);
});
it('emits skosxl:altLabel and skos:altLabel both for admitted', async () => {
const wrapper = await mountRdfView();
await openRdfSourcePanel(wrapper);
const text = wrapper.find('pre').text();
expect(text).toMatch(/skosxl:altLabel\s+/);
expect(text).toMatch(/skos:altLabel "ADU"@eng/);
});
it('emits skos:definition with language tag', async () => {
const wrapper = await mountRdfView();
await openRdfSourcePanel(wrapper);
const text = wrapper.find('pre').text();
expect(text).toMatch(/skos:definition "A data unit that cannot be subdivided\."@eng/);
});
it('emits gloss:hasDefinition with DetailedDefinition typed resource', async () => {
const wrapper = await mountRdfView();
await openRdfSourcePanel(wrapper);
const text = wrapper.find('pre').text();
expect(text).toContain('gloss:DetailedDefinition');
expect(text).toMatch(/rdf:value "[^"]+"@eng/);
});
});
describe('ConceptRdfView — Layer 6 fixture corpus snapshots', () => {
for (const fixture of CONCEPT_FIXTURES) {
it(`${fixture.name}: mounts and renders RDF for the fixture concept`, async () => {
const wrapper = await mountFixture(fixture.uri, fixture.concept);
const text = wrapper.find('pre').text();
expect(text).toContain('@prefix gloss:');
expect(text).toContain('@prefix skos:');
expect(text).toContain('@prefix skosxl:');
expect(text).toContain(fixture.uri);
});
it(`${fixture.name}: contains at least one skos:prefLabel per localization`, async () => {
const wrapper = await mountFixture(fixture.uri, fixture.concept);
const text = wrapper.find('pre').text();
for (const lang of fixture.concept.languages) {
expect(text).toMatch(new RegExp(`skos:prefLabel "[^"]+"@${lang}`));
}
});
}
});