graphdb-workbench-tests 3.5.0-TR8 → 3.5.0-loader-TR1

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.
@@ -0,0 +1,45 @@
1
+ import { defineConfig } from 'cypress';
2
+ import setupPlugins from './plugins/index.js';
3
+
4
+ const isCoverage = process.env.COVERAGE === 'true';
5
+
6
+ const loadCodeCoverage = async (on, config) => {
7
+ const mod = await import('@bahmutov/cypress-code-coverage/plugin');
8
+ const plugin = ('default' in mod) ? mod.default : mod;
9
+ plugin(on, config);
10
+ };
11
+
12
+ export default defineConfig({
13
+ projectId: 'v35btb',
14
+ fixturesFolder: 'fixtures',
15
+ screenshotsFolder: 'report/screenshots',
16
+ videosFolder: 'report/videos',
17
+ video: true,
18
+ defaultCommandTimeout: 25000,
19
+ numTestsKeptInMemory: 10,
20
+ viewportWidth: 1600,
21
+ viewportHeight: 1200,
22
+ e2e: {
23
+ retries: {
24
+ runMode: 2,
25
+ openMode: 0
26
+ },
27
+ async setupNodeEvents(on, config) {
28
+ setupPlugins(on, config);
29
+ if (isCoverage) {
30
+ await loadCodeCoverage(on, config);
31
+ }
32
+ return config;
33
+ },
34
+ baseUrl: 'http://localhost:9000',
35
+ specPattern: 'e2e-legacy/guides/**/*.{js,jsx,ts,tsx}',
36
+ supportFile: 'support/e2e.js',
37
+ reporter: "cypress-multi-reporters",
38
+ reporterOptions: {
39
+ configFile: 'cypress-reporter-config.json'
40
+ }
41
+ },
42
+ env: {
43
+ set_default_user_data: true
44
+ }
45
+ });
@@ -9,8 +9,7 @@ import {GuidesStubs} from "../../../../stubs/guides/guides-stubs.js";
9
9
  import {TTYGStubs} from "../../../../stubs/ttyg/ttyg-stubs.js";
10
10
  import {RepositoriesStubs} from "../../../../stubs/repositories/repositories-stubs.js";
11
11
 
