graphdb-workbench-tests 3.5.1 → 4.0.0-SPARQL12-TEST-FIX

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 (45) hide show
  1. package/cypress-guides.config.js +45 -0
  2. package/e2e-flaky/import/import-server-files-operations.spec.js +8 -30
  3. package/e2e-flaky/import/import-user-data-batch-operations.spec.js +7 -7
  4. package/e2e-flaky/import/import-user-data-url.spec.js +1 -1
  5. package/e2e-legacy/explore/visual-graph/visual.graph.spec.js +35 -4
  6. package/e2e-legacy/guides/import-rdf-file/confirm-duplicate-rdf-file.spec.js +1 -1
  7. package/e2e-legacy/guides/main-menu/main-menu-guide.spec.js +6 -14
  8. package/e2e-legacy/guides/ttyg/configure-agent/configure-agent-guide.spec.js +27 -32
  9. package/e2e-legacy/guides/ttyg/edit-agent/edit-ttyg-agent-guide.spec.js +12 -20
  10. package/e2e-legacy/import/import-server-files-batch-operations.spec.js +5 -5
  11. package/e2e-legacy/import/import-server-files.spec.js +21 -23
  12. package/e2e-legacy/import/import-user-data-file-upload.spec.js +21 -22
  13. package/e2e-legacy/import/import-user-data-text-snippet.spec.js +6 -45
  14. package/e2e-legacy/import/import-user-data-url.spec.js +9 -6
  15. package/e2e-legacy/import/import-view.spec.js +2 -2
  16. package/e2e-legacy/repository/rename-repository-restrictions.spec.js +129 -0
  17. package/e2e-legacy/repository/repositories.spec.js +3 -3
  18. package/e2e-legacy/resource/resource.spec.js +157 -33
  19. package/e2e-legacy/setup/aclmanagement/create-rule.spec.js +14 -25
  20. package/e2e-legacy/setup/aclmanagement/delete-rule.spec.js +6 -6
  21. package/e2e-legacy/setup/aclmanagement/edit-rule.spec.js +15 -15
  22. package/e2e-legacy/setup/aclmanagement/render-rules.spec.js +1 -1
  23. package/e2e-legacy/setup/aclmanagement/reorder-rules.spec.js +2 -2
  24. package/e2e-legacy/setup/aclmanagement/revert-rules.spec.js +2 -2
  25. package/e2e-legacy/setup/aclmanagement/update-rules.spec.js +3 -3
  26. package/e2e-legacy/setup/aclmanagement/validate-uri.spec.js +152 -0
  27. package/e2e-legacy/setup/users-and-access/user-and-access.spec.js +19 -19
  28. package/e2e-legacy/sparql-editor/yasr/download-as.spec.js +4 -7
  29. package/e2e-legacy/ttyg/edit-agent.spec.js +8 -0
  30. package/e2e-legacy/ttyg/ttyg-initial-state-with-configured-api-key.spec.js +1 -1
  31. package/e2e-legacy/ttyg/ttyg-initial-state-with-selected-repository.spec.js +1 -1
  32. package/e2e-legacy/ttyg/ttyg-initial-state-without-repositories.spec.js +1 -1
  33. package/eslint.config.js +5 -0
  34. package/fixtures/graphdb-import/wine.rdf +279 -285
  35. package/npm-shrinkwrap.json +11 -11
  36. package/package.json +3 -2
  37. package/steps/import/import-steps.js +26 -6
  38. package/steps/import/import-test-constants.js +1 -1
  39. package/steps/main-menu-steps.js +5 -14
  40. package/steps/resource/resource-steps.js +64 -5
  41. package/steps/setup/acl-management-steps.js +3 -23
  42. package/stubs/repositories/repositories-stubs.js +4 -0
  43. package/fixtures/graphdb-import/test-trigstar.trigs +0 -32
  44. package/fixtures/graphdb-import/test_turtlestar.ttls +0 -6
  45. package/fixtures/graphdb-import/turtlestar-data.ttls +0 -77
