[arvados-workbench2] created: 2.4.0-363-g9123f234
git repository hosting
git at public.arvados.org
Fri Dec 9 20:15:30 UTC 2022
at 9123f234b9b8240cbcd8570421d87fe3af6b97e4 (commit)
commit 9123f234b9b8240cbcd8570421d87fe3af6b97e4
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date: Fri Dec 9 21:15:04 2022 +0100
19691: Adds tests.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>
diff --git a/cypress/integration/collection.spec.js b/cypress/integration/collection.spec.js
index 74506aea..06436d1d 100644
--- a/cypress/integration/collection.spec.js
+++ b/cypress/integration/collection.spec.js
@@ -75,6 +75,55 @@ describe('Collection panel tests', function () {
});
});
+ it('attempts to use a preexisting name creating or updating a collection', function() {
+ const name = `Test collection ${Math.floor(Math.random() * 999999)}`;
+ cy.createCollection(adminUser.token, {
+ name: name,
+ owner_uuid: activeUser.user.uuid,
+ manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
+ });
+ cy.loginAs(activeUser);
+ cy.goToPath(`/projects/${activeUser.user.uuid}`);
+ cy.get('[data-cy=breadcrumb-first]').should('contain', 'Projects');
+ cy.get('[data-cy=breadcrumb-last]').should('not.exist');
+ // Attempt to create new collection with a duplicate name
+ cy.get('[data-cy=side-panel-button]').click();
+ cy.get('[data-cy=side-panel-new-collection]').click();
+ cy.get('[data-cy=form-dialog]')
+ .should('contain', 'New collection')
+ .within(() => {
+ cy.get('[data-cy=name-field]').within(() => {
+ cy.get('input').type(name);
+ });
+ cy.get('[data-cy=form-submit-btn]').click();
+ });
+ // Error message should display, allowing editing the name
+ cy.get('[data-cy=form-dialog]').should('exist')
+ .and('contain', 'Collection with the same name already exists')
+ .within(() => {
+ cy.get('[data-cy=name-field]').within(() => {
+ cy.get('input').type(' renamed');
+ });
+ cy.get('[data-cy=form-submit-btn]').click();
+ });
+ cy.get('[data-cy=form-dialog]').should('not.exist');
+ // Attempt to rename the collection with the duplicate name
+ cy.get('[data-cy=collection-panel-options-btn]').click();
+ cy.get('[data-cy=context-menu]').contains('Edit collection').click();
+ cy.get('[data-cy=form-dialog]')
+ .should('contain', 'Edit Collection')
+ .within(() => {
+ cy.get('[data-cy=name-field]').within(() => {
+ cy.get('input')
+ .type('{selectall}{backspace}')
+ .type(name);
+ });
+ cy.get('[data-cy=form-submit-btn]').click();
+ });
+ cy.get('[data-cy=form-dialog]').should('exist')
+ .and('contain', 'Collection with the same name already exists');
+ });
+
it('uses the property editor (from edit dialog) with vocabulary terms', function () {
cy.createCollection(adminUser.token, {
name: `Test collection ${Math.floor(Math.random() * 999999)}`,
diff --git a/cypress/integration/project.spec.js b/cypress/integration/project.spec.js
index 93e4257b..bbb3571a 100644
--- a/cypress/integration/project.spec.js
+++ b/cypress/integration/project.spec.js
@@ -158,6 +158,38 @@ describe('Project tests', function() {
cy.get('[data-cy=breadcrumb-last]').should('contain', subProjName);
});
+ it('attempts to use a preexisting name creating a project', function() {
+ const name = `Test project ${Math.floor(Math.random() * 999999)}`;
+ cy.createGroup(activeUser.token, {
+ name: name,
+ group_class: 'project',
+ });
+ cy.loginAs(activeUser);
+ cy.goToPath(`/projects/${activeUser.user.uuid}`);
+
+ // Attempt to create new collection with a duplicate name
+ cy.get('[data-cy=side-panel-button]').click();
+ cy.get('[data-cy=side-panel-new-project]').click();
+ cy.get('[data-cy=form-dialog]')
+ .should('contain', 'New Project')
+ .within(() => {
+ cy.get('[data-cy=name-field]').within(() => {
+ cy.get('input').type(name);
+ });
+ cy.get('[data-cy=form-submit-btn]').click();
+ });
+ // Error message should display, allowing editing the name
+ cy.get('[data-cy=form-dialog]').should('exist')
+ .and('contain', 'Project with the same name already exists')
+ .within(() => {
+ cy.get('[data-cy=name-field]').within(() => {
+ cy.get('input').type(' renamed');
+ });
+ cy.get('[data-cy=form-submit-btn]').click();
+ });
+ cy.get('[data-cy=form-dialog]').should('not.exist');
+ });
+
it('navigates to the parent project after trashing the one being displayed', function() {
cy.createGroup(activeUser.token, {
name: `Test root project ${Math.floor(Math.random() * 999999)}`,
@@ -313,12 +345,12 @@ describe('Project tests', function() {
});
describe('Frozen projects', () => {
- beforeEach(() => {
+ beforeEach(() => {
cy.createGroup(activeUser.token, {
name: `Main project ${Math.floor(Math.random() * 999999)}`,
group_class: 'project',
}).as('mainProject');
-
+
cy.createGroup(adminUser.token, {
name: `Admin project ${Math.floor(Math.random() * 999999)}`,
group_class: 'project',
@@ -337,7 +369,7 @@ describe('Project tests', function() {
name: `Main collection ${Math.floor(Math.random() * 999999)}`,
owner_uuid: mainProject.uuid,
manifest_text: "./subdir 37b51d194a7513e45b56f6524f2d51f2+3 0:3:foo\n. 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
- }).as('mainCollection');
+ }).as('mainCollection');
});
});
@@ -398,7 +430,7 @@ describe('Project tests', function() {
cy.get('[data-cy=context-menu]').contains('Unfreeze').click();
cy.get('main').contains(adminProject.name).rightclick();
-
+
cy.get('[data-cy=context-menu]').contains('Freeze').should('exist');
});
});
commit 6ffe67b266e94bb69098e46b102833c845288dba
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date: Fri Dec 9 17:20:07 2022 +0100
19691: Show unknown errors on project & collection creation dialogs.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>
diff --git a/src/store/collections/collection-create-actions.ts b/src/store/collections/collection-create-actions.ts
index 92e773c9..939ae9f9 100644
--- a/src/store/collections/collection-create-actions.ts
+++ b/src/store/collections/collection-create-actions.ts
@@ -68,11 +68,11 @@ export const createCollection = (data: CollectionCreateFormDialogData) =>
const error = getCommonResourceServiceError(e);
if (error === CommonResourceServiceError.UNIQUE_NAME_VIOLATION) {
dispatch(stopSubmit(COLLECTION_CREATE_FORM_NAME, { name: 'Collection with the same name already exists.' } as FormErrors));
- } else if (error === CommonResourceServiceError.NONE) {
+ } else {
dispatch(stopSubmit(COLLECTION_CREATE_FORM_NAME));
dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_CREATE_FORM_NAME }));
dispatch(snackbarActions.OPEN_SNACKBAR({
- message: 'Collection has not been created.',
+ message: e.errors.join(''),
hideDuration: 2000,
kind: SnackbarKind.ERROR
}));
diff --git a/src/store/projects/project-create-actions.ts b/src/store/projects/project-create-actions.ts
index ddf5064e..e70ff0f6 100644
--- a/src/store/projects/project-create-actions.ts
+++ b/src/store/projects/project-create-actions.ts
@@ -20,6 +20,8 @@ import { ServiceRepository } from 'services/services';
import { matchProjectRoute, matchRunProcessRoute } from 'routes/routes';
import { RouterState } from "react-router-redux";
import { GroupClass } from "models/group";
+import { snackbarActions, SnackbarKind } from "store/snackbar/snackbar-actions";
+import { progressIndicatorActions } from "store/progress-indicator/progress-indicator-actions";
export interface ProjectCreateFormDialogData {
ownerUuid: string;
@@ -65,6 +67,7 @@ export const createProject = (project: Partial<ProjectResource>) =>
async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
dispatch(startSubmit(PROJECT_CREATE_FORM_NAME));
try {
+ dispatch(progressIndicatorActions.START_WORKING(PROJECT_CREATE_FORM_NAME));
const newProject = await services.projectService.create(project, false);
dispatch(dialogActions.CLOSE_DIALOG({ id: PROJECT_CREATE_FORM_NAME }));
dispatch(reset(PROJECT_CREATE_FORM_NAME));
@@ -73,7 +76,17 @@ export const createProject = (project: Partial<ProjectResource>) =>
const error = getCommonResourceServiceError(e);
if (error === CommonResourceServiceError.UNIQUE_NAME_VIOLATION) {
dispatch(stopSubmit(PROJECT_CREATE_FORM_NAME, { name: 'Project with the same name already exists.' } as FormErrors));
+ } else {
+ dispatch(stopSubmit(PROJECT_CREATE_FORM_NAME));
+ dispatch(dialogActions.CLOSE_DIALOG({ id: PROJECT_CREATE_FORM_NAME }));
+ dispatch(snackbarActions.OPEN_SNACKBAR({
+ message: e.errors.join(''),
+ hideDuration: 2000,
+ kind: SnackbarKind.ERROR
+ }));
}
return undefined;
+ } finally {
+ dispatch(progressIndicatorActions.STOP_WORKING(PROJECT_CREATE_FORM_NAME));
}
};
commit 78a93ff46e7e9a38b9865fa743c88e1008adc81e
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date: Fri Dec 9 17:00:31 2022 +0100
19691: Avoid showing generic errors on collection & project create dialogs.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>
diff --git a/src/store/collections/collection-create-actions.ts b/src/store/collections/collection-create-actions.ts
index 17fecc1e..92e773c9 100644
--- a/src/store/collections/collection-create-actions.ts
+++ b/src/store/collections/collection-create-actions.ts
@@ -59,7 +59,7 @@ export const createCollection = (data: CollectionCreateFormDialogData) =>
let newCollection: CollectionResource | undefined;
try {
dispatch(progressIndicatorActions.START_WORKING(COLLECTION_CREATE_FORM_NAME));
- newCollection = await services.collectionService.create(data);
+ newCollection = await services.collectionService.create(data, false);
await dispatch<any>(uploadCollectionFiles(newCollection.uuid));
dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_CREATE_FORM_NAME }));
dispatch(reset(COLLECTION_CREATE_FORM_NAME));
diff --git a/src/store/projects/project-create-actions.ts b/src/store/projects/project-create-actions.ts
index 23eaf7a4..ddf5064e 100644
--- a/src/store/projects/project-create-actions.ts
+++ b/src/store/projects/project-create-actions.ts
@@ -65,7 +65,7 @@ export const createProject = (project: Partial<ProjectResource>) =>
async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
dispatch(startSubmit(PROJECT_CREATE_FORM_NAME));
try {
- const newProject = await services.projectService.create(project);
+ const newProject = await services.projectService.create(project, false);
dispatch(dialogActions.CLOSE_DIALOG({ id: PROJECT_CREATE_FORM_NAME }));
dispatch(reset(PROJECT_CREATE_FORM_NAME));
return newProject;
commit 16d7bc7663c99f73f8f129d60021e6f3ebaec2a4
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date: Fri Dec 9 17:00:07 2022 +0100
19691: Passes showErrors param on service layer's create method.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>
diff --git a/src/services/collection-service/collection-service.ts b/src/services/collection-service/collection-service.ts
index c1d57802..d08e7899 100644
--- a/src/services/collection-service/collection-service.ts
+++ b/src/services/collection-service/collection-service.ts
@@ -35,8 +35,8 @@ export class CollectionService extends TrashableResourceService<CollectionResour
return super.get(uuid, showErrors, selectParam, session);
}
- create(data?: Partial<CollectionResource>) {
- return super.create({ ...data, preserveVersion: true });
+ create(data?: Partial<CollectionResource>, showErrors?: boolean) {
+ return super.create({ ...data, preserveVersion: true }, showErrors);
}
update(uuid: string, data: Partial<CollectionResource>, showErrors?: boolean) {
diff --git a/src/services/common-service/common-resource-service.ts b/src/services/common-service/common-resource-service.ts
index ce66aa37..d9be8dae 100644
--- a/src/services/common-service/common-resource-service.ts
+++ b/src/services/common-service/common-resource-service.ts
@@ -26,7 +26,7 @@ export class CommonResourceService<T extends Resource> extends CommonService<T>
]));
}
- create(data?: Partial<T>) {
+ create(data?: Partial<T>, showErrors?: boolean) {
let payload: any;
if (data !== undefined) {
this.readOnlyFields.forEach( field => delete data[field] );
@@ -34,7 +34,7 @@ export class CommonResourceService<T extends Resource> extends CommonService<T>
[this.resourceType.slice(0, -1)]: CommonService.mapKeys(snakeCase)(data),
};
}
- return super.create(payload);
+ return super.create(payload, showErrors);
}
update(uuid: string, data: Partial<T>, showErrors?: boolean, select?: string[]) {
diff --git a/src/services/project-service/project-service.ts b/src/services/project-service/project-service.ts
index 07b083fd..442a6ab9 100644
--- a/src/services/project-service/project-service.ts
+++ b/src/services/project-service/project-service.ts
@@ -9,9 +9,9 @@ import { ListArguments } from "services/common-service/common-service";
import { FilterBuilder, joinFilters } from "services/api/filter-builder";
export class ProjectService extends GroupsService<ProjectResource> {
- create(data: Partial<ProjectResource>) {
+ create(data: Partial<ProjectResource>, showErrors?: boolean) {
const projectData = { ...data, groupClass: GroupClass.PROJECT };
- return super.create(projectData);
+ return super.create(projectData, showErrors);
}
list(args: ListArguments = {}) {
commit 5c1132153fa250f46de7954c8faeb456b96fe830
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date: Fri Dec 9 16:46:11 2022 +0100
19691: Avoid showing generic errors on collection & project update dialogs.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>
diff --git a/src/store/collections/collection-update-actions.ts b/src/store/collections/collection-update-actions.ts
index bf9c6449..2e66ce2c 100644
--- a/src/store/collections/collection-update-actions.ts
+++ b/src/store/collections/collection-update-actions.ts
@@ -52,7 +52,7 @@ export const updateCollection = (collection: CollectionUpdateFormDialogData) =>
name: collection.name,
storageClassesDesired: collection.storageClassesDesired,
description: collection.description,
- properties: collection.properties }
+ properties: collection.properties }, false
).then(updatedCollection => {
updatedCollection = {...cachedCollection, ...updatedCollection};
dispatch(collectionPanelActions.SET_COLLECTION(updatedCollection));
diff --git a/src/store/projects/project-update-actions.ts b/src/store/projects/project-update-actions.ts
index a6e67485..a9255e29 100644
--- a/src/store/projects/project-update-actions.ts
+++ b/src/store/projects/project-update-actions.ts
@@ -61,7 +61,8 @@ export const updateProject = (project: ProjectUpdateFormDialogData) =>
name: project.name,
description: project.description,
properties: project.properties,
- });
+ },
+ false);
dispatch(projectPanelActions.REQUEST_ITEMS());
dispatch(reset(PROJECT_UPDATE_FORM_NAME));
dispatch(dialogActions.CLOSE_DIALOG({ id: PROJECT_UPDATE_FORM_NAME }));
commit 85a30bc44cf21218a32be5aaf013faa262ae85e4
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date: Fri Dec 9 16:43:26 2022 +0100
19691: Passes showErrors param on service layer's update method.
Also, fixes error matching used to detect UniqueViolation errors, among
other types.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>
diff --git a/src/services/collection-service/collection-service.ts b/src/services/collection-service/collection-service.ts
index e2c420d8..c1d57802 100644
--- a/src/services/collection-service/collection-service.ts
+++ b/src/services/collection-service/collection-service.ts
@@ -39,9 +39,9 @@ export class CollectionService extends TrashableResourceService<CollectionResour
return super.create({ ...data, preserveVersion: true });
}
- update(uuid: string, data: Partial<CollectionResource>) {
+ update(uuid: string, data: Partial<CollectionResource>, showErrors?: boolean) {
const select = [...Object.keys(data), 'version', 'modifiedAt'];
- return super.update(uuid, { ...data, preserveVersion: true }, select);
+ return super.update(uuid, { ...data, preserveVersion: true }, showErrors, select);
}
async files(uuid: string) {
diff --git a/src/services/common-service/common-resource-service.ts b/src/services/common-service/common-resource-service.ts
index c6306779..ce66aa37 100644
--- a/src/services/common-service/common-resource-service.ts
+++ b/src/services/common-service/common-resource-service.ts
@@ -37,7 +37,7 @@ export class CommonResourceService<T extends Resource> extends CommonService<T>
return super.create(payload);
}
- update(uuid: string, data: Partial<T>, select?: string[]) {
+ update(uuid: string, data: Partial<T>, showErrors?: boolean, select?: string[]) {
let payload: any;
if (data !== undefined) {
this.readOnlyFields.forEach( field => delete data[field] );
@@ -48,12 +48,12 @@ export class CommonResourceService<T extends Resource> extends CommonService<T>
payload.select = ['uuid', ...select.map(field => snakeCase(field))];
};
}
- return super.update(uuid, payload);
+ return super.update(uuid, payload, showErrors);
}
}
export const getCommonResourceServiceError = (errorResponse: any) => {
- if ('errors' in errorResponse && 'errorToken' in errorResponse) {
+ if ('errors' in errorResponse) {
const error = errorResponse.errors.join('');
switch (true) {
case /UniqueViolation/.test(error):
diff --git a/src/services/common-service/common-service.ts b/src/services/common-service/common-service.ts
index b8e7dc67..fe7467a6 100644
--- a/src/services/common-service/common-service.ts
+++ b/src/services/common-service/common-service.ts
@@ -175,12 +175,14 @@ export class CommonService<T> {
}
}
- update(uuid: string, data: Partial<T>) {
+ update(uuid: string, data: Partial<T>, showErrors?: boolean) {
this.validateUuid(uuid);
return CommonService.defaultResponse(
this.serverApi
.put<T>(`/${this.resourceType}/${uuid}`, data && CommonService.mapKeys(snakeCase)(data)),
- this.actions
+ this.actions,
+ false,
+ showErrors
);
}
}
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list