12
- // TODO: there is some issue with the context side field focus that breaks the test. Should be fixed soon
13
- describe.skip('ttyg configure agent guide', () => {
12
+ describe('ttyg configure agent guide', () => {
14
13
  let repositoryId;
15
14
 
16
15
  beforeEach(() => {
@@ -0,0 +1,137 @@
1
+ import HomeSteps from '../../../steps/home-steps.js';
2
+ import {DeprecationSteps} from '../../../steps/deprecation-steps.js';
3
+ import {LoginSteps} from '../../../steps/login-steps.js';
4
+ import {GuidesStubs} from '../../../stubs/guides/guides-stubs.js';
5
+ import {GuideSteps} from '../../../steps/guides/guide-steps.js';
6
+ import {GuideDialogSteps} from '../../../steps/guides/guide-dialog-steps.js';
7
+
8
+ describe('Solr deprecation banner', () => {
9
+ context('Security disabled', () => {
10
+ it('should keep the Solr deprecation banner hidden after the anonymous user dismisses it', () => {
11
+ // GIVEN: I have opened the application with security disabled.
12
+ HomeSteps.visit();
13
+
14
+ // THEN: I expect the Solr deprecation banner to be visible.
15
+ DeprecationSteps.getDeprecationBanner()
16
+ .should('be.visible')
17
+ .should('contain.text', 'The Solr connector is deprecated and will be removed in GraphDB 12');
18
+
19
+ // WHEN: I dismiss the Solr deprecation banner.
20
+ DeprecationSteps.closeBanner();
21
+ // THEN: I expect the Solr deprecation banner to be hidden.
22
+ DeprecationSteps.getDeprecationBanner().should('not.exist');
23
+
24
+ // WHEN: I reload the application.
25
+ HomeSteps.visit();
26
+ // THEN: I expect the Solr deprecation banner to remain hidden.
27
+ DeprecationSteps.getDeprecationBanner().should('not.exist');
28
+ });
29
+ });
30
+
31
+ context('Security enabled', () => {
32
+ const PASSWORD = 'root';
33
+ const USER_USERNAME = 'username';
34
+
35
+ beforeEach(() => {
36
+ cy.createUser({
37
+ username: USER_USERNAME,
38
+ password: PASSWORD
39
+ });
40
+
41
+ cy.switchOnSecurity()
42
+ .then(() => cy.loginAsAdmin())
43
+ .then(() => cy.switchOnFreeAccess(true));
44
+ });
45
+
46
+ afterEach(() => {
47
+ cy.loginAsAdmin()
48
+ .then(() => {
49
+ cy.deleteUser(USER_USERNAME, true);
50
+ cy.switchOffFreeAccess(true);
51
+ cy.switchOffSecurity(true);
52
+ });
53
+ });
54
+
55
+ it('should persist separate Solr banner states for anonymous and logged-in users', () => {
56
+ // GIVEN: Security and free access are enabled, and no user is logged in.
57
+ HomeSteps.visit();
58
+
59
+ // THEN: I expect the Solr deprecation banner to be visible for the anonymous user.
60
+ DeprecationSteps.getDeprecationBanner()
61
+ .should('be.visible')
62
+ .should('contain.text', 'The Solr connector is deprecated and will be removed in GraphDB 12');
63
+
64
+ // WHEN: The anonymous user dismisses the banner.
65
+ DeprecationSteps.closeBanner();
66
+ // THEN: I expect the banner to be hidden for the anonymous user.
67
+ DeprecationSteps.getDeprecationBanner().should('not.exist');
68
+
69
+ // WHEN: I log in as a user who has not dismissed the banner.
70
+ cy.loginAs(USER_USERNAME, PASSWORD);
71
+ HomeSteps.visit();
72
+
73
+ // THEN: I expect the banner to be visible for the logged-in user.
74
+ DeprecationSteps.getDeprecationBanner()
75
+ .should('be.visible')
76
+ .should('contain.text', 'The Solr connector is deprecated and will be removed in GraphDB 12');
77
+
78
+ // WHEN: The logged-in user dismisses the banner.
79
+ DeprecationSteps.closeBanner();
80
+ // THEN: I expect the banner to be hidden for the logged-in user.
81
+ DeprecationSteps.getDeprecationBanner().should('not.exist');
82
+
83
+ // WHEN: The user logs out.
84
+ LoginSteps.logout();
85
+ // THEN: I expect the banner to remain hidden because the anonymous user has already dismissed it.
86
+ DeprecationSteps.getDeprecationBanner().should('not.exist');
87
+
88
+ // WHEN: I log in as the administrator, who has not dismissed the banner.
89
+ cy.loginAs('admin', 'root');
90
+ HomeSteps.visit();
91
+ // THEN: I expect the banner to be visible for the administrator.
92
+ DeprecationSteps.getDeprecationBanner()
93
+ .should('be.visible')
94
+ .should('contain.text', 'The Solr connector is deprecated and will be removed in GraphDB 12');
95
+
96
+ // WHEN: The administrator logs out.
97
+ LoginSteps.logout();
98
+ // THEN: I expect the banner to remain hidden because the anonymous user has already dismissed it.
99
+ DeprecationSteps.getDeprecationBanner().should('not.exist');
100
+
101
+ // WHEN: I log in again as the user who previously dismissed the banner.
102
+ cy.loginAs(USER_USERNAME, PASSWORD);
103
+ HomeSteps.visit();
104
+ // THEN: I expect the banner to remain hidden for the logged-in user.
105
+ DeprecationSteps.getDeprecationBanner().should('not.exist');
106
+ });
107
+ });
108
+
109
+ context('User guides', () => {
110
+ it('should hide the Solr deprecation banner while a guide is running', () => {
111
+ // GIVEN: The guides are loaded and ready to be started.
112
+ GuidesStubs.stubMainMenuGuide();
113
+ GuideSteps.visit();
114
+ GuideSteps.verifyGuidesListExists();
115
+ cy.wait('@getGuides');
116
+
117
+ // WHEN: I am on an application page, and the Solr deprecation banner has not been dismissed by the current user.
118
+ // THEN: I expect the Solr deprecation banner to be visible because it has not been dismissed by the current user.
119
+ DeprecationSteps.getDeprecationBanner()
120
+ .should('be.visible')
121
+ .should('contain.text', 'The Solr connector is deprecated and will be removed in GraphDB 12');
122
+
123
+ // WHEN: I start a guide.
124
+ GuideSteps.runFirstGuide();
125
+ // THEN: I expect the Solr deprecation banner to be hidden while the guide is running.
126
+ DeprecationSteps.getDeprecationBanner().should('not.exist');
127
+
128
+ // WHEN: I cancel the guide.
129
+ GuideDialogSteps.clickOnCancelButton();
130
+ GuideDialogSteps.clickConfirmCancelDialogExitButton();
131
+ // THEN: I expect the Solr deprecation banner to be visible again.
132
+ DeprecationSteps.getDeprecationBanner()
133
+ .should('be.visible')
134
+ .should('contain.text', 'The Solr connector is deprecated and will be removed in GraphDB 12');
135
+ });
136
+ });
137
+ });
@@ -241,4 +241,136 @@ describe('Ontop repositories', () => {
241
241
  // Then I expect url to be calculated properly
242
242
  OntopRepositorySteps.getUrlInput().should('have.value', 'jdbc:snowflake://someHostName.snowflakecomputing.com:1234/?warehouse=test_database');
243
243
  });
244
+
245
+ context('Repository maintenance permission', () => {
246
+
247
+ const PASSWORD = 'root';
248
+ const REPOSITORY_MAINTAINER_USERNAME = 'repoMaintainer';
249
+ const REPOSITORY_MANAGER_USERNAME = 'repoManager';
250
+
251
+ beforeEach(() => {
252
+ cy.createUser({
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();
271
+ });
272
+
273
+ afterEach(() => {
274
+ cy.loginAsAdmin()
275
+ .then(() => {
276
+ cy.deleteUser(REPOSITORY_MAINTAINER_USERNAME, true);
277
+ cy.deleteUser(REPOSITORY_MANAGER_USERNAME, true);
278
+ cy.switchOffSecurity(true);
279
+ });
280
+ });
281
+ it('should allow a repository maintainer to edit an Ontop repository', () => {
282
+ RepositoryStubs.spyGetJDBCProperties();
283
+ // GIVEN: An Ontop repository exists
284
+ cy.loginAs(REPOSITORY_MANAGER_USERNAME, PASSWORD);
285
+ OntopRepositorySteps.visitCreate();
286
+ createOntopRepository(repositoryId);
287
+
288
+ // WHEN: I log in as a user with maintenance permission
289
+ cy.loginAs(REPOSITORY_MAINTAINER_USERNAME, PASSWORD);
290
+ RepositorySteps.visit(false);
291
+
292
+ // THEN: The repository is visible because the user can maintain it
293
+ RepositorySteps.getRepositoryFromList(repositoryId).should('exist');
294
+
295
+ // WHEN: I edit the repository
296
+ RepositorySteps.editRepository(repositoryId);
297
+ cy.wait('@getJDBCProperties');
298
+ RepositorySteps.getUsernameFieldEditRepo()
299
+ .should('have.value', '')
300
+ .type('username');
301
+
302
+ // Uploading an OBDA file verifies that the repository maintainer can access rest/repositories/file/upload
303
+ OntopRepositorySteps.clickObdaFileUploadButton();
304
+ OntopRepositorySteps.uploadObdaFile('fixtures/ontop/university-complete_edited.obda');
305
+
306
+ // Saving the form verifies that the repository maintainer can access rest/repositories/ontop/jdbc-properties
307
+ OntopRepositorySteps.getAdditionalJDBCProperties()
308
+ .should('have.value', '')
309
+ .type('ontop.cardinalityMode=LOOSE');
310
+
311
+ RepositorySteps.clickSaveEditedRepo();
312
+ ModalDialogSteps.clickOnConfirmButton();
313
+
314
+ // THEN: The changes are persisted
315
+ RepositorySteps.visit(false);
316
+ RepositorySteps.getRepositoryFromList(repositoryId).should('exist');
317
+ RepositorySteps.editRepository(repositoryId);
318
+ cy.wait('@getJDBCProperties');
319
+
320
+ OntopRepositorySteps.getOntopSaveButton().should('be.visible');
321
+ RepositorySteps.getUsernameFieldEditRepo()
322
+ .should('have.value', 'username');
323
+
324
+ // Loading the saved properties verifies GET access to rest/repositories/ontop/jdbc-properties
325
+ OntopRepositorySteps.getAdditionalJDBCProperties()
326
+ .should('contain.value', 'ontop.cardinalityMode=LOOSE');
327
+ // Saving of the OBDA file verifies that the repository maintainer can access rest/repositories/file/upload
328
+ OntopRepositorySteps.editOBDAFile();
329
+ ModalDialogSteps.getDialogBody()
330
+ .find('textarea')
331
+ .invoke('val')
332
+ .should('include', 'edited ODBA file');
333
+ ModalDialogSteps.close();
334
+
335
+ // WHEN: I edit and save the OBDA file
336
+ // Opening the editor verifies access to rest/repositories/file,
337
+ // while saving verifies access to rest/repositories/file/update.
338
+ OntopRepositorySteps.editOBDAFile();
339
+ ModalDialogSteps.getDialogHeader()
340
+ .should('contain', 'Edit "OBDA or R2RML file" contents');
341
+
342
+ ModalDialogSteps.getDialogBody()
343
+ .find('textarea')
344
+ .type('{moveToStart}Add commentary for testing purpose');
345
+
346
+ ModalDialogSteps.clickOKButton();
347
+ RepositorySteps.clickSaveEditedRepo();
348
+ ModalDialogSteps.clickOnConfirmButton();
349
+
350
+ // THEN: The OBDA file changes are persisted
351
+ RepositorySteps.visit(false);
352
+ RepositorySteps.getRepositoryFromList(repositoryId).should('exist');
353
+ RepositorySteps.editRepository(repositoryId);
354
+ cy.wait('@getJDBCProperties');
355
+ OntopRepositorySteps.editOBDAFile();
356
+
357
+ ModalDialogSteps.getDialogBody()
358
+ .find('textarea')
359
+ .invoke('val')
360
+ .should('include', 'Add commentary for testing purpose');
361
+ });
362
+ });
244
363
  });
364
+
365
+ const createOntopRepository = (repositoryId) => {
366
+ RepositorySteps.typeRepositoryId(repositoryId);
367
+ OntopRepositorySteps.selectOracleDatabase();
368
+ OntopRepositorySteps.typeHostName('localhost');
369
+ OntopRepositorySteps.typePort(5423);
370
+ OntopRepositorySteps.typeDatabaseName('database-name');
371
+ OntopRepositorySteps.clickObdaFileUploadButton();
372
+ OntopRepositorySteps.uploadObdaFile('fixtures/ontop/university-complete.obda');
373
+ // Wait edit OBDA edit button be visible to ensure that file is uploaded.
374
+ OntopRepositorySteps.getOBDAFileFieldEditButton().should('be.visible');
375
+ OntopRepositorySteps.clickOnCreateRepositoryButton();
376
+ };
@@ -79,8 +79,8 @@ describe('User and Access', () => {
79
79
  testForUser(user, false);
80
80
  });
81
81
 
82
- it('Create manage user', () => {
83
- createUser(user, PASSWORD, ROLE_USER, {manage: true, repoName});
82
+ it('Create maintainer user', () => {
83
+ createUser(user, PASSWORD, ROLE_USER, {maintain: true, repoName});
84
84
  testForUser(user, false);
85
85
  });
86
86
 
@@ -181,17 +181,17 @@ describe('User and Access', () => {
181
181
  });
182
182
 
183
183
  // Skipped until image with GDB implementation is available
184
- it.skip('should create user with manage repo rights for specific repo', () => {
184
+ it.skip('should create user with maintain repo permission for specific repo', () => {
185
185
  SecurityStubs.spyOnUserCreate();
186
186
  UserAndAccessSteps.getUsersCatalogContainer().should('be.visible');
187
- createUser(user, PASSWORD, ROLE_USER, {manage: true, repoName: repoName});
187
+ createUser(user, PASSWORD, ROLE_USER, {maintain: true, repoName: repoName});
188
188
  // Then the user should be created with that custom role
189
189
  cy.wait('@create-user').its('request.body').then((body) => {
190
190
  expect(body).to.deep.eq({
191
191
  'password': 'password',
192
192
  'grantedAuthorities': [
193
193
  'ROLE_USER',
194
- `MANAGE_REPO_${repoName}`,
194
+ `MAINTAIN_REPO_${repoName}`,
195
195
  `WRITE_REPO_${repoName}`,
196
196
  `READ_REPO_${repoName}`,
197
197
  ],
@@ -205,13 +205,13 @@ describe('User and Access', () => {
205
205
  });
206
206
  });
207
207
  UserAndAccessSteps.getUsersCatalogContainer().should('be.visible');
208
- assertUserAuthsInCatalog(user, {repo: repoName, read: false, manage: true, graphql: false});
208
+ assertUserAuthsInCatalog(user, {repo: repoName, read: false, maintain: true, graphql: false});
209
209
 
210
210
  UserAndAccessSteps.openEditUserPage(user);
211
211
  cy.wait('@get-user');
212
212
  UserAndAccessSteps.getRepositoryRightsList().should('be.visible');
213
- verifyCheckedUserAuth(repoName, {read: true, write: true, manage: true, graphql: false});
214
- verifyDisabledUserAuth(repoName, {read: true, write: true, manage: false, graphql: true});
213
+ verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: true, graphql: false});
214
+ verifyDisabledUserAuth(repoName, {read: true, write: true, maintain: false, graphql: true});
215
215
  });
216
216
  });
217
217
 
@@ -266,6 +266,7 @@ describe('User and Access', () => {
266
266
  UserAndAccessSteps.toggleSecurity();
267
267
  LoginSteps.loginWithUser('admin', DEFAULT_ADMIN_PASSWORD);
268
268
  MainMenuSteps.clickOnSparqlMenu();
269
+ cy.get('h1').should('be.visible').should('contain', 'SPARQL Query & Update');
269
270
  cy.url().should('include', '/sparql');
270
271
 
271
272
  LoginSteps.logout();
@@ -313,32 +314,32 @@ describe('User and Access', () => {
313
314
 
314
315
  it('initial state', () => {
315
316
  UserAndAccessSteps.clickCreateNewUserButton();
316
- verifyCheckedUserAuth('*', {read: false, write: false, manage: false, graphql: false});
317
- verifyDisabledUserAuth('*', {read: false, write: false, manage: true, graphql: true});
318
- verifyCheckedUserAuth(repoName, {read: false, write: false, manage: false, graphql: false});
319
- verifyDisabledUserAuth(repoName, {read: false, write: false, manage: false, graphql: true});
317
+ verifyCheckedUserAuth('*', {read: false, write: false, maintain: false, graphql: false});
318
+ verifyDisabledUserAuth('*', {read: false, write: false, maintain: true, graphql: true});
319
+ verifyCheckedUserAuth(repoName, {read: false, write: false, maintain: false, graphql: false});
320
+ verifyDisabledUserAuth(repoName, {read: false, write: false, maintain: false, graphql: true});
320
321
  });
321
322
 
322
323
  context('for non user roles', () => {
323
324
  it('admin', () => {
324
325
  UserAndAccessSteps.clickCreateNewUserButton();
325
326
  UserAndAccessSteps.selectRoleRadioButton(ROLE_CUSTOM_ADMIN);
326
- verifyCheckedUserAuth('*', {read: true, write: true, manage: true, graphql: false});
327
- verifyDisabledUserAuth('*', {read: true, write: true, manage: true, graphql: true});
327
+ verifyCheckedUserAuth('*', {read: true, write: true, maintain: true, graphql: false});
328
+ verifyDisabledUserAuth('*', {read: true, write: true, maintain: true, graphql: true});
328
329
 
329
- verifyCheckedUserAuth(repoName, {read: true, write: true, manage: true, graphql: false});
330
- verifyDisabledUserAuth(repoName, {read: true, write: true, manage: true, graphql: true});
330
+ verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: true, graphql: false});
331
+ verifyDisabledUserAuth(repoName, {read: true, write: true, maintain: true, graphql: true});
331
332
  });
332
333
 
333
334
  it('repository manager', () => {
334
335
  UserAndAccessSteps.clickCreateNewUserButton();
335
336
  UserAndAccessSteps.selectRoleRadioButton(ROLE_REPO_MANAGER);
336
337
 
337
- verifyCheckedUserAuth('*', {read: true, write: true, manage: true, graphql: false});
338
- verifyDisabledUserAuth('*', {read: true, write: true, manage: true, graphql: true});
338
+ verifyCheckedUserAuth('*', {read: true, write: true, maintain: true, graphql: false});
339
+ verifyDisabledUserAuth('*', {read: true, write: true, maintain: true, graphql: true});
339
340
 
340
- verifyCheckedUserAuth(repoName, {read: true, write: true, manage: true, graphql: false});
341
- verifyDisabledUserAuth(repoName, {read: true, write: true, manage: true, graphql: true});
341
+ verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: true, graphql: false});
342
+ verifyDisabledUserAuth(repoName, {read: true, write: true, maintain: true, graphql: true});
342
343
  });
343
344
  });
344
345
 
@@ -346,36 +347,36 @@ describe('User and Access', () => {
346
347
  it('read', () => {
347
348
  UserAndAccessSteps.clickCreateNewUserButton();
348
349
  setRoles({read: true, repoName});
349
- verifyCheckedUserAuth(repoName, {read: true, write: false, manage: false, graphql: false});
350
- verifyDisabledUserAuth(repoName, {read: false, write: false, manage: false, graphql: false});
350
+ verifyCheckedUserAuth(repoName, {read: true, write: false, maintain: false, graphql: false});
351
+ verifyDisabledUserAuth(repoName, {read: false, write: false, maintain: false, graphql: false});
351
352
  });
352
353
 
353
354
  it('write', () => {
354
355
  UserAndAccessSteps.clickCreateNewUserButton();
355
356
  setRoles({readWrite: true, repoName});
356
- verifyCheckedUserAuth(repoName, {read: true, write: true, manage: false, graphql: false});
357
- verifyDisabledUserAuth(repoName, {read: true, write: false, manage: false, graphql: false});
357
+ verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: false, graphql: false});
358
+ verifyDisabledUserAuth(repoName, {read: true, write: false, maintain: false, graphql: false});
358
359
  });
359
360
 
360
- it('manage', () => {
361
+ it('maintain', () => {
361
362
  UserAndAccessSteps.clickCreateNewUserButton();
362
- setRoles({manage: true, repoName});
363
- verifyCheckedUserAuth(repoName, {read: true, write: true, manage: true, graphql: false});
364
- verifyDisabledUserAuth(repoName, {read: true, write: true, manage: false, graphql: true});
363
+ setRoles({maintain: true, repoName});
364
+ verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: true, graphql: false});
365
+ verifyDisabledUserAuth(repoName, {read: true, write: true, maintain: false, graphql: true});
365
366
  });
366
367
 
367
368
  it('graphql with read', () => {
368
369
  UserAndAccessSteps.clickCreateNewUserButton();
369
370
  setRoles({read: true, graphql: true, repoName});
370
- verifyCheckedUserAuth(repoName, {read: true, write: false, manage: false, graphql: true});
371
- verifyDisabledUserAuth(repoName, {read: false, write: false, manage: false, graphql: false});
371
+ verifyCheckedUserAuth(repoName, {read: true, write: false, maintain: false, graphql: true});
372
+ verifyDisabledUserAuth(repoName, {read: false, write: false, maintain: false, graphql: false});
372
373
  });
373
374
 
374
375
  it('graphql with write', () => {
375
376
  UserAndAccessSteps.clickCreateNewUserButton();
376
377
  setRoles({readWrite: true, graphql: true, repoName});
377
- verifyCheckedUserAuth(repoName, {read: true, write: true, manage: false, graphql: true});
378
- verifyDisabledUserAuth(repoName, {read: true, write: false, manage: false, graphql: false});
378
+ verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: false, graphql: true});
379
+ verifyDisabledUserAuth(repoName, {read: true, write: false, maintain: false, graphql: false});
379
380
  });
380
381
  });
381
382
 
@@ -385,41 +386,41 @@ describe('User and Access', () => {
385
386
  it('read', () => {
386
387
  UserAndAccessSteps.clickCreateNewUserButton();
387
388
  setRoles({read: true, anyRepo});
388
- verifyCheckedUserAuth(anyRepo, {read: true, write: false, manage: false, graphql: false});
389
- verifyDisabledUserAuth(anyRepo, {read: false, write: false, manage: true, graphql: false});
389
+ verifyCheckedUserAuth(anyRepo, {read: true, write: false, maintain: false, graphql: false});
390
+ verifyDisabledUserAuth(anyRepo, {read: false, write: false, maintain: true, graphql: false});
390
391
 
391
- verifyCheckedUserAuth(repoName, {read: true, write: false, manage: false, graphql: false});
392
- verifyDisabledUserAuth(repoName, {read: true, write: false, manage: false, graphql: false});
392
+ verifyCheckedUserAuth(repoName, {read: true, write: false, maintain: false, graphql: false});
393
+ verifyDisabledUserAuth(repoName, {read: true, write: false, maintain: false, graphql: false});
393
394
  });
394
395
 
395
396
  it('write', () => {
396
397
  UserAndAccessSteps.clickCreateNewUserButton();
397
398
  setRoles({readWrite: true, anyRepo});
398
- verifyCheckedUserAuth(anyRepo, {read: true, write: true, manage: false, graphql: false});
399
- verifyDisabledUserAuth(anyRepo, {read: true, write: false, manage: true, graphql: false});
399
+ verifyCheckedUserAuth(anyRepo, {read: true, write: true, maintain: false, graphql: false});
400
+ verifyDisabledUserAuth(anyRepo, {read: true, write: false, maintain: true, graphql: false});
400
401
 
401
- verifyCheckedUserAuth(repoName, {read: true, write: true, manage: false, graphql: false});
402
- verifyDisabledUserAuth(repoName, {read: true, write: true, manage: false, graphql: false});
402
+ verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: false, graphql: false});
403
+ verifyDisabledUserAuth(repoName, {read: true, write: true, maintain: false, graphql: false});
403
404
  });
404
405
 
405
406
  it('graphql with read', () => {
406
407
  UserAndAccessSteps.clickCreateNewUserButton();
407
408
  setRoles({read: true, graphql: true, anyRepo});
408
- verifyCheckedUserAuth(anyRepo, {read: true, write: false, manage: false, graphql: true});
409
- verifyDisabledUserAuth(anyRepo, {read: false, write: false, manage: true, graphql: false});
409
+ verifyCheckedUserAuth(anyRepo, {read: true, write: false, maintain: false, graphql: true});
410
+ verifyDisabledUserAuth(anyRepo, {read: false, write: false, maintain: true, graphql: false});
410
411
 
411
- verifyCheckedUserAuth(repoName, {read: true, write: false, manage: false, graphql: true});
412
- verifyDisabledUserAuth(repoName, {read: true, write: false, manage: false, graphql: true});
412
+ verifyCheckedUserAuth(repoName, {read: true, write: false, maintain: false, graphql: true});
413
+ verifyDisabledUserAuth(repoName, {read: true, write: false, maintain: false, graphql: true});
413
414
  });
414
415
 
415
416
  it('graphql with write', () => {
416
417
  UserAndAccessSteps.clickCreateNewUserButton();
417
418
  setRoles({readWrite: true, graphql: true, anyRepo});
418
- verifyCheckedUserAuth(anyRepo, {read: true, write: true, manage: false, graphql: true});
419
- verifyDisabledUserAuth(anyRepo, {read: true, write: false, manage: true, graphql: false});
419
+ verifyCheckedUserAuth(anyRepo, {read: true, write: true, maintain: false, graphql: true});
420
+ verifyDisabledUserAuth(anyRepo, {read: true, write: false, maintain: true, graphql: false});
420
421
 
421
- verifyCheckedUserAuth(repoName, {read: true, write: true, manage: false, graphql: true});
422
- verifyDisabledUserAuth(repoName, {read: true, write: true, manage: false, graphql: true});
422
+ verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: false, graphql: true});
423
+ verifyDisabledUserAuth(repoName, {read: true, write: true, maintain: false, graphql: true});
423
424
  });
424
425
  });
