Skip to content

Commit

Permalink
feat: add shortcut previous button and map button (#716)
Browse files Browse the repository at this point in the history
* feat: add shortcut previous button and map button

* refactor: update graasp ui

* refactor: add tests

* refactor: apply PR requested changes

* refactor: update yarn lock

* refactor: fix name of back button

* refactor: set settings

* refactor: change path check

* refactor: add console

* refactor: use content page build

* refactor: remove only

* refactor: remove debug code
  • Loading branch information
pyphilia authored May 28, 2024
1 parent aa21756 commit 4777616
Show file tree
Hide file tree
Showing 21 changed files with 725 additions and 264 deletions.
87 changes: 86 additions & 1 deletion cypress/e2e/island.cy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { PackedFolderItemFactory } from '@graasp/sdk';

import { buildContentPagePath } from '@/config/paths';
import { ITEM_CHATBOX_BUTTON_ID } from '@/config/selectors';
import {
ITEM_CHATBOX_BUTTON_ID,
ITEM_MAP_BUTTON_ID,
buildTreeItemClass,
} from '@/config/selectors';

import {
DOCUMENT_WITHOUT_CHAT_BOX,
Expand All @@ -24,4 +30,83 @@ describe('Island', () => {
cy.visit(buildContentPagePath({ rootId: item.id, itemId: item.id }));
cy.get(`#${ITEM_CHATBOX_BUTTON_ID}`).should('not.exist');
});

describe('map', () => {
it('Do not show button for no geolocation', () => {
const parentItem = PackedFolderItemFactory({ settings: {} });
cy.setUpApi({
items: [parentItem],
});
cy.visit(
buildContentPagePath({ rootId: parentItem.id, itemId: parentItem.id }),
);
cy.get(`#${ITEM_MAP_BUTTON_ID} button`).should('not.exist');
});

it('Show map button for parent geolocation', () => {
const parentItem = PackedFolderItemFactory({ settings: {} });
const child = PackedFolderItemFactory({ parentItem, settings: {} });
const geolocation = { lat: 0, lng: 0, item: parentItem };
cy.setUpApi({
items: [{ ...parentItem, geolocation }, child],
});
cy.visit(
buildContentPagePath({ rootId: parentItem.id, itemId: parentItem.id }),
);
cy.get(`#${ITEM_MAP_BUTTON_ID} button`)
.should('be.visible')
.should('not.be.disabled');
// check is parent link
cy.get(`#${ITEM_MAP_BUTTON_ID}`)
.parent()
.should('have.attr', 'href')
.should('include', parentItem.id)
.should('include', 'mode=map');

cy.get(`.${buildTreeItemClass(child.id)}:visible`).click();
cy.get(`#${ITEM_MAP_BUTTON_ID} button`)
.should('be.visible')
.should('not.be.disabled');
// check is parent link
cy.get(`#${ITEM_MAP_BUTTON_ID}`)
.parent()
.should('have.attr', 'href')
.should('include', parentItem.id)
.should('include', 'mode=map');
});

it('Show map button for child geolocation', () => {
const parentItem = PackedFolderItemFactory({ settings: {} });
const child1 = PackedFolderItemFactory({ parentItem, settings: {} });
const child2 = PackedFolderItemFactory({ parentItem, settings: {} });
const geolocation = { lat: 0, lng: 0, item: child1 };
cy.setUpApi({
items: [parentItem, { ...child1, geolocation }, child2],
});
cy.visit(
buildContentPagePath({ rootId: parentItem.id, itemId: parentItem.id }),
);
cy.get(`#${ITEM_MAP_BUTTON_ID} button`)
.should('be.visible')
.should('be.disabled');

cy.get(`.${buildTreeItemClass(child1.id)}:visible`).click();

cy.get(`#${ITEM_MAP_BUTTON_ID} button`)
.should('be.visible')
.should('not.be.disabled');
// check is parent link
cy.get(`#${ITEM_MAP_BUTTON_ID}`)
.parent()
.should('have.attr', 'href')
.should('include', child1.id)
.should('include', 'mode=map');

cy.get(`.${buildTreeItemClass(child2.id)}:visible`).click();

cy.get(`#${ITEM_MAP_BUTTON_ID} button`)
.should('be.visible')
.should('be.disabled');
});
});
});
141 changes: 141 additions & 0 deletions cypress/e2e/shortcut.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import {
PackedFolderItemFactory,
PackedShortcutItemFactory,
} from '@graasp/sdk';

import 'cypress-iframe';
import { v4 } from 'uuid';

import { buildContentPagePath } from '@/config/paths';
import { BACK_TO_SHORTCUT_ID, buildFolderButtonId } from '@/config/selectors';

