Skip to content

Commit 5f7f1fa

Browse files
authored
Merge pull request #151 from SolidLabResearch/fix/147
Fix/147
2 parents eafa6c0 + 62c1366 commit 5f7f1fa

File tree

7 files changed

+220
-13
lines changed

7 files changed

+220
-13
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
### Changed
13+
14+
### Fixed
15+
16+
- Correct error display when the queryLocation is a non existing file or faultive (#147).
17+
- Fixed a bug where editing a custom query did not correctly remove unchecked options (#150).
18+
1019
## [1.2.3] - 2024-07-11
1120

1221
### Added

cypress/e2e/custom-query-editor.cy.js

Lines changed: 144 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,9 @@ SELECT * WHERE {
163163

164164
cy.get('textarea[name="queryURL"]').invoke('val').then((val) => {
165165
expect(val).to.include('?name=new+query&description=new+description&queryString=PREFIX+schema%3A+%3Chttp%3A%2F%2Fschema.org%2F%3E+%0ASELECT+*+WHERE+%7B%0A++++%3Flist+schema%3Aname+%3FlistTitle%3B%0A++++++schema%3AitemListElement+%5B%0A++++++schema%3Aname+%3FbookTitle%3B%0A++++++schema%3Acreator+%5B%0A++++++++schema%3Aname+%3FauthorName%0A++++++%5D%0A++++%5D.%0A%7D&source=http%3A%2F%2Flocalhost%3A8080%2Fexample%2Fwish-list');
166-
});
167-
168-
166+
});
167+
168+
169169
})
170170

171171
it("Custom templated query", () => {
@@ -184,7 +184,7 @@ SELECT ?name ?sameAs_url WHERE {
184184
schema:genre $genre;
185185
schema:sameAs ?sameAs_url;
186186
}`
187-
);
187+
);
188188

189189
cy.get('input[name="source"]').type("http://localhost:8080/example/favourite-musicians");
190190
cy.get('input[name="templatedQueryCheck"]').click()
@@ -245,7 +245,7 @@ WHERE {
245245
?material o:name ?materialName ;
246246
}
247247
ORDER BY ?componentName`
248-
);
248+
);
249249