425
426
  });
@@ -622,25 +623,25 @@ describe('User and Access', () => {
622
623
  });
623
624
  });
624
625
 
625
- context('User with manage permission', () => {
626
+ context('User with maintain permission', () => {
626
627
  let withoutPermissionRepositoryId;
627
628
  let readRepositoryId;
628
629
  let writeRepositoryId;
629
630
  let graphQLOnlyRepositoryId;
630
- let manageRepositoryId;
631
- const manageUser = 'manageUser';
631
+ let maintainedRepositoryId;
632
+ const maintainerUser = 'maintainerUser';
632
633
 
633
634
  beforeEach(() => {
634
635
  RepositoriesStubs.spyGetRepositories();
635
636
  readRepositoryId = 'readRepositoryId-' + Date.now();
636
637
  writeRepositoryId = 'writeRepositoryId-' + Date.now();
637
638
  graphQLOnlyRepositoryId = 'graphQLOnlyRepositoryId-' + Date.now();
638
- manageRepositoryId = 'manageRepositoryId-' + Date.now();
639
+ maintainedRepositoryId = 'maintainedRepositoryId-' + Date.now();
639
640
  withoutPermissionRepositoryId = 'withoutPermissionRepositoryId-' + Date.now();
640
641
  cy.createRepository({id: readRepositoryId});
641
642
  cy.createRepository({id: writeRepositoryId});
642
643
  cy.createRepository({id: graphQLOnlyRepositoryId});
643
- cy.createRepository({id: manageRepositoryId});
644
+ cy.createRepository({id: maintainedRepositoryId});
644
645
  cy.createRepository({id: withoutPermissionRepositoryId});
645
646
  UserAndAccessSteps.visit();
646
647
  // Users table should be visible
@@ -653,21 +654,21 @@ describe('User and Access', () => {
653
654
  cy.deleteRepository(readRepositoryId, true);
654
655
  cy.deleteRepository(writeRepositoryId, true);
655
656
  cy.deleteRepository(graphQLOnlyRepositoryId, true);
656
- cy.deleteRepository(manageRepositoryId, true);
657
+ cy.deleteRepository(maintainedRepositoryId, true);
657
658
  cy.deleteRepository(withoutPermissionRepositoryId, true);
658
- cy.deleteUser(manageUser, true);
659
+ cy.deleteUser(maintainerUser, true);
659
660
  cy.switchOffFreeAccess(true);
660
661
  cy.switchOffSecurity(true);
661
662
  });
662
663
  });
663
664
 
664
- it('should list all repositories for which a user with manage permission has at least read permission', () => {
665
+ it('should list all repositories for which a user with maintain permission has at least read permission', () => {
665
666
  // Given there are five repositories.
666
667
  // And there is a user with permissions for four of them:
667
- // 1. Manage permission for one repository.
668
- createUser(manageUser, PASSWORD, ROLE_USER, {manage: true, repoName: manageRepositoryId});
668
+ // 1. Maintain permission for one repository.
669
+ createUser(maintainerUser, PASSWORD, ROLE_USER, {maintain: true, repoName: maintainedRepositoryId});
669
670
  // 2. Read permission for one repository.
670
- UserAndAccessSteps.openEditUserPage(manageUser);
671
+ UserAndAccessSteps.openEditUserPage(maintainerUser);
671
672
  cy.wait('@get-user');
672
673
  setUserAuths({repo: readRepositoryId, read: true});
673
674
  // 3. Write permission for one repository.
@@ -676,28 +677,28 @@ describe('User and Access', () => {
676
677
  setUserAuths({repo: graphQLOnlyRepositoryId, write: true, graphql: true});
677
678
  UserAndAccessSteps.confirmUserEdit();
678
679
 
679
- // When I log in as a user with repository management permission.
680
+ // When I log in as a user with repository maintain permission.
680
681
  UserAndAccessSteps.toggleSecurity();
681
- LoginSteps.loginWithUser(manageUser, PASSWORD);
682
+ LoginSteps.loginWithUser(maintainerUser, PASSWORD);
682
683
  // And navigate to the repository list view.
683
684
  RepositorySteps.visit(false);
684
685
 
685
686
  // Then I should see all repositories for which the user has at least read permission.
686
687
  RepositorySteps.getRepositories().should('have.length', 4);
687
688
 
688
- // And I should see the actions allowed for the repository the user can manage.
689
- RepositorySteps.getCopyRepositoryButton(manageRepositoryId).should('be.visible');
690
- RepositorySteps.getEditRepositoryButton(manageRepositoryId).should('be.visible');
691
- RepositorySteps.getDownloadRepositoryConfigurationButton(manageRepositoryId).should('be.visible');
692
- RepositorySteps.getRestartRepositoryButton(manageRepositoryId).should('be.visible');
689
+ // And I should see the actions allowed for the repository the user can maintain.
690
+ RepositorySteps.getCopyRepositoryButton(maintainedRepositoryId).should('be.visible');
691
+ RepositorySteps.getEditRepositoryButton(maintainedRepositoryId).should('be.visible');
692
+ RepositorySteps.getDownloadRepositoryConfigurationButton(maintainedRepositoryId).should('be.visible');
693
+ RepositorySteps.getRestartRepositoryButton(maintainedRepositoryId).should('be.visible');
693
694
 
694
- // And the delete button should not be available because users with manage permission
695
+ // And the delete button should not be available because users with maintain permission
695
696
  // are not allowed to delete repositories.
696
- RepositorySteps.getDeleteRepositoryButton(manageRepositoryId).should('not.exist');
697
+ RepositorySteps.getDeleteRepositoryButton(maintainedRepositoryId).should('not.exist');
697
698
 
698
699
  // And the "Set as default repository" button should not be available because users
699
- // with manage permission are not allowed to set the default repository.
700
- RepositorySteps.getSetDefaultRepositoryButton(manageRepositoryId).should('not.exist');
700
+ // with maintain permission are not allowed to set the default repository.
701
+ RepositorySteps.getSetDefaultRepositoryButton(maintainedRepositoryId).should('not.exist');
701
702
 
702
703
  // And should see the copy action for all repositories.
703
704
  RepositorySteps.getCopyRepositoryButton(writeRepositoryId).should('be.visible');
@@ -724,7 +725,7 @@ describe('User and Access', () => {
724
725
  RepositorySteps.getSetDefaultRepositoryButton(graphQLOnlyRepositoryId).should('not.exist');
725
726
 
726
727
  // And the "Create", "Create from file", and "Attach remote repository" page buttons
727
- // should not be available to a user with manage permission.
728
+ // should not be available to a user with maintain permission.
728
729
  RepositorySteps.getPageButtons().should('not.exist');
729
730
 
730
731
  // When I select a repository for which I have GraphQL-only permission.
@@ -733,6 +734,36 @@ describe('User and Access', () => {
733
734
  // Then I should still see all repositories for which the user has at least read permission.
734
735
  RepositorySteps.getRepositories().should('have.length', 4);
735
736
  });
737
+
738
+ it('should not allow a user with maintain permission to rename a repository', () => {
739
+ // Given there is a user with maintain permission for a repository.
740
+ createUser(maintainerUser, PASSWORD, ROLE_USER, {maintain: true, repoName: maintainedRepositoryId});
741
+ UserAndAccessSteps.toggleSecurity();
742
+ LoginSteps.loginWithUser(maintainerUser, PASSWORD);
743
+ RepositorySteps.visit(false);
744
+
745
+ // When the user opens the edit page of the repository they can maintain.
746
+ RepositorySteps.getEditRepositoryButton(maintainedRepositoryId).should('be.visible');
747
+ RepositorySteps.editRepository(maintainedRepositoryId);
748
+
749
+ // Then the repository id should be rendered as read only.
750
+ RepositorySteps.getGDBIdInput()
751
+ .should('have.value', maintainedRepositoryId)
752
+ .and('be.disabled');
753
+
754
+ // And the action which unlocks the repository id field should not be available, because renaming
755
+ // a repository is allowed only for administrators and repository managers.
756
+ RepositorySteps.getRepositoryIdEditElement().should('not.exist');
757
+
758
+ // But the rest of the repository configuration should still be editable.
759
+ RepositorySteps.typeRepositoryTitle('Renaming is not allowed');
760
+ RepositorySteps.getSaveRepositoryButton().click();
761
+ ModalDialogSteps.clickOKButton();
762
+
763
+ // And the repository should keep its original id after the configuration is saved.
764
+ RepositorySteps.getRepositoryFromList(maintainedRepositoryId).should('be.visible');
765
+ RepositorySteps.getEditRepositoryButton(maintainedRepositoryId).should('be.visible');
766
+ });
736
767
  });
737
768
 
738
769
  function createUser(username, password, role, opts = {}) {
@@ -769,8 +800,8 @@ describe('User and Access', () => {
769
800
  }
770
801
 
771
802
  function setRoles(opts = {}) {
772
- const {read = false, readWrite = false, graphql = false, manage = false, repoName = '*'} = opts;
773
- setUserAuths({repo: repoName, read, write: readWrite, graphql, manage});
803
+ const {read = false, readWrite = false, graphql = false, maintain = false, repoName = '*'} = opts;
804
+ setUserAuths({repo: repoName, read, write: readWrite, graphql, maintain});
774
805
  }
775
806
 
776
807
  function testForUser(name, isAdmin) {
@@ -789,10 +820,10 @@ describe('User and Access', () => {
789
820
  }
790
821
  }
791
822
 
792
- function assertUserAuthsInCatalog(username, {repo, read = false, write = false, manage = false, graphql = false} = {}) {
823
+ function assertUserAuthsInCatalog(username, {repo, read = false, write = false, maintain = false, graphql = false} = {}) {
793
824
  UserAndAccessSteps.findUserRowAlias(username, 'userRow');
794
825
 
795
- if (!read && !write && !manage) {
826
+ if (!read && !write && !maintain) {
796
827
  return UserAndAccessSteps.getRepoLine('@userRow', repo).should('not.exist');
797
828
  }
798
829
 
@@ -811,10 +842,10 @@ describe('User and Access', () => {
811
842
  UserAndAccessSteps.findWriteIconAlias('@repoLine').should('not.exist');
812
843
  }
813
844
 
814
- if (manage) {
815
- UserAndAccessSteps.findManageIconAlias('@repoLine').should('be.visible');
845
+ if (maintain) {
846
+ UserAndAccessSteps.findMaintainIconAlias('@repoLine').should('be.visible');
816
847
  } else {
817
- UserAndAccessSteps.findManageIconAlias('@repoLine').should('not.exist');
848
+ UserAndAccessSteps.findMaintainIconAlias('@repoLine').should('not.exist');
818
849
  }
819
850
 
820
851
  if (graphql) {
@@ -824,7 +855,7 @@ describe('User and Access', () => {
824
855
  }
825
856
  }
826
857
 
827
- function setUserAuths({repo, read = false, write = false, graphql = false, manage = false} = {}) {
858
+ function setUserAuths({repo, read = false, write = false, graphql = false, maintain = false} = {}) {
828
859
  if (read === true) {
829
860
  UserAndAccessSteps.toggleReadAccessForRepo(repo);
830
861
  UserAndAccessSteps.validateReadAccessForRepo(repo, {checked: read});
@@ -840,24 +871,24 @@ describe('User and Access', () => {
840
871
  UserAndAccessSteps.validateGraphqlAccessForRepo(repo, {checked: graphql});
841
872
  }
842
873
 
843
- if (manage === true) {
844
- UserAndAccessSteps.toggleManageRepoForRepo(repo);
845
- UserAndAccessSteps.validateManageAccessForRepo(repo, {checked: manage});
874
+ if (maintain === true) {
875
+ UserAndAccessSteps.toggleMaintainRepoForRepo(repo);
876
+ UserAndAccessSteps.validateMaintainAccessForRepo(repo, {checked: maintain});
846
877
  }
847
878
  }
848
879
 
849
- function verifyCheckedUserAuth(repo, {read = false, write = false, graphql = false, manage = false} = {}) {
880
+ function verifyCheckedUserAuth(repo, {read = false, write = false, graphql = false, maintain = false} = {}) {
850
881
  UserAndAccessSteps.validateReadAccessForRepo(repo, {checked: read});
851
882
  UserAndAccessSteps.validateWriteAccessForRepo(repo, {checked: write});
852
883
  UserAndAccessSteps.validateGraphqlAccessForRepo(repo, {checked: graphql});
853
- UserAndAccessSteps.validateManageAccessForRepo(repo, {checked: manage});
884
+ UserAndAccessSteps.validateMaintainAccessForRepo(repo, {checked: maintain});
854
885
  }
855
886
 
856
- function verifyDisabledUserAuth(repo, {read = false, write = false, graphql = false, manage = false} = {}) {
887
+ function verifyDisabledUserAuth(repo, {read = false, write = false, graphql = false, maintain = false} = {}) {
857
888
  UserAndAccessSteps.validateReadAccessForRepo(repo, {disabled: read});
858
889
  UserAndAccessSteps.validateWriteAccessForRepo(repo, {disabled: write});
859
890
  UserAndAccessSteps.validateGraphqlAccessForRepo(repo, {disabled: graphql});
860
- UserAndAccessSteps.validateManageAccessForRepo(repo, {disabled: manage});
891
+ UserAndAccessSteps.validateMaintainAccessForRepo(repo, {disabled: maintain});
861
892
  }
862
893
 
863
894
  function navigateMenuPath(pathArray, expectedUrl, expectedTitle) {
@@ -230,7 +230,7 @@ describe('TTYG chat list', () => {
230
230
  HomeSteps.visit();
231
231
  cy.wait('@get-chat');
232
232
  // and came back to the ttyg page
233
- TTYGViewSteps.visit();
233
+ TTYGViewSteps.visit(false);
234
234
 
235
235
  // Then I expect to last used chat be selected.
236
236
  TTYGViewSteps.getChatFromGroup(0, 2).should('have.class', 'selected');
@@ -61,7 +61,7 @@ describe('TTYG create chat', () => {
61
61
  // and returns to the TTYG page
62
62
  TTYGStubs.stubChatsListGet("/ttyg/chats/create/get-chats-after-create.json");
63
63
  TTYGStubs.stubAgentGet();
64
- TTYGViewSteps.visit();
64
+ TTYGViewSteps.visit(false);
65
65
  cy.wait('@get-chat-list');
66
66
  // Then I expect newly created chat be selected.
67
67
  TTYGViewSteps.getChatFromGroup(0, 0).should('contain', 'New chat of Han Solo is a character');
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
  ];
@@ -0,0 +1,106 @@
1
+ # edited ODBA file
2
+ [PrefixDeclaration]
3
+ : http://example.org/voc#
4
+ ex: http://example.org/
5
+ owl: http://www.w3.org/2002/07/owl#
6
+ rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
7
+ xml: http://www.w3.org/XML/1998/namespace
8
+ xsd: http://www.w3.org/2001/XMLSchema#
9
+ foaf: http://xmlns.com/foaf/0.1/
10
+ obda: https://w3id.org/obda/vocabulary#
11
+ rdfs: http://www.w3.org/2000/01/rdf-schema#
12
+
13
+ [MappingDeclaration] @collection [[
14
+ mappingId uni1-student
15
+ target :uni1/student/{s_id} a :Student ; foaf:firstName {first_name}^^xsd:string ; foaf:lastName {last_name}^^xsd:string .
16
+ source SELECT * FROM "uni1"."student"
17
+
18
+ mappingId uni1-academic
19
+ target :uni1/academic/{a_id} a :FacultyMember ; foaf:firstName {first_name}^^xsd:string ; foaf:lastName {last_name}^^xsd:string .
20
+ source SELECT * FROM "uni1"."academic"
21
+
22
+ mappingId uni1-fullProfessor
23
+ target :uni1/academic/{a_id} a :FullProfessor .
24
+ source SELECT * FROM "uni1"."academic"
25
+ WHERE "position" = 1
26
+
27
+ mappingId uni1-AssociateProfessor
28
+ target :uni1/academic/{a_id} a :AssociateProfessor .
29
+ source SELECT * FROM "uni1"."academic"
30
+ WHERE "position" = 2
31
+
32
+ mappingId uni1-PostDoc
33
+ target :uni1/academic/{a_id} a :PostDoc .
34
+ source SELECT * FROM "uni1"."academic"
35
+ WHERE "position" = 9
36
+
37
+ mappingId uni1-externalTeacher
38
+ target :uni1/academic/{a_id} a :ExternalTeacher .
39
+ source SELECT * FROM "uni1"."academic"
40
+ WHERE "position" = 8
41
+
42
+ mappingId uni1-teaching
43
+ target :uni1/academic/{a_id} :teaches :uni1/course/{c_id} .
44
+ source SELECT * FROM "uni1"."teaching"
45
+
46
+ mappingId uni1-course
47
+ target :uni1/course/{c_id} a :Course ; :title {title} ; :isGivenAt :uni1/university .
48
+ source SELECT * FROM "uni1"."course"
49
+
50
+ mappingId uni1-registration
51
+ target :uni1/student/{s_id} :attends :uni1/course/{c_id} .
52
+ source SELECT *
53
+ FROM "uni1"."course-registration"
54
+
55
+ mappingId uni2-person
56
+ target :uni2/person/{pid} a foaf:Person ; foaf:firstName {fname}^^xsd:string ; foaf:lastName {lname}^^xsd:string .
57
+ source SELECT * FROM "uni2"."person"
58
+
59
+ mappingId uni2-undergraduate
60
+ target :uni2/person/{pid} a :UndergraduateStudent .
61
+ source SELECT * FROM "uni2"."person"
62
+ WHERE "status" = 1
63
+
64
+ mappingId uni2-graduate
65
+ target :uni2/person/{pid} a :GraduateStudent .
66
+ source SELECT * FROM "uni2"."person"
67
+ WHERE "status" = 2
68
+
69
+ mappingId uni2-fullProfessor
70
+ target :uni2/person/{pid} a :FullProfessor .
71
+ source SELECT * FROM "uni2"."person"
72
+ WHERE "status" = 7
73
+
74
+ mappingId uni2-associate-prof
75
+ target :uni2/person/{pid} a :AssociateProfessor .
76
+ source SELECT * FROM "uni2"."person"
77
+ WHERE "status" = 8
78
+
79
+ mappingId uni2-course
80
+ target :uni2/course/{cid} a :Course ; :title {topic}^^xsd:string ; :isGivenAt :uni2/university .
81
+ source SELECT * FROM "uni2"."course"
82
+
83
+ mappingId uni2-lecturer
84
+ target :uni2/person/{lecturer} :givesLecture :uni2/course/{cid} .
85
+ source SELECT * FROM "uni2"."course"
86
+
87
+ mappingId uni2-assistantProfessor
88
+ target :uni2/person/{pid} a :AssistantProfessor .
89
+ source SELECT * FROM "uni2"."person"
90
+ WHERE "status" = 9
91
+
92
+ mappingId uni2-postDoc
93
+ target :uni2/person/{pid} a :PostDoc .
94
+ source SELECT * FROM "uni2"."person"
95
+ WHERE "status" = 3
96
+
97
+ mappingId uni2-lab-teacher
98
+ target :uni2/person/{lab_teacher} :givesLab :uni2/course/{cid} .
99
+ source SELECT * FROM "uni2"."course"
100
+
101
+ mappingId uni2-registration
102
+ target :uni2/person/{pid} :attends :uni2/course/{cid} .
103
+ source SELECT *
104
+ FROM "uni2"."registration"
105
+ ]]
106
+
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "graphdb-workbench-tests",
3
- "version": "3.5.0-TR8",
3
+ "version": "3.5.0-loader-TR1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "graphdb-workbench-tests",
9
- "version": "3.5.0-TR8",
9
+ "version": "3.5.0-loader-TR1",
10
10
  "license": "Apache-2.0",
11
11
  "devDependencies": {
12
12
  "@bahmutov/cypress-code-coverage": "^2.7.2",
@@ -3343,9 +3343,9 @@
3343
3343
  "license": "MIT"
3344
3344
  },
3345
3345
  "node_modules/brace-expansion": {
3346
- "version": "1.1.16",
3347
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz",
3348
- "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==",
3346
+ "version": "1.1.18",
3347
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
3348
+ "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
3349
3349
  "dev": true,
3350
3350
  "license": "MIT",
3351
3351
  "dependencies": {
@@ -5407,9 +5407,9 @@
5407
5407
  "license": "MIT"
5408
5408
  },
5409
5409
  "node_modules/fast-uri": {
5410
- "version": "3.1.4",
5411
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz",
5412
- "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==",
5410
+ "version": "3.1.5",
5411
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz",
5412
+ "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==",
5413
5413
  "dev": true,
5414
5414
  "funding": [
5415
5415
  {
@@ -7728,9 +7728,9 @@
7728
7728
  }
7729
7729
  },
7730
7730
  "node_modules/mocha/node_modules/brace-expansion": {
7731
- "version": "5.0.7",
7732
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz",
7733
- "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==",
7731
+ "version": "5.0.9",
7732
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
7733
+ "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
7734
7734
  "dev": true,
7735
7735
  "license": "MIT",
7736
7736
  "peer": true,
@@ -7738,7 +7738,7 @@
7738
7738
  "balanced-match": "^4.0.2"
7739
7739
  },
7740
7740
  "engines": {
7741
- "node": "18 || 20 || >=22"
7741
+ "node": "20 || >=22"
7742
7742
  }
7743
7743
  },
7744
7744
  "node_modules/mocha/node_modules/glob": {
@@ -9086,16 +9086,16 @@
9086
9086
  }
9087
9087
  },
9088
9088
  "node_modules/rimraf/node_modules/brace-expansion": {
9089
- "version": "5.0.7",
9090
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz",
9091
- "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==",
9089
+ "version": "5.0.9",
9090
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
9091
+ "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
9092
9092
  "dev": true,
9093
9093
  "license": "MIT",
9094
9094
  "dependencies": {
9095
9095
  "balanced-match": "^4.0.2"
9096
9096
  },
9097
9097
  "engines": {
9098
- "node": "18 || 20 || >=22"
9098
+ "node": "20 || >=22"
9099
9099
  }
9100
9100
  },
9101
9101
  "node_modules/rimraf/node_modules/glob": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphdb-workbench-tests",
3
- "version": "3.5.0-TR8",
3
+ "version": "3.5.0-loader-TR1",
4
4
  "description": "Cypress tests for GraphDB workbench",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -10,7 +10,8 @@
10
10
  "cy:open-legacy": "cypress open --config-file cypress-legacy.config.js",
11
11
  "cy:open-security": "cypress open --config-file cypress-security.config.js",
12
12
  "cy:open-flaky": "cypress open --config-file cypress-flaky.config.js",
13
- "cy:guides": "cypress run --config-file cypress-legacy.config.js --spec \"e2e-legacy/guides/**/*.spec.js\" --browser chrome",
13
+ "cy:open-guides": "cypress open --config-file cypress-guides.config.js",
14
+ "cy:run-guides": "cypress run --config-file cypress-guides.config.js",
14
15
  "cy:run": "npm run cy:run-legacy && cypress run",
15
16
  "cy:run:partial": "cypress run --config-file cypress-legacy.config.js --spec \"e2e-legacy/ttyg/**/*.spec.js\" --browser chrome",
16
17
  "cy:run-legacy": "cypress run --config-file cypress-legacy.config.js --browser chrome",
@@ -0,0 +1,13 @@
1
+ export class DeprecationSteps {
2
+ static getDeprecationBanner() {
3
+ return cy.get('onto-deprecation-banner');
4
+ }
5
+
6
+ static getCloseButton() {
7
+ return DeprecationSteps.getDeprecationBanner().find('.close-button');
8
+ }
9
+
10
+ static closeBanner() {
11
+ DeprecationSteps.getCloseButton().click();
12
+ }
13
+ }
@@ -9,10 +9,22 @@ export class OntopRepositorySteps {
9
9
  return cy.get('div').contains("OBDA or R2RML file *").parent();
10
10
  }
11
11
 
12
+ static getPage() {
13
+ return cy.get('#wb-repository');
14
+ }
15
+
12
16
  static getOBDAUploadButton() {
13
17
  return cy.get('span[for="obdaFile"]').contains("Upload file...");
14
18
  }
15
19
 
20
+ static getOBDAFileFieldEditButton() {
21
+ return OntopRepositorySteps.getOBDAFileField().find('.ot-edit-input');
22
+ }
23
+
24
+ static editOBDAFile() {
25
+ OntopRepositorySteps.getOBDAFileFieldEditButton().click();
26
+ }
27
+
16
28
  static getOntologyFileField() {
17
29
  return cy.get('div').contains("Ontology file");
18
30
  }
@@ -119,9 +131,17 @@ export class OntopRepositorySteps {
119
131
  OntopRepositorySteps.getOBDAUploadButton().click();
120
132
  }
121
133
 
134
+ static getAdditionalJDBCProperties() {
135
+ return OntopRepositorySteps.getPage().find('.additional-jdbc-properties');
136
+ }
137
+
122
138
  static uploadObdaFile(file) {
123
139
  // The label for the input has visibility: hidden, so force must be used
124
140
  // eq() index 0 for location of OBDA field input
125
141
  cy.get('input[type=file]').eq(0).selectFile(file, {force: true});
126
142
  }
143
+
144
+ static getOntopSaveButton() {
145
+ return cy.get('#addEditOntopRepository');
146
+ }
127
147
  }
@@ -303,7 +303,7 @@ export class UserAndAccessSteps {
303
303
  return cy.get(repoLineAlias).find('.ri-edit-line');
304
304
  }
305
305
 
306
- static findManageIconAlias(repoLineAlias) {
306
+ static findMaintainIconAlias(repoLineAlias) {
307
307
  return cy.get(repoLineAlias).find('.ri-folder-settings-line');
308
308
  }
309
309
 
@@ -382,24 +382,24 @@ export class UserAndAccessSteps {
382
382
  this.validateRightsForRepo(repoName, writeAccessCheckbox, expectedState);
383
383
  }
384
384
 
385
- // ============= Manange Repository Access Toggles and Validations =============
385
+ // ============= Maintain Repository Access Toggles and Validations =============
386
386
 
387
- static getManageAccessRepoCheckbox(repoName) {
387
+ static getMaintainAccessRepoCheckbox(repoName) {
388
388
  return this.getRepositoryRightsLine(repoName)
389
- .find('.manage-repository');
389
+ .find('.maintain-repository');
390
390
  }
391
391
 
392
- static clickManageAccessRepo(repoName) {
393
- UserAndAccessSteps.getManageAccessRepoCheckbox(repoName).realClick();
392
+ static clickMaintainAccessRepo(repoName) {
393
+ UserAndAccessSteps.getMaintainAccessRepoCheckbox(repoName).realClick();
394
394
  }
395
395
 
396
- static toggleManageRepoForRepo(repoName) {
397
- return this.clickManageAccessRepo(repoName);
396
+ static toggleMaintainRepoForRepo(repoName) {
397
+ return this.clickMaintainAccessRepo(repoName);
398
398
  }
399
399
 
400
- static validateManageAccessForRepo(repoName, expectedState) {
401
- const manageAccessCheckbox = this.getManageAccessRepoCheckbox(repoName);
402
- this.validateRightsForRepo(repoName, manageAccessCheckbox, expectedState);
400
+ static validateMaintainAccessForRepo(repoName, expectedState) {
401
+ const maintainAccessCheckbox = this.getMaintainAccessRepoCheckbox(repoName);
402
+ this.validateRightsForRepo(repoName, maintainAccessCheckbox, expectedState);
403
403
  }
404
404
 
405
405
  // ============= GraphQL Access Toggles and Validations =============
@@ -2,9 +2,20 @@ import {BaseSteps} from "../base-steps";
2
2
  import {DeprecationSteps} from '../deprecation-banner/deprecation-banner-steps.js';
3
3
 
4
4
  export class TTYGViewSteps extends BaseSteps {
5
- static visit() {
5
+ /**
6
+ * Visits the TTYG page and closes the Solr deprecation banner by default.
7
+ *
8
+ * @param {boolean} closeSolrBanner Whether to close the banner. Set to `false`
9
+ * when revisiting the page after the banner has already been closed.
10
+ */
11
+ static visit(closeSolrBanner = true) {
6
12
  cy.visit('/ttyg');
7
- DeprecationSteps.closeBanner();
13
+ // Temporary workaround until the Solr deprecation banner is removed.
14
+ // The banner changes the page layout, causing tests to fail randomly.
15
+ // This quick fix prevents GraphDB build failures and should be deleted together with the banner.
16
+ if (closeSolrBanner) {
17
+ DeprecationSteps.closeBanner();
18
+ }
8
19
  }
9
20
 
10
21
  static getTtygView() {
@@ -247,4 +247,8 @@ export class RepositoriesStubs extends Stubs {
247
247
  }
248
248
  });
249
249
  }
250
+
251
+ static spyGetJDBCProperties() {
252
+ cy.intercept('GET', '/rest/repositories/ontop/jdbc-properties?**').as('getJDBCProperties');
253
+ }
250
254
  }
@@ -29,6 +29,30 @@ Cypress.Commands.add('loginAsAdmin', () => {
29
29
  });
30
30
  });
31
31
 
32
+ Cypress.Commands.add('loginAs', (username, password) => {
33
+ return cy.request({
34
+ method: 'POST',
35
+ url: '/rest/login',
36
+ body: {
37
+ username,
38
+ password,
39
+ },
40
+ headers: {
41
+ 'Content-Type': 'application/json',
42
+ },
43
+ failOnStatusCode: true,
44
+ }).then((response) => {
45
+ const authHeader = response.headers['authorization'];
46
+ const token = Array.isArray(authHeader)
47
+ ? authHeader[0]
48
+ : authHeader;
49
+ cy.window().then((win) => {
50
+ win.localStorage.setItem('ontotext.gdb.auth.jwt', token);
51
+ win.localStorage.setItem('ontotext.gdb.auth.authenticated', 'true');
52
+ });
53
+ });
54
+ });
55
+
32
56
  Cypress.Commands.add('switchOffSecurity', (secured = false) => {
33
57
  let headers = {'Content-Type': 'application/json'};
34
58
  if (secured) {
@@ -64,3 +88,22 @@ Cypress.Commands.add('switchOffFreeAccess', (secured = false) => {
64
88
  failOnStatusCode: true,
65
89
  });
66
90
  });
91
+
92
+ Cypress.Commands.add('switchOnFreeAccess', (secured = false) => {
93
+ let headers = {'Content-Type': 'application/json'};
94
+ if (secured) {
95
+ const authHeader = Cypress.env('adminToken');
96
+ headers = {...headers,
97
+ 'Authorization': authHeader
98
+ }
99
+ }
100
+ return cy.request({
101
+ method: 'POST',
102
+ url: '/rest/security/free-access',
103
+ body: {
104
+ 'enabled': true
105
+ },
106
+ headers,
107
+ failOnStatusCode: false,
108
+ });
109
+ });