@@ -0,0 +1,152 @@
1
+ import {AclManagementSteps} from "../../../steps/setup/acl-management-steps";
2
+ import {ApplicationSteps} from "../../../steps/application-steps";
3
+
4
+ describe('ACL Management: IRI validation', () => {
5
+
6
+ let repositoryId;
7
+
8
+ afterEach(() => {
9
+ cy.deleteRepository(repositoryId);
10
+ });
11
+
12
+ beforeEach(() => {
13
+ repositoryId = 'acl-management-' + Date.now();
14
+ cy.createRepository({id: repositoryId});
15
+ cy.presetRepository(repositoryId);
16
+ cy.initializeRepository(repositoryId);
17
+ cy.enableAutocomplete(repositoryId);
18
+ AclManagementSteps.visit();
19
+ ApplicationSteps.getLoader().should('not.exist');
20
+ });
21
+
22
+ /**
23
+ * Fills in all the fields required for the rule to be otherwise valid, except the subject,
24
+ * so that only the subject's own validity determines whether the rule can be saved.
25
+ * @param {number} index
26
+ */
27
+ const fillMandatoryFieldsExceptSubject = (index) => {
28
+ AclManagementSteps.fillRole(index, 'ROLE1');
29
+ AclManagementSteps.selectPolicy(index, 'allow');
30
+ AclManagementSteps.selectOperation(index, 'write');
31
+ AclManagementSteps.fillPredicate(index, '*');
32
+ AclManagementSteps.fillObject(index, '*');
33
+ AclManagementSteps.fillContext(index, '*');
34
+ };
35
+
36
+ it('should mark the subject field as invalid and block saving when an absolute http IRI is typed without angle brackets', () => {
37
+ // When I create a new rule and type an absolute http IRI without wrapping it in angle brackets
38
+ AclManagementSteps.addRuleInBeginning();
39
+ fillMandatoryFieldsExceptSubject(0);
40
+ AclManagementSteps.fillSubject(0, 'http://example.com/John');
41
+
42
+ // Then I expect the field to be marked as invalid
43
+ AclManagementSteps.getSubjectField(0).should('have.class', 'invalid');
44
+ // And I expect saving the rule to be forbidden
45
+ AclManagementSteps.checkIfRuleSavingIsForbidden(0);
46
+ });
47
+
48
+ it('should mark the subject field as valid and allow saving once the http IRI is wrapped in angle brackets', () => {
49
+ // When I create a new rule and type a properly wrapped absolute http IRI
50
+ AclManagementSteps.addRuleInBeginning();
51
+ fillMandatoryFieldsExceptSubject(0);
52
+ AclManagementSteps.fillSubject(0, '<http://example.com/John>');
53
+
54
+ // Then I expect the field to be marked as valid
55
+ AclManagementSteps.getSubjectField(0).should('not.have.class', 'invalid');
56
+ // And I expect saving the rule to be allowed
57
+ AclManagementSteps.checkIfRuleSavingIsAllowed(0);
58
+ });
59
+
60
+ it('should mark the subject field as invalid for a urn IRI without angle brackets and valid once wrapped', () => {
61
+ // When I create a new rule and type a urn IRI without angle brackets
62
+ AclManagementSteps.addRuleInBeginning();
63
+ fillMandatoryFieldsExceptSubject(0);
64
+ AclManagementSteps.fillSubject(0, 'urn:John');
65
+
66
+ // Then I expect the field to be marked as invalid
67
+ AclManagementSteps.getSubjectField(0).should('have.class', 'invalid');
68
+ AclManagementSteps.checkIfRuleSavingIsForbidden(0);
69
+
70
+ // When I wrap the same urn IRI in angle brackets
71
+ AclManagementSteps.fillSubject(0, '<urn:John>');
72
+
73
+ // Then I expect the field to become valid
74
+ AclManagementSteps.getSubjectField(0).should('not.have.class', 'invalid');
75
+ AclManagementSteps.checkIfRuleSavingIsAllowed(0);
76
+ });
77
+
78
+ it('should keep the wildcard (*) value valid', () => {
79
+ // When I create a new rule and use the wildcard value for the subject
80
+ AclManagementSteps.addRuleInBeginning();
81
+ fillMandatoryFieldsExceptSubject(0);
82
+ AclManagementSteps.fillSubject(0, '*');
83
+
84
+ // Then I expect the field to remain valid
85
+ AclManagementSteps.getSubjectField(0).should('not.have.class', 'invalid');
86
+ AclManagementSteps.checkIfRuleSavingIsAllowed(0);
87
+ });
88
+
89
+ it('should still query autocomplete suggestions for an absolute IRI typed without angle brackets', () => {
90
+ // Given I intercept the autocomplete suggestions requests
91
+ cy.intercept('GET', '**/rest/autocomplete/query*').as('autocompleteQuery');
92
+
93
+ // When I create a new rule and type an absolute http IRI without angle brackets
94
+ AclManagementSteps.addRuleInBeginning();
95
+ fillMandatoryFieldsExceptSubject(0);
96
+ AclManagementSteps.fillSubject(0, 'http://example.com/resource/John');
97
+
98
+ // Then I expect the autocomplete request to still be triggered, searching only by the
99
+ // local name within the detected namespace (namespace and local name joined by ";")
100
+ cy.wait('@autocompleteQuery');
101
+ cy.get('@autocompleteQuery.all').then((interceptions) => {
102
+ const lastCall = interceptions[interceptions.length - 1];
103
+ const url = new URL(lastCall.request.url);
104
+ expect(url.searchParams.get('q')).to.eq('http://example.com/resource/;John');
105
+ });
106
+ });
107
+
108
+ it('should reject a triple term value for a plain field validated only as an IRI', () => {
109
+ // Predicate only allows validate-uri/validate-default-value, so a triple term is not a valid value there
110
+ AclManagementSteps.addRuleInBeginning();
111
+ AclManagementSteps.fillRole(0, 'ROLE1');
112
+ AclManagementSteps.selectPolicy(0, 'allow');
113
+ AclManagementSteps.selectOperation(0, 'write');
114
+ AclManagementSteps.fillSubject(0, '*');
115
+ AclManagementSteps.fillObject(0, '*');
116
+ AclManagementSteps.fillContext(0, '*');
117
+ AclManagementSteps.fillPredicate(0, '<<(<http://example.com/a> <http://example.com/b> "c")>>');
118
+
119
+ AclManagementSteps.getPredicateField(0).should('have.class', 'invalid');
120
+ AclManagementSteps.checkIfRuleSavingIsForbidden(0);
121
+ });
122
+
123
+ it('should accept a triple term value for the object field, where it is allowed', () => {
124
+ // Only the object field is configured with validate-triple-term-value="true"
125
+ AclManagementSteps.addRuleInBeginning();
126
+ AclManagementSteps.fillRole(0, 'ROLE1');
127
+ AclManagementSteps.selectPolicy(0, 'allow');
128
+ AclManagementSteps.selectOperation(0, 'write');
129
+ AclManagementSteps.fillSubject(0, '*');
130
+ AclManagementSteps.fillPredicate(0, '*');
131
+ AclManagementSteps.fillContext(0, '*');
132
+ AclManagementSteps.fillObject(0, '<<(<http://example.com/a> <http://example.com/b> "c")>>');
133
+
134
+ AclManagementSteps.getObjectField(0).should('not.have.class', 'invalid');
135
+ AclManagementSteps.checkIfRuleSavingIsAllowed(0);
136
+ });
137
+
138
+ it('should reject a malformed triple term value (missing closing brackets) for the object field', () => {
139
+ AclManagementSteps.addRuleInBeginning();
140
+ AclManagementSteps.fillRole(0, 'ROLE1');
141
+ AclManagementSteps.selectPolicy(0, 'allow');
142
+ AclManagementSteps.selectOperation(0, 'write');
143
+ AclManagementSteps.fillSubject(0, '*');
144
+ AclManagementSteps.fillPredicate(0, '*');
145
+ AclManagementSteps.fillContext(0, '*');
146
+ AclManagementSteps.fillObject(0, '<<(<http://example.com/a> <http://example.com/b> "c")');
147
+
148
+ AclManagementSteps.getObjectField(0).should('have.class', 'invalid');
149
+ AclManagementSteps.checkIfRuleSavingIsForbidden(0);
150
+ });
151
+ });
152
+
@@ -280,7 +280,7 @@ describe('User and Access', () => {
280
280
  LoginSteps.loginWithUser('admin', DEFAULT_ADMIN_PASSWORD);
281
281
  UserAndAccessSteps.getUsersTable().should('be.visible');
282
282
 
283
- cy.visit('/login?r=%252Fsparql');
283
+ cy.visit('/login?r=%2Fsparql');
284
284
  cy.reload();
285
285
  UserAndAccessSteps.getUrl().should('include', '/sparql');
286
286
  });
