Skip to content

Commit

Permalink
feat: disable guest row in membership table (#1479)
Browse files Browse the repository at this point in the history
* feat: disable guest row in membership table

* refactor: update put item login schema instead of delete

* refactor: update sdk

* refactor: update query client

* refactor: fix tests

* refactor: apply PR requested changes
  • Loading branch information
pyphilia authored Sep 27, 2024
1 parent 7f3ba1b commit 5d2c0b0
Show file tree
Hide file tree
Showing 15 changed files with 310 additions and 81 deletions.
16 changes: 8 additions & 8 deletions cypress/e2e/item/authorization/itemLogin/utils.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { ItemLoginSchema, ItemLoginSchemaType, PackedItem } from '@graasp/sdk';

import { v4 } from 'uuid';
import {
ItemLoginSchema,
ItemLoginSchemaFactory,
ItemLoginSchemaType,
PackedItem,
} from '@graasp/sdk';

export const addItemLoginSchema = (
item: PackedItem,
itemLoginSchemaType: ItemLoginSchemaType,
): PackedItem & { itemLoginSchema: ItemLoginSchema } => ({
...item,
itemLoginSchema: {
itemLoginSchema: ItemLoginSchemaFactory({
item,
type: itemLoginSchemaType,
id: v4(),
createdAt: '2021-08-11T12:56:36.834Z',
updatedAt: '2021-08-11T12:56:36.834Z',
},
}),
});
16 changes: 15 additions & 1 deletion cypress/e2e/item/share/changeVisibility.cy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
ItemLoginSchemaStatus,
ItemLoginSchemaType,
ItemTagType,
PackedFolderItemFactory,
Expand Down Expand Up @@ -91,6 +92,12 @@ describe('Visibility of an Item', () => {
} = data[0];
expect(url).to.contain(item.id);
expect(url).to.contain(ItemTagType.Public); // originally item login

const {
request: { body, url: itemLoginUrl },
} = data[1];
expect(itemLoginUrl).to.contain(item.id);
expect(body.status).to.contain(ItemLoginSchemaStatus.Active);
});
});

Expand Down Expand Up @@ -125,8 +132,9 @@ describe('Visibility of an Item', () => {

// change pseudonymized -> private
changeVisibility(SETTINGS.ITEM_PRIVATE.name);
cy.wait(`@deleteItemLoginSchema`).then(({ request: { url } }) => {
cy.wait(`@putItemLoginSchema`).then(({ request: { url, body } }) => {
expect(url).to.include(item.id);
expect(body.status).to.eq(ItemLoginSchemaStatus.Disabled);
});
});

Expand Down Expand Up @@ -193,6 +201,12 @@ describe('Visibility of an Item', () => {
} = data[0];
expect(url).to.contain(item.id);
expect(url).to.contain(ItemTagType.Public); // originally item login

const {
request: { url: itemLoginUrl, body },
} = data[1];
expect(itemLoginUrl).to.contain(item.id); // originally item login
expect(body.status).to.eq(ItemLoginSchemaStatus.Active);
});
});
});
Expand Down
174 changes: 171 additions & 3 deletions cypress/e2e/memberships/viewMemberships.cy.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { Member, PackedFolderItemFactory, PermissionLevel } from '@graasp/sdk';
import {
GuestFactory,
ItemLoginSchemaFactory,
ItemLoginSchemaStatus,
ItemLoginSchemaType,
Member,
PackedFolderItemFactory,
PermissionLevel,
} from '@graasp/sdk';
import { namespaces } from '@graasp/translations';

import i18n from '@/config/i18n';

import { buildItemPath } from '../../../src/config/paths';
import { buildItemPath, buildItemSharePath } from '../../../src/config/paths';
import {
buildDataCyWrapper,
buildItemMembershipRowDeleteButtonId,
Expand Down Expand Up @@ -43,7 +51,7 @@ const membershipsWithoutAdmin = [
}),
];

