diff --git a/cypress.json b/cypress.json index c9676a739..70637b8e1 100644 --- a/cypress.json +++ b/cypress.json @@ -1,3 +1,4 @@ { - "baseUrl": "http://web.graasp.org:3111" + "baseUrl": "http://web.graasp.org:3111", + "video": false } diff --git a/cypress/integration/copyItem.spec.js b/cypress/integration/copyItem.spec.js deleted file mode 100644 index 111a13773..000000000 --- a/cypress/integration/copyItem.spec.js +++ /dev/null @@ -1,109 +0,0 @@ -import { ROOT_ID } from '../../src/config/constants'; -import { buildItemPath } from '../../src/config/paths'; -import { - buildItemCard, - buildItemMenu, - buildTreeItemClass, - ITEM_MENU_BUTTON_CLASS, - ITEM_MENU_COPY_BUTTON_CLASS, - TREE_MODAL_CONFIRM_BUTTON_ID, - TREE_MODAL_TREE_ID, -} from '../../src/config/selectors'; -import { SIMPLE_ITEMS } from '../fixtures/items'; - -const copyItem = (id, toItemId) => { - const menuSelector = `#${buildItemCard(id)} .${ITEM_MENU_BUTTON_CLASS}`; - cy.get(menuSelector).click(); - cy.get(`#${buildItemMenu(id)} .${ITEM_MENU_COPY_BUTTON_CLASS}`).click(); - - cy.get( - `#${TREE_MODAL_TREE_ID} .${buildTreeItemClass( - toItemId, - )} .MuiTreeItem-label`, - ) - .first() - .click(); - - cy.get(`#${TREE_MODAL_CONFIRM_BUTTON_ID}`).click(); -}; - -describe('Copy Item', () => { - it('copy item on Home', () => { - cy.setUpApi({ items: SIMPLE_ITEMS }); - cy.visit('/'); - - // move - const { id: movedItem } = SIMPLE_ITEMS[0]; - const { id: toItem } = SIMPLE_ITEMS[1]; - copyItem(movedItem, toItem); - - cy.wait('@copyItem').then(({ response: { body } }) => { - cy.get(`#${buildItemCard(movedItem)}`).should('exist'); - - // check in new parent - cy.goToItem(toItem); - cy.get(`#${buildItemCard(body.id)}`).should('exist'); - }); - }); - - it('copy item in item', () => { - cy.setUpApi({ items: SIMPLE_ITEMS }); - const { id } = SIMPLE_ITEMS[0]; - - // go to children item - cy.visit(buildItemPath(id)); - - // move - const { id: movedItem } = SIMPLE_ITEMS[2]; - const { id: toItem } = SIMPLE_ITEMS[3]; - copyItem(movedItem, toItem); - - cy.wait('@copyItem').then(({ response: { body } }) => { - cy.get(`#${buildItemCard(movedItem)}`).should('exist'); - - // check in new parent - cy.goToItem(toItem); - cy.get(`#${buildItemCard(body.id)}`).should('exist'); - }); - }); - - it('copy item to Home', () => { - cy.setUpApi({ items: SIMPLE_ITEMS }); - const { id } = SIMPLE_ITEMS[0]; - - // go to children item - cy.visit(buildItemPath(id)); - - // move - const { id: movedItem } = SIMPLE_ITEMS[2]; - const toItem = ROOT_ID; - copyItem(movedItem, toItem); - - cy.wait('@copyItem').then(({ response: { body } }) => { - cy.get(`#${buildItemCard(movedItem)}`).should('exist'); - - // check in new parent - cy.goToHome(); - cy.get(`#${buildItemCard(body.id)}`).should('exist'); - }); - }); - - it('error while moving item does not create in interface', () => { - cy.setUpApi({ items: SIMPLE_ITEMS, copyItemError: true }); - const { id } = SIMPLE_ITEMS[0]; - - // go to children item - cy.visit(buildItemPath(id)); - - // move - const { id: movedItem } = SIMPLE_ITEMS[2]; - const { id: toItem } = SIMPLE_ITEMS[0]; - copyItem(movedItem, toItem); - - cy.wait('@copyItem').then(({ response: { body } }) => { - // check item is still existing in parent - cy.get(`#${buildItemCard(movedItem)}`).should('exist'); - cy.get(`#${buildItemCard(body.id)}`).should('not.exist'); - }); - }); -}); diff --git a/cypress/integration/createItem.spec.js b/cypress/integration/createItem.spec.js deleted file mode 100644 index 65927e321..000000000 --- a/cypress/integration/createItem.spec.js +++ /dev/null @@ -1,80 +0,0 @@ -import { ITEM_TYPES } from '../../src/config/constants'; -import { buildItemPath } from '../../src/config/paths'; -import { - buildItemCard, - CREATE_ITEM_BUTTON_ID, - ITEM_FORM_CONFIRM_BUTTON_ID, - ITEM_FORM_DESCRIPTION_INPUT_ID, - ITEM_FORM_IMAGE_INPUT_ID, - ITEM_FORM_NAME_INPUT_ID, - ITEM_FORM_TYPE_SELECT_ID, -} from '../../src/config/selectors'; -import { CREATED_ITEM, SIMPLE_ITEMS } from '../fixtures/items'; -import { CREATE_ITEM_PAUSE } from '../support/constants'; - -const createItem = ({ - name = '', - type = ITEM_TYPES.SPACE, - extra = {}, - description = '', -}) => { - cy.get(`#${CREATE_ITEM_BUTTON_ID}`).click(); - - cy.get(`#${ITEM_FORM_NAME_INPUT_ID}`).type(name); - - cy.get(`#${ITEM_FORM_DESCRIPTION_INPUT_ID}`).type(description); - - cy.get(`#${ITEM_FORM_TYPE_SELECT_ID}`).click(); - cy.get(`li[data-value="${type}"]`).click(); - cy.get(`#${ITEM_FORM_IMAGE_INPUT_ID}`).type(extra.image); - - cy.get(`#${ITEM_FORM_CONFIRM_BUTTON_ID}`).click(); -}; - -describe('Create Item', () => { - it('create item on Home', () => { - cy.setUpApi(); - cy.visit('/'); - - // create - createItem(CREATED_ITEM); - - cy.wait('@postItem').then(({ response: { body } }) => { - // check item is created and displayed - cy.wait(CREATE_ITEM_PAUSE); - cy.get(`#${buildItemCard(body.id)}`).should('exist'); - }); - }); - - it('create item in item', () => { - cy.setUpApi({ items: SIMPLE_ITEMS }); - const { id } = SIMPLE_ITEMS[0]; - - // go to children item - cy.visit(buildItemPath(id)); - - // create - createItem(CREATED_ITEM); - - cy.wait('@postItem').then(({ response: { body } }) => { - // check item is created and displayed - cy.get(`#${buildItemCard(body.id)}`).should('exist'); - }); - }); - - it('error while creating item does not create in interface', () => { - cy.setUpApi({ items: SIMPLE_ITEMS, postItemError: true }); - const { id } = SIMPLE_ITEMS[0]; - - // go to children item - cy.visit(buildItemPath(id)); - - // create - createItem(CREATED_ITEM); - - cy.wait('@postItem').then(({ response: { body } }) => { - // check item is created and displayed - cy.get(`#${buildItemCard(body.id)}`).should('not.exist'); - }); - }); -}); diff --git a/cypress/integration/item/copy/gridCopyItem.spec.js b/cypress/integration/item/copy/gridCopyItem.spec.js new file mode 100644 index 000000000..31f674ea2 --- /dev/null +++ b/cypress/integration/item/copy/gridCopyItem.spec.js @@ -0,0 +1,103 @@ +import { MODES, ROOT_ID } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; +import { + buildItemCard, + buildItemMenu, + ITEM_MENU_BUTTON_CLASS, + ITEM_MENU_COPY_BUTTON_CLASS, +} from '../../../../src/config/selectors'; +import { SIMPLE_ITEMS } from '../../../fixtures/items'; + +const copyItem = (id, toItemId) => { + const menuSelector = `#${buildItemCard(id)} .${ITEM_MENU_BUTTON_CLASS}`; + cy.get(menuSelector).click(); + cy.get(`#${buildItemMenu(id)} .${ITEM_MENU_COPY_BUTTON_CLASS}`).click(); + cy.fillTreeModal(toItemId); +}; + +describe('Copy Item in Grid', () => { + it('copy item on Home', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + cy.visit(HOME_PATH); + cy.switchMode(MODES.GRID); + + // copy + const { id: copyItemId } = SIMPLE_ITEMS[0]; + const { id: toItem } = SIMPLE_ITEMS[1]; + copyItem(copyItemId, toItem); + + cy.wait('@copyItem').then(({ response: { body } }) => { + cy.get(`#${buildItemCard(copyItemId)}`).should('exist'); + + // check in new parent + cy.goToItemInGrid(toItem); + cy.get(`#${buildItemCard(body.id)}`).should('exist'); + }); + }); + + it('copy item in item', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.GRID); + + // move + const { id: copyItemId } = SIMPLE_ITEMS[2]; + const { id: toItem } = SIMPLE_ITEMS[3]; + copyItem(copyItemId, toItem); + + cy.wait('@copyItem').then(({ response: { body } }) => { + cy.get(`#${buildItemCard(copyItemId)}`).should('exist'); + + // check in new parent + cy.goToItemInGrid(toItem); + cy.get(`#${buildItemCard(body.id)}`).should('exist'); + }); + }); + + it('copy item to Home', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.GRID); + + // move + const { id: copyItemId } = SIMPLE_ITEMS[2]; + const toItem = ROOT_ID; + copyItem(copyItemId, toItem); + + cy.wait('@copyItem').then(({ response: { body } }) => { + cy.get(`#${buildItemCard(copyItemId)}`).should('exist'); + + // check in new parent + cy.goToHome(); + cy.get(`#${buildItemCard(body.id)}`).should('exist'); + }); + }); + + describe('Errors handling', () => { + it('error while moving item does not create in interface', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, copyItemError: true }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.GRID); + + // move + const { id: copyItemId } = SIMPLE_ITEMS[2]; + const { id: toItem } = SIMPLE_ITEMS[0]; + copyItem(copyItemId, toItem); + + cy.wait('@copyItem').then(({ response: { body } }) => { + // check item is still existing in parent + cy.get(`#${buildItemCard(copyItemId)}`).should('exist'); + cy.get(`#${buildItemCard(body.id)}`).should('not.exist'); + }); + }); + }); +}); diff --git a/cypress/integration/item/copy/listCopyItem.spec.js b/cypress/integration/item/copy/listCopyItem.spec.js new file mode 100644 index 000000000..6d4f7d14c --- /dev/null +++ b/cypress/integration/item/copy/listCopyItem.spec.js @@ -0,0 +1,105 @@ +import { MODES, ROOT_ID } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; +import { + buildItemsTableRowId, + buildItemMenu, + ITEM_MENU_BUTTON_CLASS, + ITEM_MENU_COPY_BUTTON_CLASS, +} from '../../../../src/config/selectors'; +import { SIMPLE_ITEMS } from '../../../fixtures/items'; + +const copyItem = (id, toItemId) => { + const menuSelector = `#${buildItemsTableRowId( + id, + )} .${ITEM_MENU_BUTTON_CLASS}`; + cy.get(menuSelector).click(); + cy.get(`#${buildItemMenu(id)} .${ITEM_MENU_COPY_BUTTON_CLASS}`).click(); + cy.fillTreeModal(toItemId); +}; + +describe('Copy Item in List', () => { + it('copy item on Home', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + cy.visit(HOME_PATH); + cy.switchMode(MODES.LIST); + + // copy + const { id: copyItemId } = SIMPLE_ITEMS[0]; + const { id: toItem } = SIMPLE_ITEMS[1]; + copyItem(copyItemId, toItem); + + cy.wait('@copyItem').then(({ response: { body } }) => { + cy.get(`#${buildItemsTableRowId(copyItemId)}`).should('exist'); + + // check in new parent + cy.goToItemInList(toItem); + cy.get(`#${buildItemsTableRowId(body.id)}`).should('exist'); + }); + }); + + it('copy item in item', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.LIST); + + // copy + const { id: copyItemId } = SIMPLE_ITEMS[2]; + const { id: toItem } = SIMPLE_ITEMS[3]; + copyItem(copyItemId, toItem); + + cy.wait('@copyItem').then(({ response: { body } }) => { + cy.get(`#${buildItemsTableRowId(copyItemId)}`).should('exist'); + + // check in new parent + cy.goToItemInList(toItem); + cy.get(`#${buildItemsTableRowId(body.id)}`).should('exist'); + }); + }); + + it('copy item to Home', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.LIST); + + // copy + const { id: copyItemId } = SIMPLE_ITEMS[2]; + const toItem = ROOT_ID; + copyItem(copyItemId, toItem); + + cy.wait('@copyItem').then(({ response: { body } }) => { + cy.get(`#${buildItemsTableRowId(copyItemId)}`).should('exist'); + + // check in new parent + cy.goToHome(); + cy.get(`#${buildItemsTableRowId(body.id)}`).should('exist'); + }); + }); + + describe('Errors handling', () => { + it('error while moving item does not create in interface', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, copyItemError: true }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.LIST); + + // copy + const { id: copyItemId } = SIMPLE_ITEMS[2]; + const { id: toItem } = SIMPLE_ITEMS[0]; + copyItem(copyItemId, toItem); + + cy.wait('@copyItem').then(({ response: { body } }) => { + // check item is still existing in parent + cy.get(`#${buildItemsTableRowId(copyItemId)}`).should('exist'); + cy.get(`#${buildItemsTableRowId(body.id)}`).should('not.exist'); + }); + }); + }); +}); diff --git a/cypress/integration/item/create/gridCreateItem.spec.js b/cypress/integration/item/create/gridCreateItem.spec.js new file mode 100644 index 000000000..54826c55e --- /dev/null +++ b/cypress/integration/item/create/gridCreateItem.spec.js @@ -0,0 +1,67 @@ +import { MODES } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; +import { + buildItemCard, + CREATE_ITEM_BUTTON_ID, +} from '../../../../src/config/selectors'; +import { CREATED_ITEM, SIMPLE_ITEMS } from '../../../fixtures/items'; +import { CREATE_ITEM_PAUSE } from '../../../support/constants'; + +const createItem = (payload) => { + cy.get(`#${CREATE_ITEM_BUTTON_ID}`).click(); + + cy.fillItemModal(payload); +}; + +describe('Create Item in Grid', () => { + it('create item on Home', () => { + cy.setUpApi(); + cy.visit(HOME_PATH); + cy.switchMode(MODES.GRID); + + // create + createItem(CREATED_ITEM); + + cy.wait('@postItem').then(({ response: { body } }) => { + // check item is created and displayed + cy.wait(CREATE_ITEM_PAUSE); + cy.get(`#${buildItemCard(body.id)}`).should('exist'); + }); + }); + + it('create item in item', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.GRID); + + // create + createItem(CREATED_ITEM); + + cy.wait('@postItem').then(({ response: { body } }) => { + // check item is created and displayed + cy.get(`#${buildItemCard(body.id)}`).should('exist'); + }); + }); + + describe('Errors handling', () => { + it('error while creating item does not create in interface', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, postItemError: true }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.GRID); + + // create + createItem(CREATED_ITEM); + + cy.wait('@postItem').then(({ response: { body } }) => { + // check item is created and displayed + cy.get(`#${buildItemCard(body.id)}`).should('not.exist'); + }); + }); + }); +}); diff --git a/cypress/integration/item/create/listCreateItem.spec.js b/cypress/integration/item/create/listCreateItem.spec.js new file mode 100644 index 000000000..2fabd09e1 --- /dev/null +++ b/cypress/integration/item/create/listCreateItem.spec.js @@ -0,0 +1,67 @@ +import { MODES } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; +import { + buildItemsTableRowId, + CREATE_ITEM_BUTTON_ID, +} from '../../../../src/config/selectors'; +import { CREATED_ITEM, SIMPLE_ITEMS } from '../../../fixtures/items'; +import { CREATE_ITEM_PAUSE } from '../../../support/constants'; + +const createItem = (payload) => { + cy.get(`#${CREATE_ITEM_BUTTON_ID}`).click(); + + cy.fillItemModal(payload); +}; + +describe('Create Item in List', () => { + it('create item on Home', () => { + cy.setUpApi(); + cy.visit(HOME_PATH); + cy.switchMode(MODES.LIST); + + // create + createItem(CREATED_ITEM); + + cy.wait('@postItem').then(({ response: { body } }) => { + // check item is created and displayed + cy.wait(CREATE_ITEM_PAUSE); + cy.get(`#${buildItemsTableRowId(body.id)}`).should('exist'); + }); + }); + + it('create item in item', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.LIST); + + // create + createItem(CREATED_ITEM); + + cy.wait('@postItem').then(({ response: { body } }) => { + // check item is created and displayed + cy.get(`#${buildItemsTableRowId(body.id)}`).should('exist'); + }); + }); + + describe('Errors handling', () => { + it('error while creating item does not create in interface', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, postItemError: true }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.LIST); + + // create + createItem(CREATED_ITEM); + + cy.wait('@postItem').then(({ response: { body } }) => { + // check item is created and displayed + cy.get(`#${buildItemsTableRowId(body.id)}`).should('not.exist'); + }); + }); + }); +}); diff --git a/cypress/integration/deleteItem.spec.js b/cypress/integration/item/delete/gridDeleteItem.spec.js similarity index 54% rename from cypress/integration/deleteItem.spec.js rename to cypress/integration/item/delete/gridDeleteItem.spec.js index 7e3b0d4d8..bfe21a138 100644 --- a/cypress/integration/deleteItem.spec.js +++ b/cypress/integration/item/delete/gridDeleteItem.spec.js @@ -1,18 +1,20 @@ -import { buildItemPath } from '../../src/config/paths'; +import { MODES } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; import { buildItemCard, ITEM_DELETE_BUTTON_CLASS, -} from '../../src/config/selectors'; -import { SIMPLE_ITEMS } from '../fixtures/items'; +} from '../../../../src/config/selectors'; +import { SIMPLE_ITEMS } from '../../../fixtures/items'; const deleteItem = (id) => { cy.get(`#${buildItemCard(id)} .${ITEM_DELETE_BUTTON_CLASS}`).click(); }; -describe('Delete Item', () => { +describe('Delete Item in Grid', () => { it('delete item on Home', () => { cy.setUpApi({ items: SIMPLE_ITEMS }); - cy.visit('/'); + cy.visit(HOME_PATH); + cy.switchMode(MODES.GRID); const { id } = SIMPLE_ITEMS[0]; @@ -32,6 +34,7 @@ describe('Delete Item', () => { // go to children item cy.visit(buildItemPath(id)); + cy.switchMode(MODES.GRID); // delete deleteItem(idToDelete); @@ -42,20 +45,23 @@ describe('Delete Item', () => { }); }); - it('error while deleting item does not delete in interface', () => { - cy.setUpApi({ items: SIMPLE_ITEMS, deleteItemError: true }); - const { id } = SIMPLE_ITEMS[0]; - const { id: idToDelete } = SIMPLE_ITEMS[2]; + describe('Errors handling', () => { + it('error while deleting item does not delete in interface', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, deleteItemError: true }); + const { id } = SIMPLE_ITEMS[0]; + const { id: idToDelete } = SIMPLE_ITEMS[2]; - // go to children item - cy.visit(buildItemPath(id)); + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.GRID); - // delete - deleteItem(idToDelete); + // delete + deleteItem(idToDelete); - cy.wait('@deleteItem').then(() => { - // check item is still displayed - cy.get(`#${buildItemCard(idToDelete)}`).should('exist'); + cy.wait('@deleteItem').then(() => { + // check item is still displayed + cy.get(`#${buildItemCard(idToDelete)}`).should('exist'); + }); }); }); }); diff --git a/cypress/integration/item/delete/listDeleteItem.spec.js b/cypress/integration/item/delete/listDeleteItem.spec.js new file mode 100644 index 000000000..e5fb99cb0 --- /dev/null +++ b/cypress/integration/item/delete/listDeleteItem.spec.js @@ -0,0 +1,67 @@ +import { MODES } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; +import { + buildItemsTableRowId, + ITEM_DELETE_BUTTON_CLASS, +} from '../../../../src/config/selectors'; +import { SIMPLE_ITEMS } from '../../../fixtures/items'; + +const deleteItem = (id) => { + cy.get(`#${buildItemsTableRowId(id)} .${ITEM_DELETE_BUTTON_CLASS}`).click(); +}; + +describe('Delete Item in List', () => { + it('delete item on Home', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + cy.visit(HOME_PATH); + cy.switchMode(MODES.LIST); + + const { id } = SIMPLE_ITEMS[0]; + + // delete + deleteItem(id); + cy.wait('@deleteItem').then(() => { + // check item is deleted, others are still displayed + cy.get(`#${buildItemsTableRowId(id)}`).should('not.exist'); + cy.get(`#${buildItemsTableRowId(SIMPLE_ITEMS[1].id)}`).should('exist'); + }); + }); + + it('delete item inside parent', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + const { id } = SIMPLE_ITEMS[0]; + const { id: idToDelete } = SIMPLE_ITEMS[2]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.LIST); + + // delete + deleteItem(idToDelete); + cy.wait('@deleteItem').then(() => { + // check item is deleted, others are still displayed + cy.get(`#${buildItemsTableRowId(idToDelete)}`).should('not.exist'); + cy.get(`#${buildItemsTableRowId(SIMPLE_ITEMS[3].id)}`).should('exist'); + }); + }); + + describe('Errors handling', () => { + it('error while deleting item does not delete in interface', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, deleteItemError: true }); + const { id } = SIMPLE_ITEMS[0]; + const { id: idToDelete } = SIMPLE_ITEMS[2]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.LIST); + + // delete + deleteItem(idToDelete); + + cy.wait('@deleteItem').then(() => { + // check item is still displayed + cy.get(`#${buildItemsTableRowId(idToDelete)}`).should('exist'); + }); + }); + }); +}); diff --git a/cypress/integration/item/delete/listDeleteItems.spec.js b/cypress/integration/item/delete/listDeleteItems.spec.js new file mode 100644 index 000000000..0b928dd48 --- /dev/null +++ b/cypress/integration/item/delete/listDeleteItems.spec.js @@ -0,0 +1,73 @@ +import { MODES } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; +import { + buildItemsTableRowId, + ITEMS_TABLE_DELETE_SELECTED_ITEMS_ID, + ITEMS_TABLE_ROW_CHECKBOX_CLASS, +} from '../../../../src/config/selectors'; +import { SIMPLE_ITEMS } from '../../../fixtures/items'; + +const deleteItems = (itemIds) => { + // check selected ids + itemIds.forEach((id) => { + cy.get( + `#${buildItemsTableRowId(id)} .${ITEMS_TABLE_ROW_CHECKBOX_CLASS}`, + ).click(); + }); + + cy.get(`#${ITEMS_TABLE_DELETE_SELECTED_ITEMS_ID}`).click(); +}; + +describe('Delete Items in List', () => { + it('delete 2 items in Home', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + cy.visit(HOME_PATH); + cy.switchMode(MODES.LIST); + + // delete + deleteItems([SIMPLE_ITEMS[0].id, SIMPLE_ITEMS[1].id]); + cy.wait('@deleteItems').then(() => { + // check item is deleted, others are still displayed + cy.get(`#${buildItemsTableRowId(SIMPLE_ITEMS[1].id)}`).should( + 'not.exist', + ); + cy.get(`#${buildItemsTableRowId(SIMPLE_ITEMS[1].id)}`).should( + 'not.exist', + ); + }); + }); + + it('delete 2 items in item', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + cy.visit(buildItemPath(SIMPLE_ITEMS[0].id)); + cy.switchMode(MODES.LIST); + + // delete + deleteItems([SIMPLE_ITEMS[2].id, SIMPLE_ITEMS[3].id]); + cy.wait('@deleteItems').then(() => { + // check item is deleted, others are still displayed + cy.get(`#${buildItemsTableRowId(SIMPLE_ITEMS[2].id)}`).should( + 'not.exist', + ); + cy.get(`#${buildItemsTableRowId(SIMPLE_ITEMS[3].id)}`).should( + 'not.exist', + ); + }); + }); + + describe('Errors handling', () => { + it('does not delete items on error', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, deleteItemsError: true }); + cy.visit(HOME_PATH); + cy.switchMode(MODES.LIST); + + // delete + deleteItems([SIMPLE_ITEMS[0].id, SIMPLE_ITEMS[1].id]); + cy.wait('@deleteItems').then(() => { + // check item is deleted, others are still displayed + cy.get(`#${buildItemsTableRowId(SIMPLE_ITEMS[0].id)}`).should('exist'); + cy.get(`#${buildItemsTableRowId(SIMPLE_ITEMS[1].id)}`).should('exist'); + }); + }); + }); +}); diff --git a/cypress/integration/editItem.spec.js b/cypress/integration/item/edit/gridEditItem.spec.js similarity index 50% rename from cypress/integration/editItem.spec.js rename to cypress/integration/item/edit/gridEditItem.spec.js index a9506198b..d16cc3c45 100644 --- a/cypress/integration/editItem.spec.js +++ b/cypress/integration/item/edit/gridEditItem.spec.js @@ -1,46 +1,26 @@ -import { ITEM_TYPES } from '../../src/config/constants'; -import { buildItemPath } from '../../src/config/paths'; +import { MODES } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; import { buildItemCard, buildItemLink, - buildItemMenu, - ITEM_MENU_BUTTON_CLASS, - ITEM_MENU_EDIT_BUTTON_CLASS, - ITEM_FORM_CONFIRM_BUTTON_ID, - ITEM_FORM_DESCRIPTION_INPUT_ID, - ITEM_FORM_IMAGE_INPUT_ID, - ITEM_FORM_NAME_INPUT_ID, - ITEM_FORM_TYPE_SELECT_ID, -} from '../../src/config/selectors'; -import { EDITED_FIELDS, SIMPLE_ITEMS } from '../fixtures/items'; -import { EDIT_ITEM_PAUSE } from '../support/constants'; + EDIT_ITEM_BUTTON_CLASS, +} from '../../../../src/config/selectors'; +import { EDITED_FIELDS, SIMPLE_ITEMS } from '../../../fixtures/items'; +import { EDIT_ITEM_PAUSE } from '../../../support/constants'; -const editItem = ({ - id, - name = '', - type = ITEM_TYPES.SPACE, - extra = {}, - description = '', -}) => { - const menuSelector = `#${buildItemCard(id)} .${ITEM_MENU_BUTTON_CLASS}`; - cy.get(menuSelector).click(); - cy.get(`#${buildItemMenu(id)} .${ITEM_MENU_EDIT_BUTTON_CLASS}`).click(); +const editItem = (payload) => { + const { id } = payload; + const button = `#${buildItemCard(id)} .${EDIT_ITEM_BUTTON_CLASS}`; + cy.get(button).click(); - cy.get(`#${ITEM_FORM_NAME_INPUT_ID}`).clear().type(name); - - cy.get(`#${ITEM_FORM_DESCRIPTION_INPUT_ID}`).clear().type(description); - - cy.get(`#${ITEM_FORM_TYPE_SELECT_ID}`).click(); - cy.get(`li[data-value="${type}"]`).click(); - cy.get(`#${ITEM_FORM_IMAGE_INPUT_ID}`).clear().type(extra.image); - - cy.get(`#${ITEM_FORM_CONFIRM_BUTTON_ID}`).click(); + cy.fillItemModal(payload); }; -describe('Edit Item', () => { +describe('Edit Item in Grid', () => { it('edit item on Home', () => { cy.setUpApi({ items: SIMPLE_ITEMS }); - cy.visit('/'); + cy.visit(HOME_PATH); + cy.switchMode(MODES.GRID); const itemToEdit = SIMPLE_ITEMS[0]; @@ -68,6 +48,7 @@ describe('Edit Item', () => { cy.setUpApi({ items: SIMPLE_ITEMS }); // go to children item cy.visit(buildItemPath(SIMPLE_ITEMS[0].id)); + cy.switchMode(MODES.GRID); const itemToEdit = SIMPLE_ITEMS[2]; diff --git a/cypress/integration/item/edit/listEditItem.spec.js b/cypress/integration/item/edit/listEditItem.spec.js new file mode 100644 index 000000000..0d10d32ac --- /dev/null +++ b/cypress/integration/item/edit/listEditItem.spec.js @@ -0,0 +1,72 @@ +import { MODES } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; +import { + buildItemsTableRowId, + EDIT_ITEM_BUTTON_CLASS, +} from '../../../../src/config/selectors'; +import { EDITED_FIELDS, SIMPLE_ITEMS } from '../../../fixtures/items'; +import { EDIT_ITEM_PAUSE } from '../../../support/constants'; + +const editItem = (payload) => { + const { id } = payload; + cy.get(`#${buildItemsTableRowId(id)} .${EDIT_ITEM_BUTTON_CLASS}`).click(); + + cy.fillItemModal(payload); +}; + +describe('Edit Item in List', () => { + it('edit item on Home', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + cy.visit(HOME_PATH); + cy.switchMode(MODES.LIST); + + const itemToEdit = SIMPLE_ITEMS[0]; + + // edit + editItem({ + ...itemToEdit, + ...EDITED_FIELDS, + }); + + cy.wait('@editItem').then( + ({ + response: { + body: { id, name }, + }, + }) => { + // check item is edited and updated + cy.wait(EDIT_ITEM_PAUSE); + cy.get(`#${buildItemsTableRowId(id)}`).should('exist'); + cy.get(`#${buildItemsTableRowId(id)}`).contains(name); + }, + ); + }); + + it('create item in item', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + // go to children item + cy.visit(buildItemPath(SIMPLE_ITEMS[0].id)); + cy.switchMode(MODES.LIST); + + const itemToEdit = SIMPLE_ITEMS[2]; + + // edit + editItem({ + ...itemToEdit, + ...EDITED_FIELDS, + }); + + cy.wait('@editItem').then( + ({ + response: { + body: { id, name }, + }, + }) => { + // check item is edited and updated + cy.wait(EDIT_ITEM_PAUSE); + cy.get(`#${buildItemsTableRowId(id)}`).should('exist'); + cy.get(`#${buildItemsTableRowId(id)}`).contains(name); + }, + ); + }); +}); diff --git a/cypress/integration/moveItem.spec.js b/cypress/integration/item/move/gridMoveItem.spec.js similarity index 62% rename from cypress/integration/moveItem.spec.js rename to cypress/integration/item/move/gridMoveItem.spec.js index d003a50f0..47c3b1262 100644 --- a/cypress/integration/moveItem.spec.js +++ b/cypress/integration/item/move/gridMoveItem.spec.js @@ -1,16 +1,13 @@ -import { ROOT_ID } from '../../src/config/constants'; -import { buildItemPath } from '../../src/config/paths'; +import { MODES, ROOT_ID } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; import { buildItemCard, buildItemMenu, - buildTreeItemClass, ITEM_MENU_BUTTON_CLASS, ITEM_MENU_MOVE_BUTTON_CLASS, NAVIGATION_HOME_LINK_ID, - TREE_MODAL_CONFIRM_BUTTON_ID, - TREE_MODAL_TREE_ID, -} from '../../src/config/selectors'; -import { SIMPLE_ITEMS } from '../fixtures/items'; +} from '../../../../src/config/selectors'; +import { SIMPLE_ITEMS } from '../../../fixtures/items'; const moveItem = (movedItemId, toItemId) => { const menuSelector = `#${buildItemCard( @@ -21,21 +18,14 @@ const moveItem = (movedItemId, toItemId) => { `#${buildItemMenu(movedItemId)} .${ITEM_MENU_MOVE_BUTTON_CLASS}`, ).click(); - cy.get( - `#${TREE_MODAL_TREE_ID} .${buildTreeItemClass( - toItemId, - )} .MuiTreeItem-label`, - ) - .first() - .click(); - - cy.get(`#${TREE_MODAL_CONFIRM_BUTTON_ID}`).click(); + cy.fillTreeModal(toItemId); }; -describe('Move Item', () => { +describe('Move Item in Grid', () => { it('move item on Home', () => { cy.setUpApi({ items: SIMPLE_ITEMS }); - cy.visit('/'); + cy.visit(HOME_PATH); + cy.switchMode(MODES.GRID); // move const { id: movedItem } = SIMPLE_ITEMS[0]; @@ -47,7 +37,7 @@ describe('Move Item', () => { cy.get(`#${buildItemCard(movedItem)}`).should('not.exist'); // check in new parent - cy.goToItem(toItem); + cy.goToItemInGrid(toItem); cy.get(`#${buildItemCard(movedItem)}`).should('exist'); }); @@ -57,6 +47,7 @@ describe('Move Item', () => { // go to children item cy.visit(buildItemPath(id)); + cy.switchMode(MODES.GRID); // move const { id: movedItem } = SIMPLE_ITEMS[2]; @@ -68,7 +59,7 @@ describe('Move Item', () => { cy.get(`#${buildItemCard(movedItem)}`).should('not.exist'); // check in new parent - cy.goToItem(toItem); + cy.goToItemInGrid(toItem); cy.get(`#${buildItemCard(movedItem)}`).should('exist'); }); @@ -78,6 +69,7 @@ describe('Move Item', () => { // go to children item cy.visit(buildItemPath(id)); + cy.switchMode(MODES.GRID); // move const { id: movedItem } = SIMPLE_ITEMS[2]; @@ -93,21 +85,24 @@ describe('Move Item', () => { cy.get(`#${buildItemCard(movedItem)}`).should('exist'); }); - it('error while moving item does not create in interface', () => { - cy.setUpApi({ items: SIMPLE_ITEMS, moveItemError: true }); - const { id } = SIMPLE_ITEMS[0]; + describe('Error handling', () => { + it('error while moving item does not create in interface', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, moveItemError: true }); + const { id } = SIMPLE_ITEMS[0]; - // go to children item - cy.visit(buildItemPath(id)); + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.GRID); - // move - const { id: movedItem } = SIMPLE_ITEMS[2]; - const { id: toItem } = SIMPLE_ITEMS[3]; - moveItem(movedItem, toItem); + // move + const { id: movedItem } = SIMPLE_ITEMS[2]; + const { id: toItem } = SIMPLE_ITEMS[3]; + moveItem(movedItem, toItem); - cy.wait('@moveItem').then(({ response: { body } }) => { - // check item is created and displayed - cy.get(`#${buildItemCard(body.id)}`).should('not.exist'); + cy.wait('@moveItem').then(({ response: { body } }) => { + // check item is created and displayed + cy.get(`#${buildItemCard(body.id)}`).should('not.exist'); + }); }); }); }); diff --git a/cypress/integration/item/move/listMoveItem.spec.js b/cypress/integration/item/move/listMoveItem.spec.js new file mode 100644 index 000000000..96a98998b --- /dev/null +++ b/cypress/integration/item/move/listMoveItem.spec.js @@ -0,0 +1,108 @@ +import { MODES, ROOT_ID } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; +import { + buildItemsTableRowId, + buildItemMenu, + ITEM_MENU_BUTTON_CLASS, + ITEM_MENU_MOVE_BUTTON_CLASS, + NAVIGATION_HOME_LINK_ID, +} from '../../../../src/config/selectors'; +import { SIMPLE_ITEMS } from '../../../fixtures/items'; + +const moveItem = (movedItemId, toItemId) => { + const menuSelector = `#${buildItemsTableRowId( + movedItemId, + )} .${ITEM_MENU_BUTTON_CLASS}`; + cy.get(menuSelector).click(); + cy.get( + `#${buildItemMenu(movedItemId)} .${ITEM_MENU_MOVE_BUTTON_CLASS}`, + ).click(); + + cy.fillTreeModal(toItemId); +}; + +describe('Move Item in List', () => { + it('move item on Home', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + cy.visit(HOME_PATH); + cy.switchMode(MODES.LIST); + + // move + const { id: movedItem } = SIMPLE_ITEMS[0]; + const { id: toItem } = SIMPLE_ITEMS[1]; + moveItem(movedItem, toItem); + + cy.wait('@moveItem'); + + cy.get(`#${buildItemsTableRowId(movedItem)}`).should('not.exist'); + + // check in new parent + cy.goToItemInList(toItem); + cy.get(`#${buildItemsTableRowId(movedItem)}`).should('exist'); + }); + + it('move item in item', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.LIST); + + // move + const { id: movedItem } = SIMPLE_ITEMS[2]; + const { id: toItem } = SIMPLE_ITEMS[3]; + moveItem(movedItem, toItem); + + cy.wait('@moveItem'); + + cy.get(`#${buildItemsTableRowId(movedItem)}`).should('not.exist'); + + // check in new parent + cy.goToItemInList(toItem); + cy.get(`#${buildItemsTableRowId(movedItem)}`).should('exist'); + }); + + it('move item to Home', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.LIST); + + // move + const { id: movedItem } = SIMPLE_ITEMS[2]; + const toItem = ROOT_ID; + moveItem(movedItem, toItem); + + cy.wait('@moveItem'); + + cy.get(`#${buildItemsTableRowId(movedItem)}`).should('not.exist'); + + // check in new parent + cy.get(`#${NAVIGATION_HOME_LINK_ID}`).click(); + cy.get(`#${buildItemsTableRowId(movedItem)}`).should('exist'); + }); + + describe('Errors handling', () => { + it('error while moving item does not create in interface', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, moveItemError: true }); + const { id } = SIMPLE_ITEMS[0]; + + // go to children item + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.LIST); + + // move + const { id: movedItem } = SIMPLE_ITEMS[2]; + const { id: toItem } = SIMPLE_ITEMS[3]; + moveItem(movedItem, toItem); + + cy.wait('@moveItem').then(({ response: { body } }) => { + // check item is created and displayed + cy.get(`#${buildItemsTableRowId(body.id)}`).should('not.exist'); + }); + }); + }); +}); diff --git a/cypress/integration/item/share/gridShareItem.spec.js b/cypress/integration/item/share/gridShareItem.spec.js new file mode 100644 index 000000000..cc45a764a --- /dev/null +++ b/cypress/integration/item/share/gridShareItem.spec.js @@ -0,0 +1,49 @@ +import { MODES, PERMISSION_LEVELS } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; +import { + buildItemCard, + SHARE_ITEM_BUTTON_CLASS, +} from '../../../../src/config/selectors'; +import { MEMBERS, SIMPLE_ITEMS } from '../../../fixtures/items'; + +const shareItem = ({ id, member, permission }) => { + cy.get(`#${buildItemCard(id)} .${SHARE_ITEM_BUTTON_CLASS}`).click(); + + cy.fillShareModal({ member, permission }); +}; + +describe('Share Item in Grid', () => { + it('share item on Home', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, members: Object.values(MEMBERS) }); + cy.visit(HOME_PATH); + cy.switchMode(MODES.GRID); + + // share + const { id } = SIMPLE_ITEMS[0]; + const member = MEMBERS.ANNA; + shareItem({ id, member, permission: PERMISSION_LEVELS.WRITE }); + + cy.wait('@shareItem').then(() => { + cy.get(`#${buildItemCard(id)}`).should('exist'); + }); + }); + + it('share item in item', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, members: Object.values(MEMBERS) }); + + // go to children item + cy.visit(buildItemPath(SIMPLE_ITEMS[0].id)); + cy.switchMode(MODES.GRID); + + // share + const { id } = SIMPLE_ITEMS[2]; + const member = MEMBERS.ANNA; + shareItem({ id, member, permission: PERMISSION_LEVELS.READ }); + + cy.wait('@shareItem').then(() => { + cy.get(`#${buildItemCard(id)}`).should('exist'); + }); + }); + + // todo : check item permission for users +}); diff --git a/cypress/integration/item/share/listShareItem.spec.js b/cypress/integration/item/share/listShareItem.spec.js new file mode 100644 index 000000000..0315a6cd7 --- /dev/null +++ b/cypress/integration/item/share/listShareItem.spec.js @@ -0,0 +1,49 @@ +import { MODES, PERMISSION_LEVELS } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; +import { + buildItemsTableRowId, + SHARE_ITEM_BUTTON_CLASS, +} from '../../../../src/config/selectors'; +import { MEMBERS, SIMPLE_ITEMS } from '../../../fixtures/items'; + +const shareItem = ({ id, member, permission }) => { + cy.get(`#${buildItemsTableRowId(id)} .${SHARE_ITEM_BUTTON_CLASS}`).click(); + + cy.fillShareModal({ member, permission }); +}; + +describe('Share Item in List', () => { + it('share item on Home', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, members: Object.values(MEMBERS) }); + cy.visit(HOME_PATH); + cy.switchMode(MODES.LIST); + + // share + const { id } = SIMPLE_ITEMS[0]; + const member = MEMBERS.ANNA; + shareItem({ id, member, permission: PERMISSION_LEVELS.WRITE }); + + cy.wait('@shareItem').then(() => { + cy.get(`#${buildItemsTableRowId(id)}`).should('exist'); + }); + }); + + it('share item in item', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, members: Object.values(MEMBERS) }); + + // go to children item + cy.visit(buildItemPath(SIMPLE_ITEMS[0].id)); + cy.switchMode(MODES.LIST); + + // share + const { id } = SIMPLE_ITEMS[2]; + const member = MEMBERS.ANNA; + shareItem({ id, member, permission: PERMISSION_LEVELS.READ }); + + cy.wait('@shareItem').then(() => { + cy.get(`#${buildItemsTableRowId(id)}`).should('exist'); + }); + }); + + // todo : check item permission for users +}); diff --git a/cypress/integration/viewItem.spec.js b/cypress/integration/item/view/gridViewItem.spec.js similarity index 71% rename from cypress/integration/viewItem.spec.js rename to cypress/integration/item/view/gridViewItem.spec.js index 3c0fadf1d..13eaa2568 100644 --- a/cypress/integration/viewItem.spec.js +++ b/cypress/integration/item/view/gridViewItem.spec.js @@ -1,16 +1,18 @@ -import { buildItemPath } from '../../src/config/paths'; +import { MODES } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; import { buildItemCard, ITEMS_GRID_NO_ITEM_ID, ITEM_SCREEN_ERROR_ALERT_ID, NAVIGATION_HOME_LINK_ID, -} from '../../src/config/selectors'; -import { SIMPLE_ITEMS } from '../fixtures/items'; +} from '../../../../src/config/selectors'; +import { SIMPLE_ITEMS } from '../../../fixtures/items'; -describe('Create Item', () => { +describe('Create Item in Grid', () => { it('visit Home', () => { cy.setUpApi({ items: SIMPLE_ITEMS }); - cy.visit('/'); + cy.visit(HOME_PATH); + cy.switchMode(MODES.GRID); // should get own items cy.wait('@getOwnItems').then(({ response: { body } }) => { @@ -22,7 +24,7 @@ describe('Create Item', () => { // visit child const { id: childId } = SIMPLE_ITEMS[0]; - cy.goToItem(childId); + cy.goToItemInGrid(childId); // should get children cy.wait('@getChildren').then(({ response: { body } }) => { @@ -34,7 +36,7 @@ describe('Create Item', () => { // visit child const { id: childChildId } = SIMPLE_ITEMS[2]; - cy.goToItem(childChildId); + cy.goToItemInGrid(childChildId); // expect no children cy.get(`#${ITEMS_GRID_NO_ITEM_ID}`).should('exist'); @@ -54,6 +56,7 @@ describe('Create Item', () => { cy.setUpApi({ items: SIMPLE_ITEMS }); const { id } = SIMPLE_ITEMS[0]; cy.visit(buildItemPath(id)); + cy.switchMode(MODES.GRID); // should get current item cy.wait('@getItem'); @@ -78,14 +81,16 @@ describe('Create Item', () => { }); }); - it('visiting non-existing item display no item here', () => { - cy.setUpApi({ items: SIMPLE_ITEMS, getItemError: true }); - const { id } = SIMPLE_ITEMS[0]; - cy.visit(buildItemPath(id)); + describe('Errors handling', () => { + it('visiting non-existing item display no item here', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, getItemError: true }); + const { id } = SIMPLE_ITEMS[0]; + cy.visit(buildItemPath(id)); - // should get current item - cy.wait('@getItem').then(() => { - cy.get(`#${ITEM_SCREEN_ERROR_ALERT_ID}`).should('exist'); + // should get current item + cy.wait('@getItem').then(() => { + cy.get(`#${ITEM_SCREEN_ERROR_ALERT_ID}`).should('exist'); + }); }); }); }); diff --git a/cypress/integration/item/view/listViewItem.spec.js b/cypress/integration/item/view/listViewItem.spec.js new file mode 100644 index 000000000..ffcec1083 --- /dev/null +++ b/cypress/integration/item/view/listViewItem.spec.js @@ -0,0 +1,96 @@ +import { MODES } from '../../../../src/config/constants'; +import { buildItemPath, HOME_PATH } from '../../../../src/config/paths'; +import { + buildItemsTableRowId, + ITEMS_TABLE_EMPTY_ROW_ID, + ITEM_SCREEN_ERROR_ALERT_ID, + NAVIGATION_HOME_LINK_ID, +} from '../../../../src/config/selectors'; +import { SIMPLE_ITEMS } from '../../../fixtures/items'; + +describe('Create Item in List', () => { + it('visit Home', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + cy.visit(HOME_PATH); + cy.switchMode(MODES.LIST); + + // should get own items + cy.wait('@getOwnItems').then(({ response: { body } }) => { + // check item is created and displayed + for (const item of body) { + cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + } + }); + + // visit child + const { id: childId } = SIMPLE_ITEMS[0]; + cy.goToItemInList(childId); + + // should get children + cy.wait('@getChildren').then(({ response: { body } }) => { + // check item is created and displayed + for (const item of body) { + cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + } + }); + + // visit child + const { id: childChildId } = SIMPLE_ITEMS[2]; + cy.goToItemInList(childChildId); + + // expect no children + cy.get(`#${ITEMS_TABLE_EMPTY_ROW_ID}`).should('exist'); + + // return parent with navigation and should display children + cy.goToItemWithNavigation(childId); + // should get children + cy.wait('@getChildren').then(({ response: { body } }) => { + // check item is created and displayed + for (const item of body) { + cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + } + }); + }); + + it('visit item by id', () => { + cy.setUpApi({ items: SIMPLE_ITEMS }); + const { id } = SIMPLE_ITEMS[0]; + cy.visit(buildItemPath(id)); + cy.switchMode(MODES.LIST); + + // should get current item + cy.wait('@getItem'); + + // should get children + cy.wait('@getChildren').then(({ response: { body } }) => { + // check item is created and displayed + for (const item of body) { + cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + } + }); + + // visit home + cy.get(`#${NAVIGATION_HOME_LINK_ID}`).click(); + + // should get own items + cy.wait('@getOwnItems').then(({ response: { body } }) => { + // check item is created and displayed + for (const item of body) { + cy.get(`#${buildItemsTableRowId(item.id)}`).should('exist'); + } + }); + }); + + describe('Errors handling', () => { + it('visiting non-existing item display no item here', () => { + cy.setUpApi({ items: SIMPLE_ITEMS, getItemError: true }); + const { id } = SIMPLE_ITEMS[0]; + cy.visit(buildItemPath(id)); + + // should get current item + cy.wait('@getItem').then(() => { + cy.get(`#${ITEM_SCREEN_ERROR_ALERT_ID}`).should('exist'); + }); + }); + }); +}); diff --git a/cypress/integration/shareItem.spec.js b/cypress/integration/shareItem.spec.js deleted file mode 100644 index 1bac99970..000000000 --- a/cypress/integration/shareItem.spec.js +++ /dev/null @@ -1,62 +0,0 @@ -import { PERMISSION_LEVELS } from '../../src/config/constants'; -import { buildItemPath } from '../../src/config/paths'; -import { - buildItemCard, - buildItemMenu, - ITEM_MENU_BUTTON_CLASS, - ITEM_MENU_SHARE_BUTTON_CLASS, - SHARE_ITEM_MODAL_PERMISSION_SELECT_ID, - SHARE_ITEM_MODAL_SHARE_BUTTON_ID, - buildPermissionOptionId, - SHARE_ITEM_MODAL_EMAIL_INPUT_ID, -} from '../../src/config/selectors'; -import { MEMBERS, SIMPLE_ITEMS } from '../fixtures/items'; - -const shareItem = ({ id, member, permission }) => { - const menuSelector = `#${buildItemCard(id)} .${ITEM_MENU_BUTTON_CLASS}`; - cy.get(menuSelector).click(); - cy.get(`#${buildItemMenu(id)} .${ITEM_MENU_SHARE_BUTTON_CLASS}`).click(); - - // select permission - cy.get(`#${SHARE_ITEM_MODAL_PERMISSION_SELECT_ID}`).click(); - cy.get(`#${buildPermissionOptionId(permission)}`).click(); - - // input mail - cy.get(`#${SHARE_ITEM_MODAL_EMAIL_INPUT_ID}`).type(member.email); - - cy.get(`#${SHARE_ITEM_MODAL_SHARE_BUTTON_ID}`).click(); -}; - -describe('Share Item', () => { - it('share item on Home', () => { - cy.setUpApi({ items: SIMPLE_ITEMS, members: Object.values(MEMBERS) }); - cy.visit('/'); - - // share - const { id } = SIMPLE_ITEMS[0]; - const member = MEMBERS.ANNA; - shareItem({ id, member, permission: PERMISSION_LEVELS.WRITE }); - - cy.wait('@shareItem').then(() => { - cy.get(`#${buildItemCard(id)}`).should('exist'); - }); - }); - - it('share item in item', () => { - cy.setUpApi({ items: SIMPLE_ITEMS, members: Object.values(MEMBERS) }); - - // go to children item - cy.visit(buildItemPath(SIMPLE_ITEMS[0].id)); - - // share - const { id } = SIMPLE_ITEMS[2]; - const member = MEMBERS.ANNA; - shareItem({ id, member, permission: PERMISSION_LEVELS.READ }); - - cy.wait('@shareItem').then(() => { - cy.get(`#${buildItemCard(id)}`).should('exist'); - }); - }); - - // todo : check item permission for users -}); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 8f538ce4e..9a149d4f1 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -1,9 +1,8 @@ +import { MODES } from '../../src/config/constants'; import { - buildItemLink, - buildNavigationLink, - NAVIGATION_HOME_LINK_ID, + MODE_GRID_BUTTON_ID, + MODE_LIST_BUTTON_ID, } from '../../src/config/selectors'; -import { NAVIGATE_PAUSE } from './constants'; import { mockCopyItem, mockDeleteItem, @@ -15,7 +14,10 @@ import { mockEditItem, mockShareItem, mockGetMember, + mockDeleteItems, } from './server'; +import './commands/item'; +import './commands/navigation'; Cypress.Commands.add( 'setUpApi', @@ -23,6 +25,7 @@ Cypress.Commands.add( items = [], members = [], deleteItemError = false, + deleteItemsError = false, postItemError = false, moveItemError = false, copyItemError = false, @@ -40,6 +43,8 @@ Cypress.Commands.add( mockDeleteItem(cachedItems, deleteItemError); + mockDeleteItems(cachedItems, deleteItemsError); + mockGetItem(cachedItems, getItemError); mockGetChildren(cachedItems); @@ -56,17 +61,16 @@ Cypress.Commands.add( }, ); -Cypress.Commands.add('goToItem', (id) => { - cy.wait(NAVIGATE_PAUSE); - cy.get(`#${buildItemLink(id)}`).click(); -}); - -Cypress.Commands.add('goToHome', () => { - cy.wait(NAVIGATE_PAUSE); - cy.get(`#${NAVIGATION_HOME_LINK_ID}`).click(); -}); - -Cypress.Commands.add('goToItemWithNavigation', (id) => { - cy.wait(NAVIGATE_PAUSE); - cy.get(`#${buildNavigationLink(id)}`).click(); +Cypress.Commands.add('switchMode', (mode) => { + switch (mode) { + case MODES.GRID: + cy.get(`#${MODE_GRID_BUTTON_ID}`).click({ force: true }); + break; + case MODES.LIST: + cy.get(`#${MODE_LIST_BUTTON_ID}`).click({ force: true }); + break; + default: + console.error(`invalid mode ${mode} provided`); + break; + } }); diff --git a/cypress/support/commands/item.js b/cypress/support/commands/item.js new file mode 100644 index 000000000..2afdfa5e2 --- /dev/null +++ b/cypress/support/commands/item.js @@ -0,0 +1,54 @@ +import { ITEM_TYPES } from '../../../src/config/constants'; +import { + SHARE_ITEM_MODAL_PERMISSION_SELECT_ID, + SHARE_ITEM_MODAL_SHARE_BUTTON_ID, + buildPermissionOptionId, + SHARE_ITEM_MODAL_EMAIL_INPUT_ID, + buildTreeItemClass, + TREE_MODAL_CONFIRM_BUTTON_ID, + TREE_MODAL_TREE_ID, + ITEM_FORM_CONFIRM_BUTTON_ID, + ITEM_FORM_DESCRIPTION_INPUT_ID, + ITEM_FORM_IMAGE_INPUT_ID, + ITEM_FORM_NAME_INPUT_ID, + ITEM_FORM_TYPE_SELECT_ID, +} from '../../../src/config/selectors'; + +// eslint-disable-next-line import/prefer-default-export +Cypress.Commands.add('fillShareModal', ({ member, permission }) => { + // select permission + cy.get(`#${SHARE_ITEM_MODAL_PERMISSION_SELECT_ID}`).click(); + cy.get(`#${buildPermissionOptionId(permission)}`).click(); + + // input mail + cy.get(`#${SHARE_ITEM_MODAL_EMAIL_INPUT_ID}`).type(member.email); + + cy.get(`#${SHARE_ITEM_MODAL_SHARE_BUTTON_ID}`).click(); +}); + +Cypress.Commands.add('fillTreeModal', (toItemId) => { + cy.get( + `#${TREE_MODAL_TREE_ID} .${buildTreeItemClass( + toItemId, + )} .MuiTreeItem-label`, + ) + .first() + .click(); + + cy.get(`#${TREE_MODAL_CONFIRM_BUTTON_ID}`).click(); +}); + +Cypress.Commands.add( + 'fillItemModal', + ({ name = '', type = ITEM_TYPES.SPACE, extra = {}, description = '' }) => { + cy.get(`#${ITEM_FORM_NAME_INPUT_ID}`).clear().type(name); + + cy.get(`#${ITEM_FORM_DESCRIPTION_INPUT_ID}`).clear().type(description); + + cy.get(`#${ITEM_FORM_TYPE_SELECT_ID}`).click(); + cy.get(`li[data-value="${type}"]`).click(); + cy.get(`#${ITEM_FORM_IMAGE_INPUT_ID}`).clear().type(extra.image); + + cy.get(`#${ITEM_FORM_CONFIRM_BUTTON_ID}`).click(); + }, +); diff --git a/cypress/support/commands/navigation.js b/cypress/support/commands/navigation.js new file mode 100644 index 000000000..47ee0bbe5 --- /dev/null +++ b/cypress/support/commands/navigation.js @@ -0,0 +1,27 @@ +import { + buildItemLink, + buildItemsTableRowId, + buildNavigationLink, + NAVIGATION_HOME_LINK_ID, +} from '../../../src/config/selectors'; +import { NAVIGATE_PAUSE } from '../constants'; + +Cypress.Commands.add('goToItemInGrid', (id) => { + cy.wait(NAVIGATE_PAUSE); + cy.get(`#${buildItemLink(id)}`).click(); +}); + +Cypress.Commands.add('goToItemInList', (id) => { + cy.wait(NAVIGATE_PAUSE); + cy.get(`#${buildItemsTableRowId(id)}`).click(); +}); + +Cypress.Commands.add('goToHome', () => { + cy.wait(NAVIGATE_PAUSE); + cy.get(`#${NAVIGATION_HOME_LINK_ID}`).click(); +}); + +Cypress.Commands.add('goToItemWithNavigation', (id) => { + cy.wait(NAVIGATE_PAUSE); + cy.get(`#${buildNavigationLink(id)}`).click(); +}); diff --git a/cypress/support/server.js b/cypress/support/server.js index aee7280dc..def90fa0a 100644 --- a/cypress/support/server.js +++ b/cypress/support/server.js @@ -1,5 +1,6 @@ import { v4 as uuidv4 } from 'uuid'; import { StatusCodes } from 'http-status-codes'; +import qs from 'querystring'; import { buildCopyItemRoute, buildDeleteItemRoute, @@ -11,6 +12,7 @@ import { GET_OWN_ITEMS_ROUTE, buildShareItemWithRoute, MEMBERS_ROUTE, + ITEMS_ROUTE, } from '../../src/api/routes'; import { getItemById, @@ -89,6 +91,28 @@ export const mockDeleteItem = (items, shouldThrowError) => { ).as('deleteItem'); }; +export const mockDeleteItems = (items, shouldThrowError) => { + cy.intercept( + { + method: DEFAULT_DELETE.method, + pathname: `/${ITEMS_ROUTE}`, + query: { id: ID_FORMAT }, + }, + ({ url, reply }) => { + const ids = qs.parse(url.slice(url.indexOf('?') + 1)).id; + + if (shouldThrowError) { + return reply({ statusCode: StatusCodes.BAD_REQUEST, body: null }); + } + + return reply({ + statusCode: StatusCodes.OK, + body: ids.map((id) => getItemById(items, id)), + }); + }, + ).as('deleteItems'); +}; + export const mockGetItem = (items, shouldThrowError) => { cy.intercept( { diff --git a/package.json b/package.json index fccbe0d41..928040bd8 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "lodash.truncate": "4.4.2", "node-fetch": "2.6.1", "prop-types": "15.7.2", + "qs": "6.9.6", "react": "^17.0.1", "react-dom": "^17.0.1", "react-i18next": "11.8.5", diff --git a/src/actions/item.js b/src/actions/item.js index 0809a274d..9ecb0f87b 100644 --- a/src/actions/item.js +++ b/src/actions/item.js @@ -135,6 +135,8 @@ export const deleteItem = (itemId) => async (dispatch) => { try { dispatch(createFlag(FLAG_DELETING_ITEM, true)); await Api.deleteItem(itemId); + // eslint-disable-next-line no-console + console.log('woiefjksdnm,'); dispatch({ type: DELETE_ITEM_SUCCESS, payload: { id: itemId }, @@ -153,18 +155,21 @@ export const deleteItems = (itemIds) => async (dispatch) => { // choose corresponding call depending on number of items if (itemIds.length === 1) { await Api.deleteItem(itemIds); + dispatch({ + type: DELETE_ITEM_SUCCESS, + payload: { id: itemIds[0] }, + }); } else { await Api.deleteItems(itemIds); + dispatch({ + type: DELETE_ITEMS_SUCCESS, + payload: itemIds, + }); } - - dispatch({ - type: DELETE_ITEMS_SUCCESS, - payload: itemIds, - }); } catch (e) { console.error(e); } finally { - dispatch(createFlag(FLAG_DELETING_ITEM, false)); + dispatch(createFlag(FLAG_DELETING_ITEMS, false)); } }; diff --git a/src/api/routes.js b/src/api/routes.js index 1959c24e7..564d6c01e 100644 --- a/src/api/routes.js +++ b/src/api/routes.js @@ -1,20 +1,21 @@ -export const GET_OWN_ITEMS_ROUTE = `items/own`; -export const SHARE_ITEM_WITH_ROUTE = 'items/shared-with'; +export const ITEMS_ROUTE = 'items'; +export const GET_OWN_ITEMS_ROUTE = `${ITEMS_ROUTE}/own`; +export const SHARE_ITEM_WITH_ROUTE = `${ITEMS_ROUTE}/shared-with`; export const buildPostItemRoute = (parentId) => { - let url = `items`; + let url = ITEMS_ROUTE; if (parentId) { url += `?parentId=${parentId}`; } return url; }; -export const buildDeleteItemRoute = (id) => `items/${id}`; +export const buildDeleteItemRoute = (id) => `${ITEMS_ROUTE}/${id}`; export const buildDeleteItemsRoute = (ids) => - `items?${ids.map((id) => `id=${id}`).join('&')}`; -export const buildGetChildrenRoute = (id) => `items/${id}/children`; -export const buildGetItemRoute = (id) => `items/${id}`; -export const buildMoveItemRoute = (id) => `items/${id}/move`; -export const buildCopyItemRoute = (id) => `items/${id}/copy`; -export const buildEditItemRoute = (id) => `items/${id}`; + `${ITEMS_ROUTE}?${ids.map((id) => `id=${id}`).join('&')}`; +export const buildGetChildrenRoute = (id) => `${ITEMS_ROUTE}/${id}/children`; +export const buildGetItemRoute = (id) => `${ITEMS_ROUTE}/${id}`; +export const buildMoveItemRoute = (id) => `${ITEMS_ROUTE}/${id}/move`; +export const buildCopyItemRoute = (id) => `${ITEMS_ROUTE}/${id}/copy`; +export const buildEditItemRoute = (id) => `${ITEMS_ROUTE}/${id}`; export const buildShareItemWithRoute = (id) => `item-memberships?itemId=${id}`; export const buildGetItemMembershipForItemRoute = (id) => `item-memberships?itemId=${id}`; diff --git a/src/components/common/DeleteButton.js b/src/components/common/DeleteButton.js index a0991871e..cf570fd7e 100644 --- a/src/components/common/DeleteButton.js +++ b/src/components/common/DeleteButton.js @@ -8,12 +8,13 @@ import DeleteIcon from '@material-ui/icons/Delete'; import { deleteItems } from '../../actions/item'; import { ITEM_DELETE_BUTTON_CLASS } from '../../config/selectors'; -const DeleteButton = ({ itemIds, dispatchDeleteItems, color }) => { +const DeleteButton = ({ itemIds, dispatchDeleteItems, color, id }) => { const { t } = useTranslation(); return ( { @@ -19,7 +19,7 @@ const Item = ({ itemId, dispatchSetEditModalSettings }) => { diff --git a/src/components/common/ShareButton.js b/src/components/common/ShareButton.js index b91e6c03c..10edbf0c4 100644 --- a/src/components/common/ShareButton.js +++ b/src/components/common/ShareButton.js @@ -5,7 +5,7 @@ import IconButton from '@material-ui/core/IconButton'; import ShareIcon from '@material-ui/icons/Share'; import { useTranslation } from 'react-i18next'; import Tooltip from '@material-ui/core/Tooltip'; -import { ITEM_MENU_SHARE_BUTTON_CLASS } from '../../config/selectors'; +import { SHARE_ITEM_BUTTON_CLASS } from '../../config/selectors'; import { setShareModalSettings } from '../../actions/layout'; const Item = ({ itemId, dispatchSetShareModalSettings }) => { @@ -19,7 +19,7 @@ const Item = ({ itemId, dispatchSetShareModalSettings }) => { diff --git a/src/components/main/Home.js b/src/components/main/Home.js index 946e6060d..fc7d2c72d 100644 --- a/src/components/main/Home.js +++ b/src/components/main/Home.js @@ -8,6 +8,7 @@ import { withRouter } from 'react-router'; import ItemsHeader from './ItemsHeader'; import { setItem, getOwnItems, getSharedItems } from '../../actions/item'; import Items from './Items'; +import { OWNED_ITEMS_ID, SHARED_ITEMS_ID } from '../../config/selectors'; class Home extends Component { static propTypes = { @@ -54,9 +55,13 @@ class Home extends Component { return ( <> - + - + ); } diff --git a/src/components/main/ItemScreen.js b/src/components/main/ItemScreen.js index a0e5d0585..f358f8732 100644 --- a/src/components/main/ItemScreen.js +++ b/src/components/main/ItemScreen.js @@ -66,6 +66,7 @@ class ItemScreen extends Component { }, activity, } = this.props; + // todo: might have to change // necessary to avoid render return activity || itemId !== nextId || !areItemsEqual(item, nextItem); diff --git a/src/components/main/Items.js b/src/components/main/Items.js index 6f9a69e0f..60068c543 100644 --- a/src/components/main/Items.js +++ b/src/components/main/Items.js @@ -17,14 +17,19 @@ class Items extends Component { classes: PropTypes.shape({ title: PropTypes.string.isRequired, }).isRequired, + id: PropTypes.string, + }; + + static defaultProps = { + id: null, }; render() { - const { items, mode, title } = this.props; - return mode === MODES.CARD ? ( - + const { items, mode, title, id } = this.props; + return mode === MODES.GRID ? ( + ) : ( - + ); } } diff --git a/src/components/main/ItemsHeader.js b/src/components/main/ItemsHeader.js index 71e157e7a..3f6c24cdd 100644 --- a/src/components/main/ItemsHeader.js +++ b/src/components/main/ItemsHeader.js @@ -1,7 +1,7 @@ import React from 'react'; import { makeStyles } from '@material-ui/core/styles'; import Navigation from '../layout/Navigation'; -import ModeSwitch from './ModeSwitch'; +import ModeButtons from './ModeButtons'; const useStyles = makeStyles((theme) => ({ root: { @@ -17,7 +17,7 @@ const ItemsHeader = () => { return (
- +
); }; diff --git a/src/components/main/ItemsTable.js b/src/components/main/ItemsTable.js index 73160e417..ed38dbfe0 100644 --- a/src/components/main/ItemsTable.js +++ b/src/components/main/ItemsTable.js @@ -31,6 +31,12 @@ import NewItemButton from './NewItemButton'; import EditButton from '../common/EditButton'; import ShareButton from '../common/ShareButton'; import DeleteButton from '../common/DeleteButton'; +import { + buildItemsTableRowId, + ITEMS_TABLE_DELETE_SELECTED_ITEMS_ID, + ITEMS_TABLE_EMPTY_ROW_ID, + ITEMS_TABLE_ROW_CHECKBOX_CLASS, +} from '../../config/selectors'; const EnhancedTableHead = (props) => { const { @@ -149,7 +155,11 @@ const EnhancedTableToolbar = (props) => { )} {numSelected > 0 ? ( - + ) : null} ); @@ -195,7 +205,7 @@ const useStyles = makeStyles((theme) => ({ }, })); -const ItemsTable = ({ items: rows, tableTitle }) => { +const ItemsTable = ({ items: rows, tableTitle, id: tableId }) => { const classes = useStyles(); const { t } = useTranslation(); const { push } = useHistory(); @@ -352,6 +362,7 @@ const ItemsTable = ({ items: rows, tableTitle }) => { /> { return ( { > handleClick(event, row.id)} color="primary" /> - { - // does not render name - headCells.map(({ id: field, align, type }, idx) => ( - { - // do not navigate when clicking on actions - const shouldNavigate = idx !== headCells.length - 1; - if (shouldNavigate) { - handleRowOnClick(row.id); - } - }} - > - {formatRowValue({ value: row[field], type })} - - )) - } + {headCells.map(({ id: field, align, type }, idx) => ( + { + // do not navigate when clicking on actions + const shouldNavigate = idx !== headCells.length - 1; + if (shouldNavigate) { + handleRowOnClick(row.id); + } + }} + > + {formatRowValue({ value: row[field], type })} + + ))} ); })} {emptyRows > 0 && ( - + )} @@ -443,6 +456,11 @@ const ItemsTable = ({ items: rows, tableTitle }) => { ItemsTable.propTypes = { items: PropTypes.instanceOf(List).isRequired, tableTitle: PropTypes.string.isRequired, + id: PropTypes.string, +}; + +ItemsTable.defaultProps = { + id: '', }; export default ItemsTable; diff --git a/src/components/main/ModeSwitch.js b/src/components/main/ModeButtons.js similarity index 86% rename from src/components/main/ModeSwitch.js rename to src/components/main/ModeButtons.js index b4ee43bcb..3221e2604 100644 --- a/src/components/main/ModeSwitch.js +++ b/src/components/main/ModeButtons.js @@ -8,6 +8,10 @@ import ViewModuleIcon from '@material-ui/icons/ViewModule'; import IconButton from '@material-ui/core/IconButton'; import { MODES } from '../../config/constants'; import { setMode } from '../../actions/layout'; +import { + MODE_GRID_BUTTON_ID, + MODE_LIST_BUTTON_ID, +} from '../../config/selectors'; const ModeButtons = ({ dispatchSetMode, mode }) => { const { t } = useTranslation(); @@ -21,6 +25,7 @@ const ModeButtons = ({ dispatchSetMode, mode }) => { { handleOnClick(MODES.LIST); @@ -34,10 +39,11 @@ const ModeButtons = ({ dispatchSetMode, mode }) => { { - handleOnClick(MODES.CARD); + handleOnClick(MODES.GRID); }} > diff --git a/src/config/constants.js b/src/config/constants.js index 8f49665b0..9ab73b747 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -35,7 +35,7 @@ export const PERMISSION_LEVELS = { export const DEFAULT_PERMISSION_LEVEL = PERMISSION_LEVELS.WRITE; export const MODES = { - CARD: 'card', + GRID: 'grid', LIST: 'list', }; diff --git a/src/config/selectors.js b/src/config/selectors.js index 65e7645d9..ee33489af 100644 --- a/src/config/selectors.js +++ b/src/config/selectors.js @@ -18,10 +18,20 @@ export const TREE_MODAL_TREE_ID = 'treeModalTree'; export const buildTreeItemClass = (id) => `treeItem-${id}`; export const TREE_MODAL_CONFIRM_BUTTON_ID = 'treeModalConfirmButton'; export const ITEMS_GRID_NO_ITEM_ID = 'itemsGridNoItem'; -export const ITEM_MENU_EDIT_BUTTON_CLASS = 'itemMenuEditButton'; -export const ITEM_MENU_SHARE_BUTTON_CLASS = 'itemMenuShareButton'; +export const EDIT_ITEM_BUTTON_CLASS = 'editButton'; +export const SHARE_ITEM_BUTTON_CLASS = 'itemMenuShareButton'; export const SHARE_ITEM_MODAL_EMAIL_INPUT_ID = 'shareItemModalEmailInput'; export const SHARE_ITEM_MODAL_PERMISSION_SELECT_ID = 'shareItemModalPermissionSelect'; export const buildPermissionOptionId = (id) => `permission-${id}`; export const SHARE_ITEM_MODAL_SHARE_BUTTON_ID = 'shareItemModalShareButton'; +export const MODE_LIST_BUTTON_ID = 'modeListButton'; + +export const MODE_GRID_BUTTON_ID = 'modeCardButton'; +export const SHARED_ITEMS_ID = 'sharedItems'; +export const OWNED_ITEMS_ID = 'ownedItems'; +export const buildItemsTableRowId = (id) => `itemsTableRow-${id}`; +export const ITEMS_TABLE_EMPTY_ROW_ID = 'itemsTableEmptyRow'; +export const ITEMS_TABLE_DELETE_SELECTED_ITEMS_ID = + 'itemsTableDeleteSelectedItems'; +export const ITEMS_TABLE_ROW_CHECKBOX_CLASS = 'itemsTableRowCheckbox'; diff --git a/src/langs/en.json b/src/langs/en.json index 723cf5e61..bcbfe1e62 100644 --- a/src/langs/en.json +++ b/src/langs/en.json @@ -45,6 +45,16 @@ "Updated At": "Updated At", "My Items": "My Items", "Items Shared With Me": "Items Shared With Me", - "nbitem selected":"{{numSelected}} selected" + "nbitem selected": "{{numSelected}} selected", + "Delete": "Delete", + "sorted descending": "sorted descending", + "sorted ascending": "sorted ascending", + "select all items": "select all items", + "Actions": "Actions", + "View as Card": "View as Card", + "View as List": "View as List", + "Share": "Share", + "Permission": "Permission", + "Share Item": "Share Item" } } diff --git a/src/langs/fr.json b/src/langs/fr.json index 7d6c26046..85508511a 100644 --- a/src/langs/fr.json +++ b/src/langs/fr.json @@ -44,6 +44,17 @@ "Created At": "Créé à", "Updated At": "Mis à jour à", "My Items": "Mes éléments", - "Items Shared With Me": "Eléments partagés avec moi" + "Items Shared With Me": "Eléments partagés avec moi", + "nbitem selected": "{{numSelected}} sélectionné", + "Delete": "Supprimer", + "sorted descending": "trié par ordre décroissant", + "sorted ascending": "trié par ordre croissant", + "select all items": "Sélectioner Tous les Eléments", + "Actions": "Actions", + "View as Card": "Afficher avec des cartes", + "View as List": "Afficher en liste", + "Share": "Partager", + "Permission": "Permission", + "Share Item": "Partager un Elément" } } diff --git a/src/reducers/item.js b/src/reducers/item.js index 8bddfc003..721ffa340 100644 --- a/src/reducers/item.js +++ b/src/reducers/item.js @@ -24,6 +24,7 @@ import { FLAG_EDITING_ITEM, GET_SHARED_ITEMS_SUCCESS, DELETE_ITEMS_SUCCESS, + FLAG_DELETING_ITEMS, } from '../types/item'; const DEFAULT_ITEM = Map({ @@ -47,6 +48,7 @@ const INITIAL_STATE = Map({ [FLAG_COPYING_ITEM]: [], [FLAG_SETTING_ITEM]: [], [FLAG_EDITING_ITEM]: [], + [FLAG_DELETING_ITEMS]: [], }), }); @@ -86,6 +88,7 @@ export default (state = INITIAL_STATE, { type, payload }) => { case FLAG_CREATING_ITEM: case FLAG_GETTING_OWN_ITEMS: case FLAG_DELETING_ITEM: + case FLAG_DELETING_ITEMS: case FLAG_GETTING_CHILDREN: case FLAG_GETTING_ITEMS: case FLAG_MOVING_ITEM: diff --git a/src/utils/item.js b/src/utils/item.js index c402ed445..d5c3ade6a 100644 --- a/src/utils/item.js +++ b/src/utils/item.js @@ -10,6 +10,9 @@ export const getParentsIdsFromPath = (path) => export const getItemById = (items, id) => items.find(({ id: thisId }) => id === thisId); +export const getItemsById = (items, ids) => + items.filter(({ id: thisId }) => ids.includes(thisId)); + export const getDirectParentId = (path) => { const ids = getParentsIdsFromPath(path); const parentIdx = ids.length - 2; diff --git a/yarn.lock b/yarn.lock index 9da9ea7d0..fb717403d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10505,6 +10505,11 @@ qs@6.7.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== +qs@6.9.6: + version "6.9.6" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" + integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== + qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"