graphdb-workbench-tests 4.0.0-TR5 → 4.0.0-TR7

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.
Files changed (35) hide show
  1. package/e2e-flaky/import/import-server-files-operations.spec.js +1 -23
  2. package/e2e-legacy/cluster/cluster-configuration/cluster-configuration-multi-region.spec.js +7 -0
  3. package/e2e-legacy/cluster/edit-cluster-nodes-modal.spec.js +1 -1
  4. package/e2e-legacy/explore/visual-graph/visual.graph.spec.js +35 -4
  5. package/e2e-legacy/import/import-server-files.spec.js +3 -5
  6. package/e2e-legacy/import/import-user-data-text-snippet.spec.js +0 -39
  7. package/e2e-legacy/import/import-user-data-url.spec.js +6 -3
  8. package/e2e-legacy/rdf-version/rdf-version-accept-header.spec.js +145 -0
  9. package/e2e-legacy/reactodia/reactodia.spec.js +122 -0
  10. package/e2e-legacy/resource/resource.spec.js +176 -39
  11. package/e2e-legacy/setup/aclmanagement/create-rule.spec.js +14 -25
  12. package/e2e-legacy/setup/aclmanagement/delete-rule.spec.js +6 -6
  13. package/e2e-legacy/setup/aclmanagement/edit-rule.spec.js +15 -15
  14. package/e2e-legacy/setup/aclmanagement/render-rules.spec.js +1 -1
  15. package/e2e-legacy/setup/aclmanagement/reorder-rules.spec.js +2 -2
  16. package/e2e-legacy/setup/aclmanagement/revert-rules.spec.js +2 -2
  17. package/e2e-legacy/setup/aclmanagement/update-rules.spec.js +3 -3
  18. package/e2e-legacy/setup/aclmanagement/validate-uri.spec.js +152 -0
  19. package/e2e-legacy/setup/users-and-access/user-and-access.spec.js +1 -1
  20. package/e2e-legacy/sparql-editor/yasr/download-as.spec.js +4 -7
  21. package/e2e-security/setup/users-and-access/user-and-access.spec.js +0 -1
  22. package/fixtures/cluster/cluster-config-with-tag.json +17 -0
  23. package/fixtures/graphdb-import/wine.rdf +279 -285
  24. package/npm-shrinkwrap.json +2 -2
  25. package/package.json +1 -1
  26. package/steps/error-steps.js +1 -1
  27. package/steps/import/import-test-constants.js +1 -1
  28. package/steps/main-menu-steps.js +9 -0
  29. package/steps/reactodia-steps.js +42 -0
  30. package/steps/resource/resource-steps.js +72 -5
  31. package/steps/setup/acl-management-steps.js +3 -23
  32. package/stubs/cluster/cluster-stubs.js +7 -0
  33. package/fixtures/graphdb-import/test-trigstar.trigs +0 -32
  34. package/fixtures/graphdb-import/test_turtlestar.ttls +0 -6
  35. package/fixtures/graphdb-import/turtlestar-data.ttls +0 -77