describe('View Memberships', () => {
describe('View Memberships - Individual', () => {
beforeEach(() => {
cy.setUpApi({
items: [
Expand Down Expand Up @@ -85,6 +93,166 @@ describe('View Memberships', () => {
});
});

describe('View Memberships - Guest', () => {
it('view guest membership', () => {
const itemLoginSchema = ItemLoginSchemaFactory({
type: ItemLoginSchemaType.Username,
item: itemWithAdmin,
});
const guestMemberships = [
buildItemMembership({
item: itemWithAdmin,
permission: PermissionLevel.Read,
account: GuestFactory({
itemLoginSchema,
}),
creator: MEMBERS.ANNA,
}),
buildItemMembership({
item: itemWithAdmin,
permission: PermissionLevel.Read,
account: GuestFactory({
itemLoginSchema,
}),
creator: MEMBERS.ANNA,
}),
];
const item = itemWithAdmin;
cy.setUpApi({
items: [
{
...itemWithAdmin,
itemLoginSchema,
memberships: [adminMembership, ...guestMemberships],
},
],
});
i18n.changeLanguage(CURRENT_USER.extra.lang);
cy.visit(buildItemSharePath(item.id));
// editable rows
for (const { permission, account, id } of guestMemberships) {
const { name } = Object.values(
guestMemberships.map((m) => m.account),
).find(({ id: mId }) => mId === account.id);

// check name and disabled permission
cy.get(buildDataCyWrapper(buildItemMembershipRowId(id)))
.should('contain', name)
.should('contain', i18n.t(permission, { ns: namespaces.enums }));

// check delete button exists
cy.get(`#${buildItemMembershipRowDeleteButtonId(id)}`).should('exist');
}
});
it('view frozen guest membership', () => {
const itemLoginSchema = ItemLoginSchemaFactory({
type: ItemLoginSchemaType.Username,
item: itemWithAdmin,
status: ItemLoginSchemaStatus.Freeze,
});
const guestMemberships = [
buildItemMembership({
item: itemWithAdmin,
permission: PermissionLevel.Read,
account: GuestFactory({
itemLoginSchema,
}),
creator: MEMBERS.ANNA,
}),
buildItemMembership({
item: itemWithAdmin,
permission: PermissionLevel.Read,
account: GuestFactory({
itemLoginSchema,
}),
creator: MEMBERS.ANNA,
}),
];
const item = itemWithAdmin;
cy.setUpApi({
items: [
{
...itemWithAdmin,
itemLoginSchema,
memberships: [adminMembership, ...guestMemberships],
},
],
});
i18n.changeLanguage(CURRENT_USER.extra.lang);
cy.visit(buildItemSharePath(item.id));
// editable rows
for (const { permission, account, id } of guestMemberships) {
const { name } = Object.values(
guestMemberships.map((m) => m.account),
).find(({ id: mId }) => mId === account.id);

// check name and disabled permission
cy.get(buildDataCyWrapper(buildItemMembershipRowId(id)))
.should('contain', name)
.should('contain', i18n.t(permission, { ns: namespaces.enums }));

// check delete button exists
cy.get(`#${buildItemMembershipRowDeleteButtonId(id)}`).should('exist');
}
});

it('view disabled guest membership', () => {
const itemLoginSchema = ItemLoginSchemaFactory({
type: ItemLoginSchemaType.Username,
item: itemWithAdmin,
status: ItemLoginSchemaStatus.Disabled,
});
const guestMemberships = [
buildItemMembership({
item: itemWithAdmin,
permission: PermissionLevel.Read,
account: GuestFactory({
itemLoginSchema,
}),
creator: MEMBERS.ANNA,
}),
buildItemMembership({
item: itemWithAdmin,
permission: PermissionLevel.Read,
account: GuestFactory({
itemLoginSchema,
}),
creator: MEMBERS.ANNA,
}),
];
const item = itemWithAdmin;
cy.setUpApi({
items: [
{
...itemWithAdmin,
itemLoginSchema,
memberships: [adminMembership, ...guestMemberships],
},
],
});
i18n.changeLanguage(CURRENT_USER.extra.lang);
cy.visit(buildItemSharePath(item.id));
// editable rows
for (const { permission, account, id } of guestMemberships) {
const { name } = Object.values(
guestMemberships.map((m) => m.account),
).find(({ id: mId }) => mId === account.id);

// check name and disabled permission
cy.get(buildDataCyWrapper(buildItemMembershipRowId(id)))
.should('contain', name)
.should('not.contain', permission)
.should(
'contain',
i18n.t(ItemLoginSchemaStatus.Disabled, { ns: namespaces.enums }),
);

// check delete button exists
cy.get(`#${buildItemMembershipRowDeleteButtonId(id)}`).should('exist');
}
});
});

describe('View Memberships Read-Only Mode', () => {
it('view membership in settings read-only mode', () => {
const item = PackedFolderItemFactory(
Expand Down
3 changes: 0 additions & 3 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {
mockDeleteFavorite,
mockDeleteInvitation,
mockDeleteItemCategory,
mockDeleteItemLoginSchemaRoute,
mockDeleteItemMembershipForItem,
mockDeleteItemTag,
mockDeleteItemThumbnail,
Expand Down Expand Up @@ -337,8 +336,6 @@ Cypress.Commands.add(

mockUpdatePassword(members, updatePasswordError);

mockDeleteItemLoginSchemaRoute(items);

mockGetItemFavorites(bookmarkedItems, getFavoriteError);

mockAddFavorite(cachedItems, addFavoriteError);
Expand Down
20 changes: 0 additions & 20 deletions cypress/support/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -948,26 +948,6 @@ export const mockPostItemLogin = (
).as('postItemLogin');
};

export const mockDeleteItemLoginSchemaRoute = (items: ItemForTest[]): void => {
cy.intercept(
{
method: HttpMethod.Delete,
// TODO: use build url
url: new RegExp(`${API_HOST}/items/${ID_FORMAT}/login-schema$`),
},
({ reply, url }) => {
// check query match item login schema
const id = url.slice(API_HOST.length).split('/')[2];
const item: ItemForTest = getItemById(items, id);

// TODO: item login is not in extra anymore
item.itemLoginSchema = null;

reply(item);
},
).as('deleteItemLoginSchema');
};

export const mockPutItemLoginSchema = (
items: ItemForTest[],
shouldThrowError: boolean,
Expand Down
4 changes: 3 additions & 1 deletion cypress/support/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
ItemTag,
ItemValidationGroup,
LocalFileItemType,
PackedItem,
PermissionLevel,
PublicationStatus,
RecycledItemData,
Expand All @@ -23,7 +24,8 @@ import {

export type ItemForTest = DiscriminatedItem & {
categories?: ItemCategory[];
thumbnails?: string;
// TODO: INCORRECT! Fix in coming
thumbnails?: PackedItem['thumbnails'];
tags?: ItemTag[];
itemLoginSchema?: ItemLoginSchema;
readFilepath?: string;
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
"@emotion/styled": "11.13.0",
"@graasp/chatbox": "3.3.0",
"@graasp/map": "1.18.0",
"@graasp/query-client": "3.24.0",
"@graasp/sdk": "4.29.1",
"@graasp/query-client": "3.25.0",
"@graasp/sdk": "4.31.0",
"@graasp/stylis-plugin-rtl": "2.2.0",
"@graasp/translations": "1.38.0",
"@graasp/ui": "5.2.0",
Expand Down
Loading

0 comments on commit 5d2c0b0

Please sign in to comment.