Skip to content

Commit d1ede11

Browse files
committed
improve tests, add @comunica/query-sparql to be able to retrieve VoID description directly from the SPARQL Service Description
1 parent 6fcf683 commit d1ede11

File tree

9 files changed

+10786
-4134
lines changed

9 files changed

+10786
-4134
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ jobs:
2323
- name: Build packages
2424
run: npm run build
2525

26-
# - name: Run tests
27-
# run: npm test
26+
- name: Run tests
27+
run: npm test

package-lock.json

Lines changed: 10533 additions & 3997 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/demo/src/check.html

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ <h2>SPARQL Endpoint Metadata Check</h2>
3030
<div id="results" class="result"></div>
3131
</div>
3232

33-
<script>
33+
<script type="module">
34+
// import {} from '@sib-swiss/sparql-editor';
35+
3436
document.addEventListener("DOMContentLoaded", function () {
3537
// Prefill the input field with the 'url' parameter from the URL if available
3638
const queryParams = new URLSearchParams(window.location.search);
@@ -50,7 +52,7 @@ <h2>SPARQL Endpoint Metadata Check</h2>
5052
const response = await fetch(`${endpointUrl}?ac=1&query=${encodeURIComponent(query)}`, {
5153
signal: AbortSignal.timeout(5000),
5254
headers: {
53-
Accept: "application/json",
55+
Accept: "application/sparql-results+json",
5456
},
5557
});
5658
// console.log(await response.text());
@@ -104,27 +106,27 @@ <h2>SPARQL Endpoint Metadata Check</h2>
104106
const voidResults = await queryEndpoint(
105107
endpoint,
106108
`PREFIX up: <http://purl.uniprot.org/core/>
107-
PREFIX void: <http://rdfs.org/ns/void#>
108-
PREFIX void-ext: <http://ldf.fi/void-ext#>
109-
SELECT DISTINCT ?subjectClass
110-
WHERE {
111-
{
112-
?cp void:class ?subjectClass ;
113-
void:propertyPartition ?pp .
114-
?pp void:property ?prop .
115-
OPTIONAL {
116-
{
117-
?pp void:classPartition [ void:class ?objectClass ] .
118-
} UNION {
119-
?pp void-ext:datatypePartition [ void-ext:datatype ?objectDatatype ] .
120-
}
121-
}
122-
} UNION {
123-
?ls void:subjectsTarget ?subjectClass ;
124-
void:linkPredicate ?prop ;
125-
void:objectsTarget ?objectClass .
109+
PREFIX void: <http://rdfs.org/ns/void#>
110+
PREFIX void-ext: <http://ldf.fi/void-ext#>
111+
SELECT DISTINCT ?subjectClass ?prop ?objectClass ?objectDatatype
112+
WHERE {
113+
{
114+
?cp void:class ?subjectClass ;
115+
void:propertyPartition ?pp .
116+
?pp void:property ?prop .
117+
OPTIONAL {
118+
{
119+
?pp void:classPartition [ void:class ?objectClass ] .
120+
} UNION {
121+
?pp void-ext:datatypePartition [ void-ext:datatype ?objectDatatype ] .
122+
}
126123
}
127-
}`,
124+
} UNION {
125+
?ls void:subjectsTarget [ void:class ?subjectClass ] ;
126+
void:linkPredicate ?prop ;
127+
void:objectsTarget [ void:class ?objectClass ] .
128+
}
129+
}`,
128130
);
129131

130132
if (voidResults.length === 0) {
@@ -150,9 +152,9 @@ <h2>SPARQL Endpoint Metadata Check</h2>
150152
}
151153
}
152154
} UNION {
153-
?linkset void:subjectsTarget ?subjectClass ;
154-
void:linkPredicate ?prop ;
155-
void:objectsTarget ?objectClass .
155+
?ls void:subjectsTarget [ void:class ?subjectClass ] ;
156+
void:linkPredicate ?prop ;
157+
void:objectsTarget [ void:class ?objectClass ] .
156158
}
157159
}</code></pre>`;
158160
return;

packages/sparql-editor/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"upgrade": "npx npm-check-updates -u && npm install"
2424
},
2525
"dependencies": {
26+
"@comunica/query-sparql": "^4.1.0",
2627
"@sib-swiss/sparql-overview": "*",
2728
"@zazuko/yasgui": "4.3.3",
2829
"highlight.js": "^11.10.0",

packages/sparql-editor/src/utils.ts

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import {QueryEngine} from "@comunica/query-sparql";
2+
13
export type EndpointsMetadata = {
24
// Endpoint URL
35
[key: string]: {
@@ -75,37 +77,57 @@ export async function getPrefixes(endpoint: string): Promise<{[key: string]: str
7577
return prefixes;
7678
}
7779

80+
const voidQuery = `PREFIX up: <http://purl.uniprot.org/core/>
81+
PREFIX void: <http://rdfs.org/ns/void#>
82+
PREFIX void-ext: <http://ldf.fi/void-ext#>
83+
SELECT DISTINCT ?subjectClass ?prop ?objectClass ?objectDatatype
84+
WHERE {
85+
{
86+
?cp void:class ?subjectClass ;
87+
void:propertyPartition ?pp .
88+
?pp void:property ?prop .
89+
OPTIONAL {
90+
{
91+
?pp void:classPartition [ void:class ?objectClass ] .
92+
} UNION {
93+
?pp void-ext:datatypePartition [ void-ext:datatype ?objectDatatype ] .
94+
}
95+
}
96+
} UNION {
97+
?ls void:subjectsTarget [ void:class ?subjectClass ] ;
98+
void:linkPredicate ?prop ;
99+
void:objectsTarget [ void:class ?objectClass ] .
100+
}
101+
}`;
102+
78103
export async function getVoidDescription(endpoint: string): Promise<[VoidDict, string[], string[]]> {
79104
// Get VoID description to get classes and properties for advanced autocomplete
80105
const clsSet = new Set<string>();
81106
const predSet = new Set<string>();
82107
const voidDescription: VoidDict = {};
83108
try {
84-
const queryResults = await queryEndpoint(
85-
`PREFIX up: <http://purl.uniprot.org/core/>
86-
PREFIX void: <http://rdfs.org/ns/void#>
87-
PREFIX void-ext: <http://ldf.fi/void-ext#>
88-
SELECT DISTINCT ?subjectClass ?prop ?objectClass ?objectDatatype
89-
WHERE {
90-
{
91-
?cp void:class ?subjectClass ;
92-
void:propertyPartition ?pp .
93-
?pp void:property ?prop .
94-
OPTIONAL {
95-
{
96-
?pp void:classPartition [ void:class ?objectClass ] .
97-
} UNION {
98-
?pp void-ext:datatypePartition [ void-ext:datatype ?objectDatatype ] .
99-
}
100-
}
101-
} UNION {
102-
?ls void:subjectsTarget [ void:class ?subjectClass ] ;
103-
void:linkPredicate ?prop ;
104-
void:objectsTarget [ void:class ?objectClass ] .
105-
}
106-
}`,
107-
endpoint,
108-
);
109+
let queryResults = await queryEndpoint(voidQuery, endpoint);
110+
if (queryResults.length === 0) {
111+
// If no results from SPARQL endpoint we try to retrieve from the service description
112+
const sparqlEngine = new QueryEngine();
113+
const bindingsStream = await sparqlEngine.queryBindings(voidQuery, {
114+
sources: [
115+
// Directly query the service description:
116+
{type: "file", value: endpoint},
117+
],
118+
});
119+
const bindings = await bindingsStream.toArray();
120+
queryResults = bindings.map(b => {
121+
const result: any = {
122+
subjectClass: b.get("subjectClass"),
123+
prop: b.get("prop"),
124+
};
125+
if (b.get("objectClass")) result.objectClass = b.get("objectClass");
126+
if (b.get("objectDatatype")) result.objectDatatype = b.get("objectDatatype");
127+
return result;
128+
});
129+
}
130+
// console.log(queryResults)
109131
queryResults.forEach(b => {
110132
clsSet.add(b.subjectClass.value);
111133
predSet.add(b.prop.value);

packages/sparql-editor/test/sparql-editor.test.ts

Lines changed: 0 additions & 80 deletions
This file was deleted.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// import {describe, it, expect, beforeEach, vi} from "vitest";
2+
// import "@testing-library/jest-dom";
3+
// import "../src/sparql-editor";
4+
5+
// // We need to mock some stuff for the tests to work (vitest and jsdom don't support everything yet)
6+
// // Puppeteers or Playwright would be better for this, but they are poorly designed for testing web components
7+
// // https://playwright.dev/docs/test-components ALL FRAMEWORKS BUT NO OPTIONS FOR VANILLA JS, this is crazy
8+
9+
// // NOTE: since adding the sparql-overview we get `ReferenceError: WebGL2RenderingContext is not defined` when running with vitest
10+
11+
// describe("sparql-editor", () => {
12+
// beforeEach(() => {
13+
// document.body.innerHTML = "";
14+
15+
// // Mock getBoundingClientRect for Range
16+
// Range.prototype.getBoundingClientRect = vi.fn(() => ({
17+
// x: 0,
18+
// y: 0,
19+
// width: 100,
20+
// height: 100,
21+
// top: 0,
22+
// right: 100,
23+
// bottom: 100,
24+
// left: 0,
25+
// toJSON: () => {},
26+
// }));
27+
// // @ts-ignore Mock getClientRects for Range
28+
// Range.prototype.getClientRects = vi.fn(() => [
29+
// {
30+
// x: 0,
31+
// y: 0,
32+
// width: 100,
33+
// height: 100,
34+
// top: 0,
35+
// right: 100,
36+
// bottom: 100,
37+
// left: 0,
38+
// toJSON: () => {},
39+
// },
40+
// ]);
41+
// // Mock window.focus
42+
// window.focus = vi.fn();
43+
// });
44+
45+
// it("renders as expected for UniProt endpoint", async () => {
46+
// document.body.innerHTML = `
47+
// <sparql-editor
48+
// endpoint="https://sparql.uniprot.org/sparql/"
49+
// examples-on-main-page="10"
50+
// ></sparql-editor>
51+
// `;
52+
53+
// const sparqlEditor = document.querySelector("sparql-editor") as HTMLElement;
54+
// await customElements.whenDefined("sparql-editor");
55+
// // Wait for the element to pull examples
56+
// await new Promise(resolve => setTimeout(resolve, 2000));
57+
58+
// // Check attributes
59+
// expect(sparqlEditor).toBeInTheDocument();
60+
// expect(sparqlEditor?.getAttribute("endpoint")).toBe("https://sparql.uniprot.org/sparql/");
61+
// expect(sparqlEditor?.getAttribute("examples-on-main-page")).toBe("10");
62+
63+
// // Check DOM
64+
// expect(sparqlEditor.querySelector("#yasgui")).toBeInTheDocument();
65+
66+
// const button = sparqlEditor.querySelector("#sparql-add-prefixes-btn");
67+
// expect(button).toBeInTheDocument();
68+
// expect(button).toHaveTextContent("Add common prefixes");
69+
70+
// // Check YASGUI components. Not working when ran inside GH actions
71+
// // const yasqeEditor = sparqlEditor?.querySelectorAll(".yasqe");
72+
// // expect(yasqeEditor?.length).toBe(1);
73+
// // const yasrResult = sparqlEditor?.querySelectorAll(".yasr");
74+
// // expect(yasrResult?.length).toBe(1);
75+
76+
// // Check examples pulled successfully
77+
// const examplesOnMainPage = sparqlEditor.querySelectorAll(".sparql-main-examples");
78+
// expect(examplesOnMainPage?.length).toBe(10);
79+
// });
80+
// });

0 commit comments

Comments
 (0)