@@ -9,8 +9,6 @@ describe('Import server files - Operations', () => {
9
9
  const CONTEXT = 'http://example.org/context';
10
10
  const FILE_FOR_IMPORT = 'italian_public_schools_links.nt.gz';
11
11
  const FILE_FROM_DIRECTORY_FOR_IMPORT = 'rdfxml.rdf';
12
- const TTLS_FOR_IMPORT = 'test_turtlestar.ttls';
13
- const TRIGS_FOR_IMPORT = 'test-trigstar.trigs';
14
12
  const JSONLD_FILE_FOR_IMPORT = '0007-import-file.jsonld';
15
13
  const JSONLD_CONTEXT = 'https://w3c.github.io/json-ld-api/tests/compact/0007-context.jsonld';
16
14
 
@@ -18,7 +16,7 @@ describe('Import server files - Operations', () => {
18
16
  repositoryId = 'server-import-' + Date.now();
19
17
  cy.createRepository({id: repositoryId});
20
18
  ImportServerFilesSteps.visitServerImport(repositoryId);
21
- ImportServerFilesSteps.getResources().should('have.length', 18);
19
+ ImportServerFilesSteps.getResources().should('have.length', 17);
22
20
  });
23
21
 
24
22
  afterEach(() => {
@@ -119,24 +117,4 @@ describe('Import server files - Operations', () => {
119
117
  // Then Import status of the file should not be visible
120
118
  ImportServerFilesSteps.getResourceStatus(FILE_FROM_DIRECTORY_FOR_IMPORT).should('be.hidden');
121
119
  });
122
-
123
- it('Should import turtlestar from Server files successfully without changing settings', () => {
124
- // Given I have opened the server files tab
125
- ImportServerFilesSteps.importResourceByName(TTLS_FOR_IMPORT);
126
- // When I select to import a ttl file without changing settings
127
- ImportSettingsDialogSteps.import();
128
- // Then I should see the file imported successfully
129
- ImportServerFilesSteps.checkImportedResourceByIndex(0, TTLS_FOR_IMPORT);
130
- // ImportSteps.verifyImportStatusDetails(TTLS_FOR_IMPORT, '"preserveBNodeIds": false,');
131
- });
132
-
133
- it('Should import trigstar from Server files successfully without changing settings', () => {
134
- // Given I have opened the server files tab
135
- ImportServerFilesSteps.importResourceByName(TRIGS_FOR_IMPORT);
136
- // When I select to import a trigstar file without changing settings
137
- ImportSettingsDialogSteps.import();
138
- // Then I should see the file imported successfully
139
- ImportServerFilesSteps.checkImportedResourceByIndex(0, TRIGS_FOR_IMPORT);
140
- // ImportSteps.verifyImportStatusDetails(TRIGS_FOR_IMPORT, '"preserveBNodeIds": false,');
141
- });
142
120
  });
@@ -42,7 +42,9 @@ describe('Cluster configuration', () => {
42
42
  });
43
43
 
44
44
  ClusterStubs.stubClusterGroupStatusWithTag();
45
+ ClusterStubs.stubClusterConfigWithTag();
45
46
  cy.wait('@3-nodes-cluster-group-status-tag');
47
+ cy.wait('@cluster-config-with-tag');
46
48
  // Assert the tags table contains the expected tag
47
49
  ClusterConfigurationSteps.getTagsTable().should('be.visible');
48
50
  ClusterConfigurationSteps.getTagsTableRows().should('contain.text', tagName);
@@ -62,6 +64,11 @@ describe('Cluster configuration', () => {
62
64
  cy.wait('@delete-tag').then((interception) => {
63
65
  expect(interception.request.body).to.deep.equal({tag: tagName});
64
66
  });
67
+ ClusterStubs.stubClusterGroupStatus();
68
+ ClusterStubs.stubClusterConfig();
69
+ cy.wait('@3-nodes-cluster-group-status');
70
+ cy.wait('@cluster-config');
71
+ ClusterConfigurationSteps.getTagsTable().should('not.exist');
65
72
  });
66
73
 
67
74
  it('should show an alert when there is no elected leader in the cluster', () => {
@@ -460,7 +460,7 @@ describe('Cluster management', () => {
460
460
  "verificationTimeout": 1500,
461
461
  "transactionLogMaximumSizeGB": 50.0,
462
462
  "batchUpdateInterval": 5000,
463
- "nodes": ['http://pc-desktop:7200', 'http://pc-desktop:7203']
463
+ "nodes": ['http://pc-desktop:7200', 'http://pc-desktop:7203'],
464
464
  });
465
465
  });
466
466
  // And expect success message to be displayed.
@@ -8,6 +8,19 @@ import HomeSteps from '../../../steps/home-steps.js';
8
8
  const FILE_TO_IMPORT = 'wine.rdf';
9
9
  const VALID_RESOURCE = 'USRegion';
10
10
 
11
+ /**
12
+ * Updates the links limit and waits for the graph reload it triggers to complete.
13
+ *
14
+ * @param {string} value the new links limit
15
+ */
16
+ function updateLinksLimit(value) {
17
+ VisualGraphSteps.updateLinksLimitField(value);
18
+ VisualGraphSteps.getLinksNumberField().should('have.value', value);
19
+ VisualGraphSteps.getUrl().should('match', new RegExp(`[?&]linksLimit=${value}(&|$)`));
20
+ VisualGraphSteps.getGraphVisualizationPane().should('be.visible');
21
+ VisualGraphSteps.getNodes();
22
+ }
23
+
11
24
  describe('Visual graph screen validation', () => {
12
25
 
13
26
  let repositoryId;
@@ -311,6 +324,20 @@ describe('Visual graph screen validation', () => {
311
324
  VisualGraphSteps.getPredicates().should('have.length', 36);
312
325
  });
313
326
 
327
+ it('Should close the settings panel when navigating away from the graph', () => {
328
+ // Given I have opened a graph
329
+ VisualGraphSteps.openUSRegionUri();
330
+ // And I have opened the visual graph settings
331
+ VisualGraphSteps.openVisualGraphSettings();
332
+ VisualGraphSteps.getSettingsPanel().should('be.visible');
333
+
334
+ // When I click the visual graph submenu
335
+ MainMenuSteps.clickOnSubmenuVisualGraph();
336
+
337
+ // Then I expect the settings panel to be closed
338
+ VisualGraphSteps.getSettingsPanel().should('not.exist');
339
+ });
340
+
314
341
  it('Test include inferred Statements', () => {
315
342
  VisualGraphSteps.openUSRegionUri();
316
343
  // Check include inferred
@@ -361,9 +388,11 @@ describe('Visual graph screen validation', () => {
361
388
  // Pick a type that is displayed in the diagram for example "vin:Zinfandel"
362
389
  VisualGraphSteps.getNodes().and('contain', 'Zinfandel');
363
390
 
391
+ // Set the connections limit to 10 and wait for the graph reload it triggers,
392
+ // so that the settings are opened after the navigation has completed
393
+ updateLinksLimit('10');
394
+
364
395
  VisualGraphSteps.openVisualGraphSettings();
365
- // Set the connections limit to 10
366
- VisualGraphSteps.updateLinksLimitField('10');
367
396
  // Go to Settings and set "vin:Zinfandel" as an ignored type
368
397
  VisualGraphSteps.getIgnoredTypesField().clear().type('vin:Zinfandel').type('{enter}');
369
398
 
@@ -395,12 +424,14 @@ describe('Visual graph screen validation', () => {
395
424
  // Pick a type that is displayed in the diagram for example "vin:Zinfandel"
396
425
  VisualGraphSteps.getPredicates().should('contain', 'hasSugar');
397
426
 
427
+ // Set the connections limit to 10 and wait for the graph reload it triggers,
428
+ // so that the settings are opened after the navigation has completed
429
+ updateLinksLimit('10');
430
+
398
431
  VisualGraphSteps.openVisualGraphSettings();
399
432
  // Go to predicates tab
400
433
  VisualGraphSteps.openPredicatesTab();
401
434
 
402
- // Set the connections limit to 10
403
- VisualGraphSteps.updateLinksLimitField('10');
404
435
  // Set "vin:hasSugar" as an ignored predicate
405
436
  VisualGraphSteps.getIgnoredPredicatesField().clear().type('vin:hasSugar').type('{enter}');
406
437
 
@@ -165,8 +165,7 @@ describe('Import server files', () => {
165
165
  ImportServerFilesSteps.getResourceTitleRow(6).should('contain', "import-resource-with-long-error.rdf");
166
166
  // checks files in root
167
167
  ImportServerFilesSteps.getResourceTitleRow(7).should('contain', "bnodes.ttl");
168
- ImportServerFilesSteps.getResourceTitleRow(8).should('contain', "test_turtlestar.ttls");
169
- ImportServerFilesSteps.getResourceTitleRow(9).should('contain', "0007-import-file.jsonld");
168
+ ImportServerFilesSteps.getResourceTitleRow(8).should('contain', "0007-import-file.jsonld");
170
169
 
171
170
  // When I change the order by size.
172
171
  ImportServerFilesSteps.orderBySize();
@@ -182,9 +181,8 @@ describe('Import server files', () => {
182
181
  ImportServerFilesSteps.getResourceTitleRow(5).should('contain', "rdfxml.rdf");
183
182
  ImportServerFilesSteps.getResourceTitleRow(6).should('contain', "jsonld-file.jsonld");
184
183
  // checks files in root
185
- ImportServerFilesSteps.getResourceTitleRow(17).should('contain', "0007-import-file.jsonld");
186
- ImportServerFilesSteps.getResourceTitleRow(18).should('contain', "test_turtlestar.ttls");
187
- ImportServerFilesSteps.getResourceTitleRow(19).should('contain', "bnodes.ttl");
184
+ ImportServerFilesSteps.getResourceTitleRow(15).should('contain', "0007-import-file.jsonld");
185
+ ImportServerFilesSteps.getResourceTitleRow(16).should('contain', "bnodes.ttl");
188
186
  });
189
187
 
190
188
  it('should allow importing jsonld with empty "JSON-LD Context"', () => {
@@ -21,25 +21,6 @@ describe('Import user data: Text snippet', () => {
21
21
  'ab:richard ab:email "richard49@hotmail.com".\n' +
22
22
  'ab:richard ab:email "richard491@hotmail.com".';
23
23
 
24
- const TURTLESTAR_SNIPPET = '@prefix ex:<http:/base.org/> .\n' +
25
- 'ex:foo ex:pred ex:obj .\n' +
26
- '<<ex:foo rdfs:label "label">> ex:author "guest" .\n' +
27
- 'ex:obj ex:quote <<ex:meta ex:data ex:foo>> .\n' +
28
- '<<<<ex:foo rdfs:label "label">> ex:data ex:foo>> ex:recursive true .';
29
-
30
- const TRIGSTAR_SNIPPET = '@prefix ex: <http://example.com/> .\n' +
31
- '@prefix dct: <http://purl.org/dc/terms/> .\n' +
32
- '@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n' +
33
- '@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n' +
34
- 'graph ex:rdfstar {\n' +
35
- ' ex:bob foaf:knows << ex:alice foaf:knows<<ex:bob dct:created ex:book>> >> .\n' +
36
- ' <<<< ex:bob dct:created ex:book >> foaf:knows ex:alice >> dct:source ex:otherbook .\n' +
37
- ' ex:bobshomepage dct:source<< ex:book dct:creator ex:alice >> .\n' +
38
- ' << ex:book dct:creator ex:alice >> dct:source ex:bobshomepage .\n' +
39
- ' << ex:book dct:creator ex:alice >> dct:requires << ex:alice dct:created ex:book >> .\n' +
40
- ' <<<http://example.org/a>ex:b ex:c>>ex:valid "1999-08-16"^^xsd:date .\n' +
41
- '}';
42
-
43
24
  const JSONLD_TEXT_SNIPPET = '[\n' +
44
25
  ' {\n' +
45
26
  ' "@id": "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property",\n' +
@@ -55,8 +36,6 @@ describe('Import user data: Text snippet', () => {
55
36
  const CONTEXT = 'http://example.org/graph';
56
37
  const TEXT_SNIPPET = 'Text snippet';
57
38
  const JSONLD_FORMAT = 'JSON-LD';
58
- const VALID_SNIPPET_TURTLESTAR_FORMAT = 'Turtle*';
59
- const VALID_SNIPPET_TRIGSTAR_FORMAT = 'TriG*';
60
39
  const VALID_SNIPPET_RDF_FORMAT = 'Turtle';
61
40
  const RDF_ERROR_MESSAGE = 'RDF Parse Error:';
62
41
 
@@ -96,24 +75,6 @@ describe('Import user data: Text snippet', () => {
96
75
  ImportUserDataSteps.checkImportedResourceByIndex(0, TEXT_SNIPPET);
97
76
  });
98
77
 
99
- it('Should import Turtle* text snippet successfully with valid RDF star format selected', () => {
100
- ImportUserDataSteps.openImportTextSnippetDialog();
101
- ImportUserDataSteps.fillRDFTextSnippet(TURTLESTAR_SNIPPET);
102
- ImportUserDataSteps.selectRDFFormat(VALID_SNIPPET_TURTLESTAR_FORMAT);
103
- ImportUserDataSteps.clickImportTextSnippetButton();
104
- ImportSettingsDialogSteps.import();
105
- ImportUserDataSteps.checkImportedResourceByIndex(0, TEXT_SNIPPET);
106
- });
107
-
108
- it('Should import TriG* text snippet successfully with valid RDF star format selected', () => {
109
- ImportUserDataSteps.openImportTextSnippetDialog();
110
- ImportUserDataSteps.fillRDFTextSnippet(TRIGSTAR_SNIPPET);
111
- ImportUserDataSteps.selectRDFFormat(VALID_SNIPPET_TRIGSTAR_FORMAT);
112
- ImportUserDataSteps.clickImportTextSnippetButton();
113
- ImportSettingsDialogSteps.import();
114
- ImportUserDataSteps.checkImportedResourceByIndex(0, TEXT_SNIPPET);
115
- });
116
-
117
78
  it('Should import RDF text snippet successfully with filled base URI and context', () => {
118
79
  ImportUserDataSteps.openImportTextSnippetDialog();
119
80
  ImportUserDataSteps.fillRDFTextSnippet(RDF_TEXT_SNIPPET_2);
@@ -54,7 +54,8 @@ describe('Import user data: URL import', () => {
54
54
  });
55
55
 
56
56
 
57
- it('Test import file via URL successfully with Auto format selected', () => {
57
+ // FIXME: wine.rdf contains DOCTYPE which is forbidden in the TR for GDB 12
58
+ it.skip('Test import file via URL successfully with Auto format selected', () => {
58
59
  ImportUserDataSteps.openImportURLDialog(IMPORT_URL);
59
60
  ImportUserDataSteps.clickImportUrlButton();
60
61
  // Without changing settings
@@ -62,7 +63,8 @@ describe('Import user data: URL import', () => {
62
63
  ImportUserDataSteps.checkImportedResourceByIndex(0, IMPORT_URL);
63
64
  });
64
65
 
65
- it('Test import file via URL with invalid RDF format selected', () => {
66
+ // FIXME: wine.rdf contains DOCTYPE which is forbidden in the TR for GDB 12. Expected error message is different.
67
+ it.skip('Test import file via URL with invalid RDF format selected', () => {
66
68
  ImportUserDataSteps.openImportURLDialog(IMPORT_URL);
67
69
  ImportUserDataSteps.selectRDFFormat(JSONLD_FORMAT);
68
70
  ImportUserDataSteps.clickImportUrlButton();
@@ -70,7 +72,8 @@ describe('Import user data: URL import', () => {
70
72
  ImportUserDataSteps.checkImportedResourceByIndex(0, IMPORT_URL, RDF_ERROR_MESSAGE);
71
73
  });
72
74
 
73
- it('Test import file via URL successfully with valid RDF format selected', () => {
75
+ // FIXME: wine.rdf contains DOCTYPE which is forbidden in the TR for GDB 12
76
+ it.skip('Test import file via URL successfully with valid RDF format selected', () => {
74
77
  ImportUserDataSteps.openImportURLDialog(IMPORT_URL);
75
78
  ImportUserDataSteps.selectRDFFormat(VALID_URL_RDF_FORMAT);
76
79
  ImportUserDataSteps.clickImportUrlButton();
@@ -0,0 +1,145 @@
1
+ import {SparqlEditorSteps} from "../../steps/sparql-editor-steps";
2
+ import {YasguiSteps} from "../../steps/yasgui/yasgui-steps";
3
+ import {YasqeSteps} from "../../steps/yasgui/yasqe-steps";
4
+ import {YasrSteps} from "../../steps/yasgui/yasr-steps";
5
+ import {QueryStubs} from "../../stubs/yasgui/query-stubs";
6
+ import {GraphsOverviewSteps} from "../../steps/explore/graphs-overview-steps";
7
+ import {JsonLdModalSteps} from "../../steps/json-ld-modal-steps";
8
+
9
+ // The workbench requests RDF 1.2 by adding the "version" media type parameter to the Accept header.
10
+ // The parameter must be present on every RDF media range and must precede the weight ("q"),
11
+ // because anything after the weight is not a media type parameter.
12
+ const SELECT_QUERY_ACCEPT = 'application/x-sparqlstar-results+json;version=1.2, application/sparql-results+json;version=1.2;q=0.9, */*;version=1.2;q=0.8';
13
+ const CONSTRUCT_QUERY_ACCEPT = 'application/x-graphdb-table-results+json;version=1.2, application/rdf+json;version=1.2;q=0.9, */*;version=1.2;q=0.8';
14
+ const JSONLD_EXPANDED_ACCEPT = 'application/ld+json;profile=http://www.w3.org/ns/json-ld#expanded;version=1.2';
15
+
16
+ describe('RDF version in the Accept header', () => {
17
+ let repositoryId;
18
+
19
+ afterEach(() => {
20
+ cy.deleteRepository(repositoryId);
21
+ });
22
+
23
+ describe('SPARQL editor', () => {
24
+ beforeEach(() => {
25
+ repositoryId = 'rdf-version-sparql-' + Date.now();
26
+ QueryStubs.stubQueryCountResponse();
27
+ cy.createRepository({id: repositoryId});
28
+ cy.presetRepository(repositoryId);
29
+ QueryStubs.stubDefaultQueryResponse(repositoryId);
30
+
31
+ SparqlEditorSteps.visitSparqlEditorPage();
32
+ YasguiSteps.getYasgui().should('be.visible');
33
+ });
34
+
35
+ it('should request RDF 1.2 when executing a SELECT query', () => {
36
+ // Given I am about to execute the default SELECT query
37
+ cy.intercept('POST', `/repositories/${repositoryId}`).as('query');
38
+
39
+ // When I execute it
40
+ YasqeSteps.executeQuery();
41
+
42
+ // Then every media range of the Accept header should request RDF 1.2
43
+ verifyAcceptHeader('@query', SELECT_QUERY_ACCEPT);
44
+ });
45
+
46
+ it('should request RDF 1.2 when executing a CONSTRUCT query', () => {
47
+ // Given I am about to execute a CONSTRUCT query
48
+ cy.intercept('POST', `/repositories/${repositoryId}`).as('query');
49
+
50
+ // When I execute it
51
+ pasteAndExecuteConstructQuery();
52
+
53
+ // Then every media range of the Accept header should request RDF 1.2
54
+ verifyAcceptHeader('@query', CONSTRUCT_QUERY_ACCEPT);
55
+ });
56
+
57
+ it('should request RDF 1.2 when downloading SELECT results', () => {
58
+ // Given I have executed a SELECT query
59
+ YasqeSteps.executeQuery();
60
+ cy.intercept('POST', `/repositories/${repositoryId}`).as('download');
61
+
62
+ // When I download the results as XML
63
+ YasrSteps.openDownloadAsDropdown();
64
+ YasrSteps.selectDownloadAsOption(1);
65
+
66
+ // Then the download request should ask for RDF 1.2
67
+ verifyAcceptHeader('@download', 'application/sparql-results+xml;version=1.2');
68
+ });
69
+
70
+ it('should request RDF 1.2 when downloading CONSTRUCT results as JSON-LD', () => {
71
+ // Given I have executed a CONSTRUCT query
72
+ pasteAndExecuteConstructQuery();
73
+ cy.intercept('POST', `/repositories/${repositoryId}`).as('download');
74
+
75
+ // When I download the results as JSON-LD with the default settings
76
+ YasrSteps.openDownloadAsDropdown();
77
+ YasrSteps.selectDownloadAsOption(1);
78
+ JsonLdModalSteps.clickExportJSONLD();
79
+
80
+ // Then the version should follow the JSON-LD profile
81
+ verifyAcceptHeader('@download', JSONLD_EXPANDED_ACCEPT);
82
+ });
83
+ });
84
+
85
+ describe('Graphs overview', () => {
86
+ beforeEach(() => {
87
+ repositoryId = 'rdf-version-graphs-' + Date.now();
88
+ cy.createRepository({id: repositoryId});
89
+ cy.presetRepository(repositoryId);
90
+ cy.importRDFTextSnippet(repositoryId, '<urn:s> <urn:p> <urn:o> .');
91
+
92
+ GraphsOverviewSteps.visit();
93
+ GraphsOverviewSteps.getResults().should('have.length.at.least', 1);
94
+ });
95
+
96
+ it('should request RDF 1.2 when exporting the repository', () => {
97
+ // Given the export opens the download URL in a new window
98
+ cy.window().then((win) => {
99
+ cy.stub(win, 'open').returns({closed: true}).as('windowOpen');
100
+ });
101
+
102
+ // When I export the repository as TriG
103
+ GraphsOverviewSteps.exportRepository();
104
+ cy.get('.export-repo-format-TriG').eq(0).click();
105
+
106
+ // Then the Accept parameter of the download URL should request RDF 1.2
107
+ cy.get('@windowOpen').should('have.been.calledOnce')
108
+ .its('firstCall.args.0')
109
+ .should('contain', '&Accept=' + encodeURIComponent('application/x-trig;version=1.2'));
110
+ });
111
+
112
+ it('should request RDF 1.2 when exporting the repository as JSON-LD', () => {
113
+ // Given I am about to export the repository
114
+ cy.intercept({method: 'GET', pathname: `/repositories/${repositoryId}/statements`}).as('export');
115
+
116
+ // When I export it as JSON-LD with the default settings
117
+ GraphsOverviewSteps.exportRepository();
118
+ GraphsOverviewSteps.selectJSONLDOption();
119
+ JsonLdModalSteps.clickExportJSONLD();
120
+
121
+ // Then the version should follow the JSON-LD profile
122
+ verifyAcceptHeader('@export', JSONLD_EXPANDED_ACCEPT);
123
+ });
124
+
125
+ it('should request RDF 1.2 when downloading all graphs', () => {
126
+ // Given I am about to download all graphs
127
+ cy.intercept({method: 'GET', pathname: `/repositories/${repositoryId}/contexts`}).as('downloadGraphs');
128
+
129
+ // When I download them
130
+ GraphsOverviewSteps.clickOnDownloadAllButton();
131
+
132
+ // Then RDF 1.2 should be requested for every media range except JSON
133
+ verifyAcceptHeader('@downloadGraphs', 'application/json, text/plain;version=1.2, */*;version=1.2');
134
+ });
135
+ });
136
+ });
137
+
138
+ function verifyAcceptHeader(alias, expectedAccept) {
139
+ cy.wait(alias).its('request.headers.accept').should('equal', expectedAccept);
140
+ }
141
+
142
+ function pasteAndExecuteConstructQuery() {
143
+ YasqeSteps.pasteQuery('CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }');
144
+ YasqeSteps.executeQuery();
145
+ }
@@ -0,0 +1,122 @@
1
+ import {ReactodiaSteps} from '../../steps/reactodia-steps.js';
2
+ import {LanguageSelectorSteps} from '../../steps/language-selector-steps.js';
3
+ import {RepositorySelectorSteps} from '../../steps/repository-selector-steps.js';
4
+ import {MainMenuSteps} from '../../steps/main-menu-steps.js';
5
+
6
+ const FILE_TO_IMPORT = 'resource-test-data.ttl';
7
+ const SEED_RESOURCE_ENCODED = 'http:%2F%2Fexample.com%2Fontology%23CustomerLoyalty';
8
+ const SEED_RESOURCE_LABEL = 'CustomerLoyalty';
9
+
10
+ const CONSTRUCT_QUERY = 'CONSTRUCT { <http://example.com/ontology#CustomerLoyalty> ?p ?o } WHERE { <http://example.com/ontology#CustomerLoyalty> ?p ?o }';
11
+ const CONSTRUCT_TARGET_LABEL = 'Metric';
12
+
13
+ describe('Reactodia graph explorer', () => {
14
+ let repositoryId;
15
+
16
+ beforeEach(() => {
17
+ repositoryId = 'repository-' + Date.now();
18
+ cy.createRepository({id: repositoryId});
19
+ cy.presetRepository(repositoryId);
20
+ cy.importServerFile(repositoryId, FILE_TO_IMPORT);
21
+ });
22
+
23
+ afterEach(() => {
24
+ cy.deleteRepository(repositoryId);
25
+ });
26
+
27
+ it('should mount the reactodia workspace when a repository is active', () => {
28
+ // Given I open the reactodia view without a start resource.
29
+ ReactodiaSteps.visit();
30
+
31
+ // Then I expect the reactodia workspace and its canvas to be rendered.
32
+ ReactodiaSteps.getWorkspace().should('exist');
33
+ ReactodiaSteps.getCanvas().should('exist');
34
+
35
+ // And I expect the canvas to start empty because no start resource was provided.
36
+ ReactodiaSteps.getElements().should('not.exist');
37
+ });
38
+
39
+ it('should place the start resource on the canvas as a seed', () => {
40
+ // Given I open the reactodia view with a start resource.
41
+ ReactodiaSteps.visit(SEED_RESOURCE_ENCODED);
42
+
43
+ // Then I expect the start resource to be placed on the canvas as a seed element.
44
+ ReactodiaSteps.getElements().should('have.length', 1);
45
+ ReactodiaSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
46
+ });
47
+
48
+ it('should seed the canvas with the graph computed from a CONSTRUCT query', () => {
49
+ // Given I open the reactodia view with a CONSTRUCT query, as sent from the SPARQL editor.
50
+ ReactodiaSteps.visitWithQuery(CONSTRUCT_QUERY);
51
+
52
+ // Then I expect the computed graph to be seeded on the canvas: the subject and its related resource.
53
+ ReactodiaSteps.getElements().should('have.length', 2);
54
+ ReactodiaSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
55
+ ReactodiaSteps.getElement(CONSTRUCT_TARGET_LABEL).should('exist');
56
+ });
57
+
58
+ it('should keep the displayed resources when the language is switched', () => {
59
+ // Given the reactodia view is opened with a start resource that gets seeded on the canvas.
60
+ ReactodiaSteps.visit(SEED_RESOURCE_ENCODED);
61
+ ReactodiaSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
62
+ ReactodiaSteps.getElements().should('have.length', 1);
63
+
64
+ // When I switch the language.
65
+ LanguageSelectorSteps.switchToFr();
66
+
67
+ // Then I expect the same resources to remain visible because the layout is carried across the remount.
68
+ ReactodiaSteps.getElements().should('have.length', 1);
69
+ ReactodiaSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
70
+ });
71
+
72
+ it('should keep the diagram on refresh but clear it when navigating away and back', () => {
73
+ // Given the reactodia view is opened with a start resource that gets seeded on the canvas.
74
+ ReactodiaSteps.visit(SEED_RESOURCE_ENCODED);
75
+ ReactodiaSteps.getElements().should('have.length', 1);
76
+ ReactodiaSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
77
+
78
+ // When I refresh the page.
79
+ cy.reload();
80
+
81
+ // Then I expect the diagram state to be preserved across the refresh.
82
+ ReactodiaSteps.getElements().should('have.length', 1);
83
+ ReactodiaSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
84
+
85
+ // When I navigate to another view via the navigation bar.
86
+ MainMenuSteps.clickOnSparqlMenu();
87
+ ReactodiaSteps.getComponent().should('not.exist');
88
+
89
+ // And I return to the reactodia view via the navigation bar.
90
+ MainMenuSteps.clickOnReactodia();
91
+
92
+ // Then I expect the canvas to be cleared, because leaving the view drops the persisted diagram state.
93
+ ReactodiaSteps.getWorkspace().should('exist');
94
+ ReactodiaSteps.getElements().should('not.exist');
95
+ });
96
+
97
+ describe('Repository switch', () => {
98
+ let secondRepositoryId;
99
+
100
+ beforeEach(() => {
101
+ secondRepositoryId = 'repository-second-' + Date.now();
102
+ cy.createRepository({id: secondRepositoryId});
103
+ });
104
+
105
+ afterEach(() => {
106
+ cy.deleteRepository(secondRepositoryId);
107
+ });
108
+
109
+ it('should clear the canvas when the repository is switched', () => {
110
+ // Given the reactodia view is opened with a start resource that gets seeded on the canvas.
111
+ ReactodiaSteps.visit(SEED_RESOURCE_ENCODED);
112
+ ReactodiaSteps.getElements().should('have.length', 1);
113
+
114
+ // When I switch to another repository.
115
+ RepositorySelectorSteps.selectRepository(secondRepositoryId);
116
+
117
+ // Then I expect the workspace to still be mounted, but the canvas to be cleared.
118
+ ReactodiaSteps.getWorkspace().should('exist');
119
+ ReactodiaSteps.getElements().should('not.exist');
120
+ });
121
+ });
122
+ });