graphdb-workbench-tests 4.0.0-TR14 → 4.0.0-TR16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/e2e-legacy/graph-navigator/graph-navigator.spec.js +115 -0
- package/e2e-legacy/home/home-page-without-repositories.spec.js +3 -1
- package/e2e-legacy/home/home-page-without-selected-repository.spec.js +2 -1
- package/e2e-legacy/repository/ontop-repository.spec.js +22 -31
- package/e2e-legacy/setup/plugins/plugins-without-repository.spec.js +1 -1
- package/fixtures/graph-navigator/graph-navigator-settings-invalid.ttl +149 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/steps/error-steps.js +1 -1
- package/steps/graph-navigator-steps.js +22 -0
- package/steps/ontop-repository-steps.js +4 -0
- package/steps/setup/acl-management-steps.js +1 -1
- package/steps/toaster-steps.js +4 -0
- package/steps/widgets/repository-errors-widget-steps.js +6 -2
- package/stubs/graph-navigator-stubs.js +27 -0
|
@@ -5,12 +5,15 @@ import {MainMenuSteps} from '../../steps/main-menu-steps.js';
|
|
|
5
5
|
import {YasqeSteps} from '../../steps/yasgui/yasqe-steps.js';
|
|
6
6
|
import {YasrSteps} from '../../steps/yasgui/yasr-steps.js';
|
|
7
7
|
import {ToasterSteps} from '../../steps/toaster-steps.js';
|
|
8
|
+
import {GraphNavigatorStubs} from '../../stubs/graph-navigator-stubs.js';
|
|
8
9
|
|
|
9
10
|
const FILE_TO_IMPORT = 'resource-test-data.ttl';
|
|
10
11
|
const SEED_RESOURCE_ENCODED = 'http:%2F%2Fexample.com%2Fontology%23CustomerLoyalty';
|
|
11
12
|
const SEED_RESOURCE_LABEL = 'CustomerLoyalty';
|
|
12
13
|
const SETTINGS_FILE_NAME = 'graph-navigator-settings.ttl';
|
|
13
14
|
const SETTINGS_FILE = `fixtures/graph-navigator/${SETTINGS_FILE_NAME}`;
|
|
15
|
+
const INVALID_SETTINGS_FILE_NAME = 'graph-navigator-settings-invalid.ttl';
|
|
16
|
+
const INVALID_SETTINGS_FILE = `fixtures/graph-navigator/${INVALID_SETTINGS_FILE_NAME}`;
|
|
14
17
|
|
|
15
18
|
const CONSTRUCT_QUERY = 'CONSTRUCT { <http://example.com/ontology#CustomerLoyalty> ?p ?o } WHERE { <http://example.com/ontology#CustomerLoyalty> ?p ?o }';
|
|
16
19
|
const CONSTRUCT_TARGET_LABEL = 'Metric';
|
|
@@ -219,6 +222,43 @@ describe('Graph Navigator', () => {
|
|
|
219
222
|
GraphNavigatorSteps.getWorkspace().should('exist');
|
|
220
223
|
});
|
|
221
224
|
|
|
225
|
+
it('should show the validation errors of a rejected file on its row', () => {
|
|
226
|
+
// Given I have selected a settings file with invalid values and an unknown property.
|
|
227
|
+
GraphNavigatorSteps.visit();
|
|
228
|
+
GraphNavigatorSteps.openSettings();
|
|
229
|
+
GraphNavigatorSteps.selectSettingsFile(INVALID_SETTINGS_FILE);
|
|
230
|
+
|
|
231
|
+
// When I upload it.
|
|
232
|
+
GraphNavigatorSteps.clickUpload();
|
|
233
|
+
GraphNavigatorSteps.confirmDialog();
|
|
234
|
+
|
|
235
|
+
// Then I expect the errors in a table on the file row.
|
|
236
|
+
ToasterSteps.verifyNewToasterError('Could not upload the settings');
|
|
237
|
+
GraphNavigatorSteps.getSelectedSettingsFile(INVALID_SETTINGS_FILE_NAME).should('exist');
|
|
238
|
+
GraphNavigatorSteps.getUploadErrors().should('be.visible')
|
|
239
|
+
.and('contain', '3 validation errors')
|
|
240
|
+
.and('contain', 'Fix these properties in the file and upload it again.');
|
|
241
|
+
GraphNavigatorSteps.getUploadError('gn:acceptBlankNodes').should('contain', 'Must be of type boolean');
|
|
242
|
+
GraphNavigatorSteps.getUploadError('gn:openWorldProperties').should('contain', 'Must be of type boolean');
|
|
243
|
+
GraphNavigatorSteps.getUploadError('gn:unknownSetting')
|
|
244
|
+
.should('contain', 'Not a known property');
|
|
245
|
+
|
|
246
|
+
// When I close and reopen the settings.
|
|
247
|
+
GraphNavigatorSteps.closeSettings();
|
|
248
|
+
GraphNavigatorSteps.openSettings();
|
|
249
|
+
|
|
250
|
+
// Then I expect the file and its errors to be kept.
|
|
251
|
+
GraphNavigatorSteps.getSelectedSettingsFile(INVALID_SETTINGS_FILE_NAME).should('exist');
|
|
252
|
+
GraphNavigatorSteps.getUploadErrors().should('be.visible')
|
|
253
|
+
.and('contain', '3 validation errors');
|
|
254
|
+
|
|
255
|
+
// When I remove the file.
|
|
256
|
+
GraphNavigatorSteps.clickCancelFile();
|
|
257
|
+
|
|
258
|
+
// Then I expect the errors to be cleared.
|
|
259
|
+
GraphNavigatorSteps.getUploadErrors().should('not.exist');
|
|
260
|
+
});
|
|
261
|
+
|
|
222
262
|
it('should ask for confirmation before resetting', () => {
|
|
223
263
|
// Given the repository has uploaded settings.
|
|
224
264
|
GraphNavigatorSteps.visit();
|
|
@@ -264,6 +304,48 @@ describe('Graph Navigator', () => {
|
|
|
264
304
|
});
|
|
265
305
|
});
|
|
266
306
|
|
|
307
|
+
describe('Autocomplete warning', () => {
|
|
308
|
+
beforeEach(() => {
|
|
309
|
+
GraphNavigatorStubs.stubSettingsWithAutocomplete();
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('should warn once that autocomplete is off', () => {
|
|
313
|
+
// Given the settings use autocomplete, but autocomplete is off.
|
|
314
|
+
GraphNavigatorStubs.spyEntityLookup(SEED_RESOURCE_LABEL);
|
|
315
|
+
GraphNavigatorSteps.visit();
|
|
316
|
+
cy.wait('@graph-navigator-settings');
|
|
317
|
+
|
|
318
|
+
// When I search for entities.
|
|
319
|
+
GraphNavigatorSteps.searchEntities(SEED_RESOURCE_LABEL);
|
|
320
|
+
cy.wait('@entity-lookup');
|
|
321
|
+
|
|
322
|
+
// Then I expect a warning that autocomplete is off.
|
|
323
|
+
ToasterSteps.getWarningToast().should('be.visible').and('contain', 'Autocomplete is OFF');
|
|
324
|
+
|
|
325
|
+
// When the warning is gone and I search for entities again.
|
|
326
|
+
ToasterSteps.getToast().should('not.exist');
|
|
327
|
+
GraphNavigatorSteps.searchEntities(SEED_RESOURCE_LABEL);
|
|
328
|
+
cy.wait('@entity-lookup');
|
|
329
|
+
|
|
330
|
+
// Then I expect no new warning.
|
|
331
|
+
ToasterSteps.getToast().should('not.exist');
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it('should redirect to the autocomplete view when the warning is clicked', () => {
|
|
335
|
+
// Given the settings use autocomplete, but autocomplete is off.
|
|
336
|
+
GraphNavigatorSteps.visit();
|
|
337
|
+
cy.wait('@graph-navigator-settings');
|
|
338
|
+
|
|
339
|
+
// When I search for entities and click the warning.
|
|
340
|
+
GraphNavigatorSteps.searchEntities(SEED_RESOURCE_LABEL);
|
|
341
|
+
ToasterSteps.getWarningToast().should('be.visible').and('contain', 'Autocomplete is OFF');
|
|
342
|
+
ToasterSteps.getWarningToast().click();
|
|
343
|
+
|
|
344
|
+
// Then I expect to be redirected to the autocomplete view.
|
|
345
|
+
cy.url().should('include', '/autocomplete');
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
|
|
267
349
|
describe('Repository switch', () => {
|
|
268
350
|
let secondRepositoryId;
|
|
269
351
|
|
|
@@ -314,5 +396,38 @@ describe('Graph Navigator', () => {
|
|
|
314
396
|
GraphNavigatorSteps.getElements().should('not.exist');
|
|
315
397
|
GraphNavigatorSteps.verifyOnlyRepositoryParam(secondRepositoryId);
|
|
316
398
|
});
|
|
399
|
+
|
|
400
|
+
it('should warn that autocomplete is off once per repository selection', () => {
|
|
401
|
+
// Given the settings use autocomplete, but autocomplete is off.
|
|
402
|
+
GraphNavigatorStubs.stubSettingsWithAutocomplete();
|
|
403
|
+
GraphNavigatorSteps.visit();
|
|
404
|
+
cy.wait('@graph-navigator-settings');
|
|
405
|
+
|
|
406
|
+
// When I search for entities.
|
|
407
|
+
GraphNavigatorSteps.searchEntities(SEED_RESOURCE_LABEL);
|
|
408
|
+
|
|
409
|
+
// Then I expect a warning that autocomplete is off.
|
|
410
|
+
ToasterSteps.getWarningToast().should('be.visible').and('contain', 'Autocomplete is OFF');
|
|
411
|
+
|
|
412
|
+
// When the warning is gone and I switch to another repository and search for entities.
|
|
413
|
+
ToasterSteps.getToast().should('not.exist');
|
|
414
|
+
RepositorySelectorSteps.selectRepository(secondRepositoryId);
|
|
415
|
+
GraphNavigatorSteps.confirmDialog();
|
|
416
|
+
cy.wait('@graph-navigator-settings');
|
|
417
|
+
GraphNavigatorSteps.searchEntities(SEED_RESOURCE_LABEL);
|
|
418
|
+
|
|
419
|
+
// Then I expect a new warning, for the new repository.
|
|
420
|
+
ToasterSteps.getWarningToast().should('be.visible').and('contain', 'Autocomplete is OFF');
|
|
421
|
+
|
|
422
|
+
// When the warning is gone and I switch back to the first repository and search for entities.
|
|
423
|
+
ToasterSteps.getToast().should('not.exist');
|
|
424
|
+
RepositorySelectorSteps.selectRepository(repositoryId);
|
|
425
|
+
GraphNavigatorSteps.confirmDialog();
|
|
426
|
+
cy.wait('@graph-navigator-settings');
|
|
427
|
+
GraphNavigatorSteps.searchEntities(SEED_RESOURCE_LABEL);
|
|
428
|
+
|
|
429
|
+
// Then I expect a new warning, because the repository was selected again.
|
|
430
|
+
ToasterSteps.getWarningToast().should('be.visible').and('contain', 'Autocomplete is OFF');
|
|
431
|
+
});
|
|
317
432
|
});
|
|
318
433
|
});
|
|
@@ -33,7 +33,9 @@ describe('Home page: without repositories', () => {
|
|
|
33
33
|
HomeSteps.getRepositoryErrorsWidget().should('be.visible');
|
|
34
34
|
RepositoryErrorsWidgetSteps.getInfoMessage().should('contain', 'Some functionalities are not available because you are not connected to any repository.');
|
|
35
35
|
RepositoryErrorsWidgetSteps.getCreateRepositoryBtn().should('be.visible');
|
|
36
|
-
|
|
36
|
+
// There are no repositories to filter.
|
|
37
|
+
RepositoryErrorsWidgetSteps.getRepositoryFilter().should('not.exist');
|
|
38
|
+
RepositoryErrorsWidgetSteps.getLocalOnlyCheckbox().should('not.exist');
|
|
37
39
|
});
|
|
38
40
|
|
|
39
41
|
it('should render license widget', () => {
|
|
@@ -29,7 +29,8 @@ describe('Home page: without selected repository', () => {
|
|
|
29
29
|
HomeSteps.getRepositoryErrorsWidget().should('be.visible');
|
|
30
30
|
RepositoryErrorsWidgetSteps.getInfoMessage().should('contain', 'Some functionalities are not available because you are not connected to any repository.');
|
|
31
31
|
RepositoryErrorsWidgetSteps.getCreateRepositoryBtn().should('be.visible');
|
|
32
|
-
RepositoryErrorsWidgetSteps.
|
|
32
|
+
RepositoryErrorsWidgetSteps.getRepositoryFilter().should('be.visible');
|
|
33
|
+
RepositoryErrorsWidgetSteps.getLocalOnlyCheckbox().should('be.visible').and('be.checked');
|
|
33
34
|
});
|
|
34
35
|
|
|
35
36
|
// This test is unreliable with the current implementation of the license widget.
|
|
@@ -245,48 +245,42 @@ describe('Ontop repositories', () => {
|
|
|
245
245
|
context('Repository maintenance permission', () => {
|
|
246
246
|
|
|
247
247
|
const PASSWORD = 'root';
|
|
248
|
-
|
|
249
|
-
const REPOSITORY_MANAGER_USERNAME = 'repoManager';
|
|
248
|
+
let repositoryMaintainerUsername;
|
|
250
249
|
|
|
251
250
|
beforeEach(() => {
|
|
252
|
-
|
|
253
|
-
username: REPOSITORY_MAINTAINER_USERNAME,
|
|
254
|
-
password: PASSWORD,
|
|
255
|
-
grantedAuthorities: [
|
|
256
|
-
`READ_REPO_${repositoryId}`,
|
|
257
|
-
`MAINTAIN_REPO_${repositoryId}`,
|
|
258
|
-
`WRITE_REPO_${repositoryId}`
|
|
259
|
-
]
|
|
260
|
-
});
|
|
261
|
-
cy.createUser({
|
|
262
|
-
username: REPOSITORY_MANAGER_USERNAME,
|
|
263
|
-
password: PASSWORD,
|
|
264
|
-
grantedAuthorities: [
|
|
265
|
-
'ROLE_USER',
|
|
266
|
-
'ROLE_MONITORING',
|
|
267
|
-
'ROLE_REPO_MANAGER'
|
|
268
|
-
]
|
|
269
|
-
});
|
|
270
|
-
cy.switchOnSecurity();
|
|
251
|
+
repositoryMaintainerUsername = 'repo-maintainer-' + Date.now();
|
|
271
252
|
});
|
|
272
253
|
|
|
273
254
|
afterEach(() => {
|
|
274
255
|
cy.loginAsAdmin()
|
|
275
256
|
.then(() => {
|
|
276
|
-
cy.deleteUser(
|
|
277
|
-
cy.deleteUser(REPOSITORY_MANAGER_USERNAME, true);
|
|
257
|
+
cy.deleteUser(repositoryMaintainerUsername, true);
|
|
278
258
|
cy.switchOffSecurity(true);
|
|
279
259
|
});
|
|
280
260
|
});
|
|
281
261
|
it('should allow a repository maintainer to edit an Ontop repository', () => {
|
|
282
262
|
RepositoryStubs.spyGetJDBCProperties();
|
|
283
263
|
// GIVEN: An Ontop repository exists
|
|
284
|
-
cy.loginAs(REPOSITORY_MANAGER_USERNAME, PASSWORD);
|
|
285
264
|
OntopRepositorySteps.visitCreate();
|
|
286
265
|
createOntopRepository(repositoryId);
|
|
266
|
+
RepositorySteps.waitUntilRepositoriesPageIsLoaded();
|
|
267
|
+
RepositorySteps.getRepositoryFromList(repositoryId).should('exist');
|
|
268
|
+
|
|
269
|
+
// AND: A user with maintenance permission for it is created after the repository,
|
|
270
|
+
// because creating a repository removes the permissions already granted for its ID.
|
|
271
|
+
cy.createUser({
|
|
272
|
+
username: repositoryMaintainerUsername,
|
|
273
|
+
password: PASSWORD,
|
|
274
|
+
grantedAuthorities: [
|
|
275
|
+
`READ_REPO_${repositoryId}`,
|
|
276
|
+
`MAINTAIN_REPO_${repositoryId}`,
|
|
277
|
+
`WRITE_REPO_${repositoryId}`
|
|
278
|
+
]
|
|
279
|
+
});
|
|
280
|
+
cy.switchOnSecurity();
|
|
287
281
|
|
|
288
282
|
// WHEN: I log in as a user with maintenance permission
|
|
289
|
-
cy.loginAs(
|
|
283
|
+
cy.loginAs(repositoryMaintainerUsername, PASSWORD);
|
|
290
284
|
RepositorySteps.visit();
|
|
291
285
|
|
|
292
286
|
// THEN: The repository is visible because the user can maintain it
|
|
@@ -326,8 +320,7 @@ describe('Ontop repositories', () => {
|
|
|
326
320
|
.should('contain.value', 'ontop.cardinalityMode=LOOSE');
|
|
327
321
|
// Saving of the OBDA file verifies that the repository maintainer can access rest/repositories/file/upload
|
|
328
322
|
OntopRepositorySteps.editOBDAFile();
|
|
329
|
-
|
|
330
|
-
.find('textarea')
|
|
323
|
+
OntopRepositorySteps.getFileContentEditor()
|
|
331
324
|
.invoke('val')
|
|
332
325
|
.should('include', 'edited ODBA file');
|
|
333
326
|
ModalDialogSteps.close();
|
|
@@ -339,8 +332,7 @@ describe('Ontop repositories', () => {
|
|
|
339
332
|
ModalDialogSteps.getDialogHeader()
|
|
340
333
|
.should('contain', 'Edit "OBDA or R2RML file" contents');
|
|
341
334
|
|
|
342
|
-
|
|
343
|
-
.find('textarea')
|
|
335
|
+
OntopRepositorySteps.getFileContentEditor()
|
|
344
336
|
.type('{moveToStart}Add commentary for testing purpose');
|
|
345
337
|
|
|
346
338
|
ModalDialogSteps.clickOKButton();
|
|
@@ -354,8 +346,7 @@ describe('Ontop repositories', () => {
|
|
|
354
346
|
cy.wait('@getJDBCProperties');
|
|
355
347
|
OntopRepositorySteps.editOBDAFile();
|
|
356
348
|
|
|
357
|
-
|
|
358
|
-
.find('textarea')
|
|
349
|
+
OntopRepositorySteps.getFileContentEditor()
|
|
359
350
|
.invoke('val')
|
|
360
351
|
.should('include', 'Add commentary for testing purpose');
|
|
361
352
|
});
|
|
@@ -22,7 +22,7 @@ describe('Plugins without selected repository', () => {
|
|
|
22
22
|
const verifyInitialStateWithoutSelectedRepository = () => {
|
|
23
23
|
ErrorSteps.verifyNoConnectedRepoMessage();
|
|
24
24
|
PluginsSteps.getPluginsView().should('be.visible');
|
|
25
|
-
PluginsSteps.getSearchPluginBar().should('not.
|
|
25
|
+
PluginsSteps.getSearchPluginBar().should('not.exist');
|
|
26
26
|
PluginsSteps.getPluginsList().should('not.exist');
|
|
27
27
|
};
|
|
28
28
|
})
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
@prefix gn: <http://www.ontotext.com/graph-navigator#> .
|
|
2
|
+
|
|
3
|
+
gn:settings gn:defaultPrefix """PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
4
|
+
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
|
5
|
+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
|
|
6
|
+
""";
|
|
7
|
+
gn:schemaLabelProperty "rdfs:label";
|
|
8
|
+
gn:dataLabelProperty "rdfs:label";
|
|
9
|
+
gn:classTreeQuery """
|
|
10
|
+
SELECT ?class ?label ?parent
|
|
11
|
+
WHERE {
|
|
12
|
+
{
|
|
13
|
+
?class a rdfs:Class
|
|
14
|
+
} UNION {
|
|
15
|
+
?class a owl:Class
|
|
16
|
+
}
|
|
17
|
+
FILTER ISIRI(?class)
|
|
18
|
+
OPTIONAL {
|
|
19
|
+
?class rdfs:label ?label
|
|
20
|
+
${labelLanguageFilter}
|
|
21
|
+
}
|
|
22
|
+
OPTIONAL {?class rdfs:subClassOf ?parent. FILTER ISIRI(?parent)}
|
|
23
|
+
}
|
|
24
|
+
""";
|
|
25
|
+
gn:classInfoQuery """SELECT ?class ?label ?instcount WHERE {
|
|
26
|
+
VALUES(?class) {${ids}}
|
|
27
|
+
OPTIONAL {
|
|
28
|
+
?class ${schemaLabelProperty} ?label
|
|
29
|
+
${labelLanguageFilter}
|
|
30
|
+
}
|
|
31
|
+
BIND(\"\" as ?instcount)
|
|
32
|
+
}""";
|
|
33
|
+
gn:linkTypesQuery """SELECT DISTINCT ?link ?instcount ?label WHERE {
|
|
34
|
+
${linkTypesPattern}
|
|
35
|
+
OPTIONAL {
|
|
36
|
+
?link ${schemaLabelProperty} ?label
|
|
37
|
+
${labelLanguageFilter}
|
|
38
|
+
}
|
|
39
|
+
}""";
|
|
40
|
+
gn:linkTypesPattern """
|
|
41
|
+
{ ?link a rdf:Property }
|
|
42
|
+
UNION
|
|
43
|
+
{ ?link a owl:ObjectProperty }
|
|
44
|
+
BIND('' as ?instcount)
|
|
45
|
+
""";
|
|
46
|
+
gn:linkTypesInfoQuery """SELECT ?link ?label WHERE {
|
|
47
|
+
VALUES(?link) {${ids}}
|
|
48
|
+
OPTIONAL {
|
|
49
|
+
?link ${schemaLabelProperty} ?label
|
|
50
|
+
${labelLanguageFilter}
|
|
51
|
+
}
|
|
52
|
+
}""";
|
|
53
|
+
gn:propertyInfoQuery """SELECT ?property ?label WHERE {
|
|
54
|
+
VALUES(?property) {${ids}}
|
|
55
|
+
OPTIONAL {
|
|
56
|
+
?property ${schemaLabelProperty} ?label
|
|
57
|
+
${labelLanguageFilter}
|
|
58
|
+
}
|
|
59
|
+
}""";
|
|
60
|
+
gn:elementInfoQuery """
|
|
61
|
+
CONSTRUCT {
|
|
62
|
+
?inst <urn:reactodia:sparql:type> ?class .
|
|
63
|
+
?inst <urn:reactodia:sparql:label> ?label .
|
|
64
|
+
?inst ?propType ?propValue.
|
|
65
|
+
} WHERE {
|
|
66
|
+
VALUES (?inst) {${ids}}
|
|
67
|
+
OPTIONAL { ?inst a ?class }
|
|
68
|
+
OPTIONAL {
|
|
69
|
+
?inst ${dataLabelProperty} ?label
|
|
70
|
+
${labelLanguageFilter}
|
|
71
|
+
}
|
|
72
|
+
OPTIONAL {
|
|
73
|
+
${propertyConfigurations}
|
|
74
|
+
FILTER (isLiteral(?propValue))
|
|
75
|
+
${valueLanguageFilter}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
""";
|
|
79
|
+
gn:linksInfoQuery """SELECT ?source ?type ?target
|
|
80
|
+
WHERE {
|
|
81
|
+
${linkConfigurations}
|
|
82
|
+
VALUES (?source) {${sourceIris}}
|
|
83
|
+
VALUES (?target) {${targetIris}}
|
|
84
|
+
}""";
|
|
85
|
+
gn:imageQueryPattern "{ ?inst ?linkType ?image } UNION { [] ?linkType ?inst. BIND(?inst as ?image) }";
|
|
86
|
+
gn:linkTypesOfQuery """
|
|
87
|
+
SELECT DISTINCT ?link ?direction
|
|
88
|
+
WHERE {
|
|
89
|
+
${linkConfigurations}
|
|
90
|
+
}
|
|
91
|
+
""";
|
|
92
|
+
gn:linkTypesStatisticsQuery """
|
|
93
|
+
SELECT ?link ?outCount ?inCount
|
|
94
|
+
WHERE {
|
|
95
|
+
{
|
|
96
|
+
SELECT (${linkId} as ?link) (count(?outObject) as ?outCount) WHERE {
|
|
97
|
+
${linkConfigurationOut}
|
|
98
|
+
${navigateElementFilterOut}
|
|
99
|
+
} LIMIT 101
|
|
100
|
+
} {
|
|
101
|
+
SELECT (${linkId} as ?link) (count(?inObject) as ?inCount) WHERE {
|
|
102
|
+
${linkConfigurationIn}
|
|
103
|
+
${navigateElementFilterIn}
|
|
104
|
+
} LIMIT 101
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
""";
|
|
108
|
+
gn:lookupQuery """SELECT ${outerProjection} WHERE {
|
|
109
|
+
${filterInnerPrelude}
|
|
110
|
+
{
|
|
111
|
+
SELECT DISTINCT ${innerProjection} WHERE {
|
|
112
|
+
${filterByType}
|
|
113
|
+
${filterByRefElementLink}
|
|
114
|
+
${filterByText}
|
|
115
|
+
${filterAdditionalRestriction}
|
|
116
|
+
} ${orderBy} ${limit}
|
|
117
|
+
}
|
|
118
|
+
${queryTypes}
|
|
119
|
+
${queryElementInfo}
|
|
120
|
+
} ${orderBy}""";
|
|
121
|
+
gn:filterInnerPrelude "";
|
|
122
|
+
gn:filterRefElementLinkPattern "";
|
|
123
|
+
gn:filterTypePattern "?inst a ?instType. ?instType rdfs:subClassOf* ?class";
|
|
124
|
+
gn:filterElementInfoPattern """
|
|
125
|
+
OPTIONAL {?inst rdf:type ?foundClass}
|
|
126
|
+
BIND (coalesce(?foundClass, owl:Thing) as ?class)
|
|
127
|
+
OPTIONAL {
|
|
128
|
+
?inst ${dataLabelProperty} ?label
|
|
129
|
+
${labelLanguageFilter}
|
|
130
|
+
}
|
|
131
|
+
""";
|
|
132
|
+
gn:filterAdditionalRestriction "";
|
|
133
|
+
gn:openWorldLinks false;
|
|
134
|
+
gn:openWorldProperties "no";
|
|
135
|
+
gn:acceptBlankNodes "no";
|
|
136
|
+
gn:unknownSetting "x";
|
|
137
|
+
gn:blankNodeStatementLimit "20"^^<http://www.w3.org/2001/XMLSchema#int>;
|
|
138
|
+
gn:filterOnlyLanguages [ a <http://www.w3.org/1999/02/22-rdf-syntax-ns#List>;
|
|
139
|
+
<http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "en";
|
|
140
|
+
<http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>
|
|
141
|
+
];
|
|
142
|
+
gn:fullTextSearch [
|
|
143
|
+
gn:prefix "";
|
|
144
|
+
gn:queryPattern """?inst ${dataLabelProperty} ?search1
|
|
145
|
+
FILTER regex(COALESCE(str(?search1)), \"${text}\", \"i\")
|
|
146
|
+
BIND(0 as ?score)
|
|
147
|
+
""";
|
|
148
|
+
gn:extractLabel true
|
|
149
|
+
] .
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphdb-workbench-tests",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-TR16",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "graphdb-workbench-tests",
|
|
9
|
-
"version": "4.0.0-
|
|
9
|
+
"version": "4.0.0-TR16",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"devDependencies": {
|
|
12
12
|
"@bahmutov/cypress-code-coverage": "^2.7.2",
|
package/package.json
CHANGED
package/steps/error-steps.js
CHANGED
|
@@ -44,6 +44,20 @@ export class GraphNavigatorSteps extends BaseSteps {
|
|
|
44
44
|
return GraphNavigatorSteps.getCanvas().find(`[data-element-id]`).contains(text).first();
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
static getSearchInput() {
|
|
48
|
+
return GraphNavigatorSteps.getComponent().find('.reactodia-unified-search__search-input');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static getSearchSectionTab(name) {
|
|
52
|
+
return GraphNavigatorSteps.getComponent().find('.reactodia-unified-search__section-tab').contains(name);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static searchEntities(text) {
|
|
56
|
+
GraphNavigatorSteps.getSearchInput().click();
|
|
57
|
+
GraphNavigatorSteps.getSearchSectionTab('Entities').click();
|
|
58
|
+
GraphNavigatorSteps.getSearchInput().clear().type(`${text}{enter}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
47
61
|
static getSettingsButton() {
|
|
48
62
|
return cy.get('[data-test="graph-navigator-settings-btn"]');
|
|
49
63
|
}
|
|
@@ -73,6 +87,14 @@ export class GraphNavigatorSteps extends BaseSteps {
|
|
|
73
87
|
return GraphNavigatorSteps.getSettingsPopover().contains(fileName);
|
|
74
88
|
}
|
|
75
89
|
|
|
90
|
+
static getUploadErrors() {
|
|
91
|
+
return this.getByTestId('graph-navigator-settings-upload-errors');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static getUploadError(property) {
|
|
95
|
+
return GraphNavigatorSteps.getUploadErrors().contains('[data-test="graph-navigator-settings-upload-error"]', property);
|
|
96
|
+
}
|
|
97
|
+
|
|
76
98
|
static getUploadButton() {
|
|
77
99
|
return GraphNavigatorSteps.getSettingsPopover().find('.p-fileupload-upload-button');
|
|
78
100
|
}
|
|
@@ -25,6 +25,10 @@ export class OntopRepositorySteps {
|
|
|
25
25
|
OntopRepositorySteps.getOBDAFileFieldEditButton().click();
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
static getFileContentEditor() {
|
|
29
|
+
return cy.getByTestId('repository-file-content');
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
static getOntologyFileField() {
|
|
29
33
|
return cy.get('div').contains("Ontology file");
|
|
30
34
|
}
|
|
@@ -190,7 +190,7 @@ export class AclManagementSteps {
|
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
static getWarningIcon(index) {
|
|
193
|
-
return this.getSavedRoleField(index).
|
|
193
|
+
return this.getSavedRoleField(index).find('.ri-alert-line');
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
static getWarningIconTooltipText(index) {
|
package/steps/toaster-steps.js
CHANGED
|
@@ -7,8 +7,12 @@ export class RepositoryErrorsWidgetSteps {
|
|
|
7
7
|
return RepositoryErrorsWidgetSteps.getWidget().find('.create-repository-btn');
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
static
|
|
11
|
-
return RepositoryErrorsWidgetSteps.getWidget().
|
|
10
|
+
static getRepositoryFilter() {
|
|
11
|
+
return RepositoryErrorsWidgetSteps.getWidget().getByTestId('core-errors-repository-filter');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static getLocalOnlyCheckbox() {
|
|
15
|
+
return RepositoryErrorsWidgetSteps.getWidget().getByTestId('core-errors-local-only-checkbox');
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
static getInfoMessage() {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {Stubs} from './stubs';
|
|
2
|
+
|
|
3
|
+
export class GraphNavigatorStubs extends Stubs {
|
|
4
|
+
/**
|
|
5
|
+
* Makes the full-text search of the Graph Navigator settings use the GraphDB autocomplete index.
|
|
6
|
+
*/
|
|
7
|
+
static stubSettingsWithAutocomplete() {
|
|
8
|
+
cy.intercept('GET', '/rest/repositories/*/graph-navigator/settings', (req) => {
|
|
9
|
+
req.continue((res) => {
|
|
10
|
+
res.body.fullTextSearch.prefix = 'PREFIX auto: <http://www.ontotext.com/plugins/autocomplete#>';
|
|
11
|
+
});
|
|
12
|
+
}).as('graph-navigator-settings');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Aliases the SPARQL requests that look up entities by the given text as `entity-lookup`.
|
|
17
|
+
*/
|
|
18
|
+
static spyEntityLookup(text) {
|
|
19
|
+
cy.intercept('POST', '/repositories/*', (req) => {
|
|
20
|
+
// The body is form-encoded (`query=...`), so decode it to match the SPARQL text.
|
|
21
|
+
const body = new URLSearchParams(String(req.body)).get('query') ?? '';
|
|
22
|
+
if (body.includes('SELECT ?inst ?class ?label WHERE') && body.includes(text)) {
|
|
23
|
+
req.alias = 'entity-lookup';
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|