describe('Shortcuts', () => {
it('Come back from shortcut navigation', () => {
const parentItem = PackedFolderItemFactory({
name: 'parent item',
settings: {},
});
const toShortcut = PackedFolderItemFactory({
name: 'target folder',
settings: {},
});
const shortcut = PackedShortcutItemFactory({
name: 'shortcut',
parentItem,
settings: {},
extra: { shortcut: { target: toShortcut.id } },
});
cy.setUpApi({ items: [parentItem, shortcut, toShortcut] });

cy.visit(
buildContentPagePath({ rootId: parentItem.id, itemId: parentItem.id }),
);

// click on folder shortcut
cy.get(`#${buildFolderButtonId(toShortcut.id)}`).click();
cy.url()
.should('contain', 'from')
.and('contain', parentItem.id)
.and('contain', 'fromName')
.and('contain', 'parent+item');

cy.wait(3000);

// go back to origin
cy.get(`#${BACK_TO_SHORTCUT_ID}`).click();
cy.url().should('contain', parentItem.id);
});

it('Keep other params from shortcut navigation like shuffle', () => {
const parentItem = PackedFolderItemFactory({
name: 'parent item',
settings: {},
});
const toShortcut = PackedFolderItemFactory({
name: 'target folder',
settings: {},
});
const shortcut = PackedShortcutItemFactory({
name: 'shortcut',
parentItem,
settings: {},
extra: { shortcut: { target: toShortcut.id } },
});
cy.setUpApi({ items: [parentItem, shortcut, toShortcut] });

cy.visit(
buildContentPagePath({
rootId: parentItem.id,
itemId: parentItem.id,
searchParams: 'fullscreen=true',
}),
);

// click on folder shortcut
cy.get(`#${buildFolderButtonId(toShortcut.id)}`).click();
cy.url()
.should('contain', 'from')
.and('contain', parentItem.id)
.and('contain', 'fromName')
.and('contain', 'parent+item')
.and('contain', 'fullscreen=true');

// go back to origin
cy.get(`#${BACK_TO_SHORTCUT_ID}`).click();
cy.url().should('contain', parentItem.id).and('contain', 'fullscreen=true');
});

it('No from name does not show button', () => {
const parentItem = PackedFolderItemFactory({ name: 'parent item' });
cy.setUpApi({ items: [parentItem] });

cy.visit(
`${buildContentPagePath({
rootId: parentItem.id,
itemId: parentItem.id,
})}?from=/${v4()}`,
);

// need wait for wrongly shown button to appear
cy.wait(1000);

// should not show from button
cy.get(`#${BACK_TO_SHORTCUT_ID}`).should('not.exist');
});

it('Hacking query params is safe', () => {
const parentItem = PackedFolderItemFactory({ name: 'parent item' });
cy.setUpApi({ items: [parentItem] });

cy.visit(
`${buildContentPagePath({
rootId: parentItem.id,
itemId: parentItem.id,
})}?from=/idid&fromName=shouldnotdisplay`,
);

// need wait for wrongly shown button to appear
cy.wait(1000);

// should not show from button
cy.get(`#${BACK_TO_SHORTCUT_ID}`).should('not.exist');
});

it('Hacking from url with external url is safe', () => {
const parentItem = PackedFolderItemFactory({ name: 'parent item' });
cy.setUpApi({ items: [parentItem] });

cy.visit(
`${buildContentPagePath({
rootId: parentItem.id,
itemId: parentItem.id,
})}?from=http://example.org&fromName=shouldnotdisplay`,
);

// need wait for wrongly shown button to appear
cy.wait(1000);

// should not show from button
cy.get(`#${BACK_TO_SHORTCUT_ID}`).should('not.exist');
});
});
8 changes: 7 additions & 1 deletion cypress/fixtures/mockTypes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { ItemTag, PackedItem, PermissionLevel } from '@graasp/sdk';
import {
ItemGeolocation,
ItemTag,
PackedItem,
PermissionLevel,
} from '@graasp/sdk';

export type MockItemTag = Omit<ItemTag, 'item'>;
export type MockItem = Omit<PackedItem, 'permission' | 'hidden' | 'public'> & {
Expand All @@ -9,4 +14,5 @@ export type MockItem = Omit<PackedItem, 'permission' | 'hidden' | 'public'> & {
memberships?: { memberId: string; permission: PermissionLevel }[];
hidden?: MockItemTag;
public?: MockItemTag;
geolocation?: Partial<ItemGeolocation>;
};
5 changes: 5 additions & 0 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ import {
mockGetDescendants,
mockGetItem,
mockGetItemChat,
mockGetItemGeolocation,
mockGetItemMembershipsForItem,
mockGetItemTags,
mockGetItemsInMap,
mockGetItemsTags,
mockGetLoginSchemaType,
mockGetMemberBy,
Expand Down Expand Up @@ -82,6 +84,9 @@ Cypress.Commands.add(
mockPostAppData(getAppLinkError);
mockPatchAppData(getAppLinkError);
mockDeleteAppData(getAppLinkError);

mockGetItemGeolocation(items);
mockGetItemsInMap(items, currentMember);
},
);

Expand Down
Loading

0 comments on commit 4777616

Please sign in to comment.