diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Team/components/EditorUpsertModal.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Team/components/EditorUpsertModal.tsx index 1f74e1f528..b9c74de535 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Team/components/EditorUpsertModal.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Team/components/EditorUpsertModal.tsx @@ -26,6 +26,8 @@ import { optimisticallyUpdateExistingMember, } from "./lib/optimisticallyUpdateMembersTable"; +export const DEMO_TEAM_ID = 32; + export const EditorUpsertModal = ({ setShowModal, showModal, @@ -34,6 +36,8 @@ export const EditorUpsertModal = ({ }: EditorModalProps) => { const [showUserAlreadyExistsError, setShowUserAlreadyExistsError] = useState(false); + const [ teamId, teamSlug ] = useStore(state => [state.teamId, state.teamSlug]) + const isDemoTeam = teamId === DEMO_TEAM_ID; const toast = useToast(); @@ -56,15 +60,11 @@ export const EditorUpsertModal = ({ }; const handleSubmitToAddNewUser = async () => { - const { teamId, teamSlug } = useStore.getState(); - - const createUserResult = await createAndAddUserToTeam( - formik.values.email, - formik.values.firstName, - formik.values.lastName, + const createUserResult = await createAndAddUserToTeam({ + newUser: formik.values, teamId, teamSlug, - ).catch((err) => { + }).catch((err) => { if (isUserAlreadyExistsError(err.message)) { setShowUserAlreadyExistsError(true); } @@ -114,6 +114,8 @@ export const EditorUpsertModal = ({ firstName: initialValues?.firstName || "", lastName: initialValues?.lastName || "", email: initialValues?.email || "", + // Users within the Demo team are granted a role with a restricted permission set + role: isDemoTeam ? "demoUser" : "teamEditor", }, validationSchema: upsertEditorSchema, onSubmit: handleSubmit, diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Team/components/lib/optimisticallyUpdateMembersTable.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Team/components/lib/optimisticallyUpdateMembersTable.tsx index a499633f7f..b13960045b 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Team/components/lib/optimisticallyUpdateMembersTable.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Team/components/lib/optimisticallyUpdateMembersTable.tsx @@ -13,7 +13,6 @@ export const optimisticallyAddNewMember = async ( const existingMembers = useStore.getState().teamMembers; const newMember: TeamMember = { ...values, - role: "teamEditor", id: userId, }; diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Team/queries/createAndAddUserToTeam.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Team/queries/createAndAddUserToTeam.tsx index 594657bb63..dfb805df85 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Team/queries/createAndAddUserToTeam.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Team/queries/createAndAddUserToTeam.tsx @@ -2,19 +2,18 @@ import { FetchResult, gql } from "@apollo/client"; import { GET_USERS_FOR_TEAM_QUERY } from "routes/teamMembers"; import { client } from "../../../../../lib/graphql"; +import { AddNewEditorFormValues } from "../types"; type CreateAndAddUserResponse = FetchResult<{ - insert_users_one: { id: number; __typename: "users" }; + insertUsersOne: { id: number; __typename: "users" }; }>; -export const createAndAddUserToTeam = async ( - email: string, - firstName: string, - lastName: string, - teamId: number, - teamSlug: string +export const createAndAddUserToTeam = async ({ + newUser, + teamId, + teamSlug, +}: { newUser: AddNewEditorFormValues, teamId: number, teamSlug: string } ) => { - // NB: the user is hard-coded with the 'teamEditor' role for now const response: CreateAndAddUserResponse = await client.mutate({ mutation: gql` mutation CreateAndAddUserToTeam( @@ -22,13 +21,14 @@ export const createAndAddUserToTeam = async ( $firstName: String! $lastName: String! $teamId: Int! + $role: user_roles_enum! ) { - insert_users_one( + insertUsersOne: insert_users_one( object: { email: $email first_name: $firstName last_name: $lastName - teams: { data: { role: teamEditor, team_id: $teamId } } + teams: { data: { role: $role, team_id: $teamId } } } ) { id @@ -36,9 +36,7 @@ export const createAndAddUserToTeam = async ( } `, variables: { - email, - firstName, - lastName, + ...newUser, teamId, }, refetchQueries: [ @@ -47,7 +45,7 @@ export const createAndAddUserToTeam = async ( }); if (response.data) { - return response.data.insert_users_one; + return response.data.insertUsersOne; } throw new Error("Unable to create user"); }; diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.addNewEditor.demoTeam.test.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.addNewEditor.demoTeam.test.tsx new file mode 100644 index 0000000000..e14a223595 --- /dev/null +++ b/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.addNewEditor.demoTeam.test.tsx @@ -0,0 +1,57 @@ +import { waitFor, within } from "@testing-library/react"; +import { useStore } from "pages/FlowEditor/lib/store"; +import { vi } from "vitest"; + +import { DEMO_TEAM_ID } from "../components/EditorUpsertModal"; +import { setupTeamMembersScreen } from "./helpers/setupTeamMembersScreen"; +import { userTriesToAddNewEditor } from "./helpers/userTriesToAddNewEditor"; +import { mockTeamMembersData } from "./mocks/mockTeamMembersData"; +import { mockPlatformAdminUser } from "./mocks/mockUsers"; + +const { setState, getState } = useStore; + +vi.mock( + "pages/FlowEditor/components/Team/queries/createAndAddUserToTeam.tsx", + async () => ({ + createAndAddUserToTeam: vi.fn().mockResolvedValue({ + id: 1, + __typename: "users", + }), + }) +); + +describe("adding a new user to the Demo team", () => { + beforeEach(async () => { + setState({ + user: mockPlatformAdminUser, + teamMembers: mockTeamMembersData, + teamId: DEMO_TEAM_ID, + }); + }); + + it("assigns the `demoUser` role automatically", async () => { + let currentUsers = getState().teamMembers + expect(currentUsers).toHaveLength(3); + + const { user, getByTestId } = await setupTeamMembersScreen(); + await userTriesToAddNewEditor(user); + + const membersTable = getByTestId("members-table-add-editor"); + + await waitFor(() => { + expect( + within(membersTable).getByText(/Mickey Mouse/), + ).toBeInTheDocument(); + }); + + currentUsers = getState().teamMembers + expect(currentUsers).toHaveLength(4); + + // Role correctly assigned to user + const newUser = getState().teamMembers[3]; + expect(newUser.role).toBe("demoUser"); + + // Use role tag displayed in table + expect(within(membersTable).getByText("demoUser")).toBeVisible(); + }); +}); diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.addNewEditor.test.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.addNewEditor.test.tsx index 2707a882df..5ec4040a2e 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.addNewEditor.test.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.addNewEditor.test.tsx @@ -35,6 +35,7 @@ describe("when a user presses 'add a new editor'", () => { teamMembers: mockTeamMembersData, user: mockPlatformAdminUser, teamSlug: "planx", + teamId: 1, }); const { user } = await setupTeamMembersScreen(); @@ -59,6 +60,7 @@ describe("when a user fills in the 'add a new editor' form correctly", () => { teamMembers: mockTeamMembersData, user: mockPlatformAdminUser, teamSlug: "planx", + teamId: 1, }); const { user } = await setupTeamMembersScreen(); await userTriesToAddNewEditor(user); @@ -112,6 +114,7 @@ describe("'add a new editor' button is hidden from Templates team", () => { teamMembers: mockTeamMembersData, user: mockPlatformAdminUser, teamSlug: "templates", + teamId: 2, }); }); @@ -130,6 +133,7 @@ describe("when a user is not a platform admin", () => { teamMembers: mockTeamMembersData, user: mockPlainUser, teamSlug: "trumptonshire", + teamId: 3, }); }); diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.removeUser.test.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.removeUser.test.tsx index e07a0c74c9..555c39f0ed 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.removeUser.test.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.removeUser.test.tsx @@ -25,6 +25,7 @@ describe("when a user presses 'remove' button", () => { teamMembers: mockTeamMembersData, user: mockPlatformAdminUser, teamSlug: "planx", + teamId: 1, }); const { user, container } = await setupTeamMembersScreen(); @@ -74,6 +75,7 @@ describe("when a user clicks 'Remove user' button", () => { teamMembers: mockTeamMembersData, user: mockPlatformAdminUser, teamSlug: "planx", + teamId: 1, }); const { user } = await setupTeamMembersScreen(); @@ -119,6 +121,7 @@ describe("'remove' button is hidden from Templates team", () => { teamMembers: mockTeamMembersData, user: mockPlatformAdminUser, teamSlug: "templates", + teamId: 2, }); }); @@ -137,6 +140,7 @@ describe("when a user is not a platform admin", () => { teamMembers: mockTeamMembersData, user: mockPlainUser, team: "planx", + teamId: 1, }); await setupTeamMembersScreen(); diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.updateEditor.test.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.updateEditor.test.tsx index b43b6478bc..3e4c01497b 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.updateEditor.test.tsx +++ b/editor.planx.uk/src/pages/FlowEditor/components/Team/tests/TeamMembers.updateEditor.test.tsx @@ -18,6 +18,7 @@ describe("when a user presses 'edit button'", () => { teamMembers: mockTeamMembersData, user: mockPlatformAdminUser, teamSlug: "planx", + teamId: 1, }); const { user } = await setupTeamMembersScreen(); @@ -171,6 +172,7 @@ describe("'edit' button is hidden from Templates team", () => { teamMembers: mockTeamMembersData, user: mockPlatformAdminUser, teamSlug: "templates", + teamId: 3, }); }); @@ -188,6 +190,7 @@ describe("when a user is not a platform admin", () => { teamMembers: mockTeamMembersData, user: mockPlainUser, team: "planx", + teamId: 1, }); await setupTeamMembersScreen(); diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Team/types.ts b/editor.planx.uk/src/pages/FlowEditor/components/Team/types.ts index 5ad87a8a6e..a2ccdfdcf7 100644 --- a/editor.planx.uk/src/pages/FlowEditor/components/Team/types.ts +++ b/editor.planx.uk/src/pages/FlowEditor/components/Team/types.ts @@ -1,4 +1,4 @@ -import { Role, User } from "@opensystemslab/planx-core/types"; +import { Role, TeamRole, User } from "@opensystemslab/planx-core/types"; import React, { SetStateAction } from "react"; export type TeamMember = ActiveTeamMember | ArchivedTeamMember; @@ -25,6 +25,7 @@ export interface AddNewEditorFormValues { email: string; firstName: string; lastName: string; + role: TeamRole; } export interface UpdateEditorFormValues {