@@ -976,14 +976,14 @@ describe('User and Access', () => {
976
976
  };
977
977
 
978
978
  const MENU_ITEMS_WITHOUT_GRAPHQL = [
979
- // 1) Import
979
+ // Import
980
980
  {
981
981
  path: ['Import'],
982
982
  expectedUrl: '/import',
983
983
  checks: noAuthChecks,
984
984
  },
985
985
 
986
- // 2) Explore
986
+ // Explore
987
987
  {
988
988
  path: ['Explore', 'Graphs overview'],
989
989
  expectedUrl: '/graphs',
@@ -1011,7 +1011,7 @@ describe('User and Access', () => {
1011
1011
  checks: noAuthChecks,
1012
1012
  },
1013
1013
 
1014
- // 3) SPARQL
1014
+ // SPARQL
1015
1015
  {
1016
1016
  path: ['SPARQL'],
1017
1017
  expectedTitle: 'SPARQL Query & Update',
@@ -1019,9 +1019,16 @@ describe('User and Access', () => {
1019
1019
  checks: noAuthChecks,
1020
1020
  },
1021
1021
 
1022
- // 4) GraphQL
1022
+ // TTYG
1023
+ {
1024
+ path: ['Talk to Your Graph'],
1025
+ expectedUrl: '/ttyg',
1026
+ checks: noAuthChecks,
1027
+ },
1028
+
1029
+ // GraphQL
1023
1030
 
1024
- // 5) Monitor
1031
+ // Monitor
1025
1032
  {
1026
1033
  path: ['Monitor', 'Queries and Updates'],
1027
1034
  expectedUrl: '/monitor/queries',
@@ -1029,7 +1036,7 @@ describe('User and Access', () => {
1029
1036
  checks: noAuthChecks,
1030
1037
  },
1031
1038
 
1032
- // 6) Setup
1039
+ // Setup
1033
1040
  {
1034
1041
  path: ['Setup', 'My Settings'],
1035
1042
  expectedUrl: '/settings',
@@ -1081,14 +1088,7 @@ describe('User and Access', () => {
1081
1088
  checks: noAuthChecks,
1082
1089
  },
1083
1090
 
1084
- // 7) Lab
1085
- {
1086
- path: ['Lab', 'Talk to Your Graph'],
1087
- expectedUrl: '/ttyg',
1088
- checks: noAuthChecks,
1089
- },
1090
-
1091
- // 8) Help
1091
+ // Help
1092
1092
  {
1093
1093
  path: ['Help', 'REST API'],
1094
1094
  expectedUrl: '/webapi',
@@ -1128,14 +1128,14 @@ describe('User and Access', () => {
1128
1128
  ];
1129
1129
 
1130
1130
  const FREE_ACCESS_MENU_ITEMS_WITHOUT_GRAPHQL = [
1131
- // 1) Import
1131
+ // Import
1132
1132
  {
1133
1133
  path: ['Import'],
1134
1134
  expectedUrl: '/import',
1135
1135
  checks: noAuthChecks,
1136
1136
  },
1137
1137
 
1138
- // 2) Explore
1138
+ // Explore
1139
1139
  {
1140
1140
  path: ['Explore', 'Graphs overview'],
1141
1141
  expectedUrl: '/graphs',
@@ -1163,7 +1163,7 @@ describe('User and Access', () => {
1163
1163
  checks: noAuthChecks,
1164
1164
  },
1165
1165
 
1166
- // 3) SPARQL
1166
+ // SPARQL
1167
1167
  {
1168
1168
  path: ['SPARQL'],
1169
1169
  expectedTitle: 'SPARQL Query & Update',
@@ -1171,7 +1171,7 @@ describe('User and Access', () => {
1171
1171
  checks: noAuthChecks,
1172
1172
  },
1173
1173
 
1174
- // 6) Setup
1174
+ // Setup
1175
1175
  {
1176
1176
  path: ['Setup', 'Connectors'],
1177
1177
  expectedUrl: '/connectors',
@@ -44,13 +44,10 @@ describe('Download results', () => {
44
44
 
45
45
  // Then expect follow options to be present.
46
46
  YasrSteps.getDownloadAsOption(0).contains('JSON');
47
- YasrSteps.getDownloadAsOption(1).contains( 'JSON*');
48
- YasrSteps.getDownloadAsOption(2).contains( 'XML');
49
- YasrSteps.getDownloadAsOption(3).contains( 'XML*');
50
- YasrSteps.getDownloadAsOption(4).contains( 'CSV');
51
- YasrSteps.getDownloadAsOption(5).contains( 'TSV');
52
- YasrSteps.getDownloadAsOption(6).contains( 'TSV*');
53
- YasrSteps.getDownloadAsOption(7).contains( 'Binary RDF Results');
47
+ YasrSteps.getDownloadAsOption(1).contains( 'XML');
48
+ YasrSteps.getDownloadAsOption(2).contains( 'CSV');
49
+ YasrSteps.getDownloadAsOption(3).contains( 'TSV');
50
+ YasrSteps.getDownloadAsOption(4).contains( 'Binary RDF Results');
54
51
  });
55
52
 
56
53
  it('should download as JSON-LD after a CONSTRUCT query', () => {
@@ -109,6 +109,14 @@ describe('TTYG edit an agent', () => {
109
109
 
110
110
  // THEN: The Save Agent button should be disabled
111
111
  TtygAgentSettingsModalSteps.getSaveAgentButton().should('be.disabled');
112
+ // AND: The panel of the FTS extraction method should be expanded, so that the reason is visible
113
+ TtygAgentSettingsModalSteps.getFtsDisabledHelp().should('be.visible');
114
+
115
+ // WHEN: I try to collapse the panel of the FTS extraction method
116
+ TtygAgentSettingsModalSteps.toggleFTSExtractionMethodPanel();
117
+ // THEN: The panel should remain expanded, because the precondition error is not resolved yet
118
+ TtygAgentSettingsModalSteps.getFtsDisabledHelp().should('be.visible');
119
+ TtygAgentSettingsModalSteps.getSaveAgentButton().should('be.disabled');
112
120
  });
113
121
 
114
122
  it('should be able to edit Autocomplete extraction method option', () => {
@@ -39,7 +39,7 @@ describe('TTYG initial state with API key', () => {
39
39
  it('Should display the correct initial state when navigating via the navigation menu', () => {
40
40
  // Given, I visit the TTYG page via the navigation menu
41
41
  HomeSteps.visit();
42
- MainMenuSteps.clickOnTTYG();
42
+ MainMenuSteps.clickOnMenuTTYG();
43
43
  // Then,
44
44
  verifyStateWithApiKey();
45
45
  });
@@ -38,7 +38,7 @@ describe.skip('TTYG initial state with selected repository', () => {
38
38
  it('Should display the correct initial state when navigating via the navigation menu', () => {
39
39
  // Given, I visit the TTYG page via the navigation menu with a repository selected
40
40
  HomeSteps.visit();
41
- MainMenuSteps.clickOnTTYG();
41
+ MainMenuSteps.clickOnMenuTTYG();
42
42
  // Then,
43
43
  verifyStateWithSelectedRepository();
44
44
  });
@@ -14,7 +14,7 @@ describe('TTYG initial state without selected repository', () => {
14
14
  it('Should display the correct initial state when navigating via the navigation menu', () => {
15
15
  // Given, I visit the TTYG page via the navigation menu without a repository selected
16
16
  HomeSteps.visit();
17
- MainMenuSteps.clickOnTTYG();
17
+ MainMenuSteps.clickOnMenuTTYG();
18
18
  // Then,
19
19
  ErrorSteps.verifyNoConnectedRepoMessage();
20
20
  });
package/eslint.config.js CHANGED
@@ -35,6 +35,11 @@ export default [
35
35
  rules: {
36
36
  ...pluginJs.configs.recommended.rules,
37
37
  ...pluginCypress.configs.recommended.rules,
38
+ // Exclusive tests (.only) silently skip the rest of the suite, so they must never be committed.
39
+ 'no-restricted-syntax': ['error', {
40
+ selector: "MemberExpression[computed=false][property.name='only'][object.name=/^(describe|context|it|specify|test|suite)$/]",
41
+ message: 'Exclusive tests are not allowed: remove ".only" before committing.'
42
+ }],
38
43
  },
39
44
  },
40
45
  ];