250250
// No Comunica Sources Required
251251
cy.get('input[name="sourceIndexCheck"]').click()
@@ -260,11 +260,149 @@ SELECT ?object
260260
WHERE {
261261
example:index-example rdfs:seeAlso ?object .
262262
}`
263-
)
263+
)
264264
cy.get('button[type="submit"]').click();
265265

266266
cy.contains("https://www.example.com/data/component-c01").should('exist');
267267

268268
})
269269

270+
271+
272+
it("Make a templated query, then edit it to make it a normal query", () => {
273+
274+
// First create the query
275+
cy.visit("/#/customQuery");
276+
277+
cy.get('input[name="name"]').type("custom template");
278+
cy.get('textarea[name="description"]').type("description for template");
279+
280+
// Query handling a variable
281+
cy.get('textarea[name="queryString"]').clear();
282+
cy.get('textarea[name="queryString"]').type(`PREFIX schema: <http://schema.org/>
283+
SELECT ?name ?sameAs_url WHERE {
284+
?list schema:name ?listTitle;
285+
schema:name ?name;
286+
schema:genre $genre;
287+
schema:sameAs ?sameAs_url;
288+
}`
289+
);
290+
291+
cy.get('input[name="source"]').type("http://localhost:8080/example/favourite-musicians");
292+
cy.get('input[name="templatedQueryCheck"]').click()
293+
294+
cy.get('textarea[name="templateOptions"]').clear()
295+
cy.get('textarea[name="templateOptions"]').type(`{"variables" : {
296+
"genre": [
297+
"\\"Romantic\\"",
298+
"\\"Baroque\\"",
299+
"\\"Classical\\""
300+
]
301+
}}`)
302+
cy.get('button[type="submit"]').click();
303+
304+
305+
cy.get('form').within(() => {
306+
cy.get('#genre').click();
307+
});
308+
cy.get('li').contains('Baroque').click();
309+
310+
// Comfirm query
311+
cy.get('button[type="submit"]').click();
312+
313+
cy.get('.column-name').find('span').contains("Antonio Caldara").should('exist');
314+
315+
// Now that this templated one works, lets edit it to make a normal query from it
316+
cy.get('button').contains("Edit Query").click();
317+
318+
cy.get('textarea[name="queryString"]').clear();
319+
cy.get('textarea[name="queryString"]').type(`PREFIX schema: <http://schema.org/>
320+
SELECT ?name ?genre ?sameAs_url WHERE {
321+
?list schema:name ?listTitle;
322+
schema:name ?name;
323+
schema:genre ?genre;
324+
schema:sameAs ?sameAs_url;
325+
}`
326+
);
327+
328+
// Remove the templated options
329+
cy.get('input[name="templatedQueryCheck"]').click()
330+
331+
cy.get('button[type="submit"]').click();
332+
333+
cy.get('form').should('not.exist')
334+
335+
cy.get('.column-name').find('span').contains("Ludwig van Beethoven").should('exist');
336+
})
337+
338+
// Reverse logic
339+
340+
it("Make a normal query, then edit it to make it a templated query", () => {
341+
342+
// First create the query
343+
cy.visit("/#/customQuery");
344+
345+
cy.get('input[name="name"]').type("custom template");
346+
cy.get('textarea[name="description"]').type("description for template");
347+
348+
// Query handling a variable
349+
cy.get('textarea[name="queryString"]').clear();
350+
cy.get('textarea[name="queryString"]').type(`PREFIX schema: <http://schema.org/>
351+
SELECT ?name ?genre ?sameAs_url WHERE {
352+
?list schema:name ?listTitle;
353+
schema:name ?name;
354+
schema:genre ?genre;
355+
schema:sameAs ?sameAs_url;
356+
}`
357+
);
358+
359+
cy.get('input[name="source"]').type("http://localhost:8080/example/favourite-musicians");
360+
361+
cy.get('button[type="submit"]').click();
362+
363+
cy.get('form').should('not.exist')
364+
365+
cy.get('.column-name').find('span').contains("Ludwig van Beethoven").should('exist');
366+
367+
368+
369+
370+
// Now that this normal one works, lets edit it to make a templated query from it
371+
cy.get('button').contains("Edit Query").click();
372+
373+
cy.get('textarea[name="queryString"]').clear();
374+
cy.get('textarea[name="queryString"]').type(`PREFIX schema: <http://schema.org/>
375+
SELECT ?name ?sameAs_url WHERE {
376+
?list schema:name ?listTitle;
377+
schema:name ?name;
378+
schema:genre $genre;
379+
schema:sameAs ?sameAs_url;
380+
}`
381+
);
382+
383+
cy.get('input[name="templatedQueryCheck"]').click()
384+
385+
cy.get('textarea[name="templateOptions"]').clear()
386+
cy.get('textarea[name="templateOptions"]').type(`{"variables" : {
387+
"genre": [
388+
"\\"Romantic\\"",
389+
"\\"Baroque\\"",
390+
"\\"Classical\\""
391+
]
392+
}}`)
393+
394+
cy.get('button[type="submit"]').click();
395+
396+
397+
cy.get('form').within(() => {
398+
cy.get('#genre').click();
399+
});
400+
cy.get('li').contains('Baroque').click();
401+
402+
// Comfirm query
403+
cy.get('button[type="submit"]').click();
404+
405+
cy.get('.column-name').find('span').contains("Antonio Caldara").should('exist');
406+
})
407+
270408
})

cypress/e2e/queryLocation-test.cy.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
describe("query location tests", () => {
2+
3+
// Errors with the correct message should be thrown
4+
it("queryLocation that does not end on rq", () => {
5+
cy.visit("/");
6+
cy.contains("For testing only").click();
7+
cy.contains("Average value - queryLocation without rq").click();
8+
9+
cy.contains("Invalid query location.").should("exist");
10+
});
11+
12+
it("wrong queryLocation that does not exist, correct file ending", () => {
13+
cy.visit("/");
14+
cy.contains("For testing only").click();
15+
cy.contains("Average value - unexisting queryLocation (ends in .rq)").click();
16+
17+
cy.contains("Empty query text. Check your query and location.").should("exist");
18+
});
19+
});
20+

src/components/Dashboard/CustomQueryEditor/customEditor.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,10 @@ WHERE {
175175
const updateQuery = (formData, customQuery) => {
176176
formData = parseAllObjectsToJSON(formData);
177177
configManager.updateQuery({
178-
...customQuery,
179-
...formData
178+
...formData,
179+
id: customQuery.id,
180+
queryGroupId: customQuery.queryGroupId,
181+
icon: customQuery.icon
180182
});
181183

182184
navigate(`/${customQuery.id}`)

src/config.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,32 @@
9595
]
9696
}
9797
},
98+
{
99+
"id": "1045",
100+
"queryGroupId": "c-tst",
101+
"queryLocation": "average",
102+
"name": "Average value - queryLocation without rq",
103+
"description": "Should demonstrates a query calculating some average, but the queryLocation is faultive.",
104+
"icon": "FunctionsIcon",
105+
"comunicaContext": {
106+
"sources": [
107+
"http://localhost:8080/example/values"
108+
]
109+
}
110+
},
111+
{
112+
"id": "1046",
113+
"queryGroupId": "c-tst",
114+
"queryLocation": "averagefefefefe.rq",
115+
"name": "Average value - unexisting queryLocation (ends in .rq)",
116+
"description": "Should demonstrates a query calculating some average, but the queryLocation is faultive.",
117+
"icon": "FunctionsIcon",
118+
"comunicaContext": {
119+
"sources": [
120+
"http://localhost:8080/example/values"
121+
]
122+
}
123+
},
98124
{
99125
"id": "1050",
100126
"queryGroupId": "a-ex",

src/configManager/configManager.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@ class ConfigManager extends EventEmitter {
160160
async getQueryText(query) {
161161

162162
if (query.queryLocation) {
163+
164+
if(!query.queryLocation.endsWith('.rq')){
165+
return undefined
166+
}
167+
163168
const fetchResult = await fetch(`${this.config.queryFolder}${query.queryLocation}`);
164169
return await fetchResult.text();
165170
}

src/dataProvider/SparqlDataProvider.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ async function buildQueryText(query) {
109109
try {
110110
let rawText = await configManager.getQueryText(query);
111111

112+
if (rawText === undefined) {
113+
throw new Error("Invalid query location.")
114+
}
115+
if (rawText === null || rawText === '' ) {
116+
throw new Error("Empty query text. Check your query and location.")
117+
}
118+
112119
if (query.variableValues) {
113120
rawText = replaceVariables(rawText, query.variableValues);
114121
}
@@ -344,15 +351,15 @@ const addComunicaContextSourcesFromSourcesIndex = async (sourcesIndex) => {
344351
const sourcesList = [];
345352
try {
346353
let queryStringIndexSource;
347-
if (sourcesIndex.queryLocation){
354+
if (sourcesIndex.queryLocation) {
348355
const result = await fetch(`${config.queryFolder}${sourcesIndex.queryLocation}`);
349356
queryStringIndexSource = await result.text();
350-
}else{
351-
queryStringIndexSource = sourcesIndex.queryString;
357+
} else {
358+
queryStringIndexSource = sourcesIndex.queryString;
352359
}
353-
360+
354361
const bindingsStream = await myEngine.queryBindings(queryStringIndexSource, {
355-
...generateContext({sources: [sourcesIndex.url]}),
362+
...generateContext({ sources: [sourcesIndex.url] }),
356363
});
357364
await new Promise((resolve, reject) => {
358365
bindingsStream.on('data', (bindings) => {

0 commit comments

Comments
 (0)