Skip to content

Commit 1b8dc55

Browse files
committed
Fix buttons displaying for UserRow
1 parent f7dd4e1 commit 1b8dc55

File tree

3 files changed

+120
-104
lines changed

3 files changed

+120
-104
lines changed

src/components/user/UserRow.jsx

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,11 @@ let UserRow = (props) => {
2323
<td className="report-row">{user.username}</td>
2424
<td className="report-row">{user.institution ? user.institution.name : ""}</td>
2525
<td className="report-row">{user.emailAddress}</td>
26-
<IfInternalAuth>
27-
<td className="report-row actions">
28-
<Button
29-
variant="primary"
30-
size="sm"
31-
title={i18n("users.open-tooltip")}
32-
onClick={() => props.onEdit(props.user)}
33-
>
34-
{i18n("open")}
35-
</Button>
26+
<td className="report-row actions">
27+
<Button variant="primary" size="sm" title={i18n("users.open-tooltip")} onClick={() => props.onEdit(props.user)}>
28+
{i18n("open")}
29+
</Button>
30+
<IfInternalAuth>
3631
<Button
3732
variant="warning"
3833
size="sm"
@@ -41,8 +36,8 @@ let UserRow = (props) => {
4136
>
4237
{i18n("delete")}
4338
</Button>
44-
</td>
45-
</IfInternalAuth>
39+
</IfInternalAuth>
40+
</td>
4641
</tr>
4742
);
4843
};

src/components/user/UserTable.jsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { injectIntl } from "react-intl";
55
import withI18n from "../../i18n/withI18n";
66
import UserRow from "./UserRow";
77
import PropTypes from "prop-types";
8-
import IfInternalAuth from "../misc/oidc/IfInternalAuth";
98

109
class UserTable extends React.Component {
1110
static propTypes = {
@@ -71,9 +70,7 @@ class UserTable extends React.Component {
7170
<th className="w-20 content-center">{this.i18n("login.username")}</th>
7271
<th className="w-20 content-center">{this.i18n("institution.name")}</th>
7372
<th className="w-20 content-center">{this.i18n("users.email")}</th>
74-
<IfInternalAuth>
75-
<th className="w-20 content-center">{this.i18n("actions")}</th>
76-
</IfInternalAuth>
73+
<th className="w-20 content-center">{this.i18n("actions")}</th>
7774
</tr>
7875
</thead>
7976
);
Lines changed: 112 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,126 @@
1-
"use strict";
2-
1+
import { describe, it, expect, vi, beforeEach } from "vitest";
2+
import { render, screen, fireEvent } from "@testing-library/react";
3+
import "@testing-library/jest-dom";
34
import React from "react";
5+
import UserRow from "../../../src/components/user/UserRow.jsx";
46
import { IntlProvider } from "react-intl";
5-
import TestUtils from "react-dom/test-utils";
6-
import UserRow from "../../../src/components/user/UserRow";
7-
import enLang from "../../../src/i18n/en";
8-
import { describe, expect, it, vi } from "vitest";
7+
import enLang from "../../../src/i18n/en.js";
8+
import { isUsingOidcAuth } from "../../../src/utils/OidcUtils.js";
9+
10+
vi.mock("../../../src/utils/OidcUtils", () => ({
11+
isUsingOidcAuth: vi.fn(() => false),
12+
}));
913

10-
describe("UserRow", function () {
14+
const renderWithIntl = (ui) => {
1115
const intlData = enLang;
12-
let user,
13-
deletionLoading = false,
14-
onEdit = vi.fn(),
15-
onDelete = vi.fn();
16-
17-
user = {
18-
uri: "http://onto.fel.cvut.cz/ontologies/record-manager/Admin-Administratorowitch",
19-
firstName: "Test1",
20-
lastName: "Man",
21-
username: "testman1",
22-
emailAddress: "[email protected]",
23-
institution: {
24-
uri: "http://test.io",
25-
key: "823372507340798303",
26-
name: "Test Institution",
27-
emailAddress: "[email protected]",
28-
},
29-
types: [
30-
"http://onto.fel.cvut.cz/ontologies/record-manager/administrator",
31-
"http://onto.fel.cvut.cz/ontologies/record-manager/doctor",
32-
],
16+
return render(
17+
<IntlProvider locale="en" {...intlData}>
18+
{ui}
19+
</IntlProvider>,
20+
);
21+
};
22+
23+
const mockUser = {
24+
uri: "http://onto.fel.cvut.cz/ontologies/record-manager/Admin-Administratorowitch",
25+
firstName: "Test1",
26+
lastName: "Man",
27+
username: "testman1",
28+
emailAddress: "[email protected]",
29+
institution: {
30+
uri: "http://test.io",
31+
key: "823372507340798303",
32+
name: "Test Institution",
33+
emailAddress: "[email protected]",
34+
},
35+
types: [
36+
"http://onto.fel.cvut.cz/ontologies/record-manager/administrator",
37+
"http://onto.fel.cvut.cz/ontologies/record-manager/doctor",
38+
],
39+
};
40+
41+
describe("UserRow", () => {
42+
const renderComponent = (user = mockUser, overrides = {}) => {
43+
return renderWithIntl(<UserRow user={user} onEdit={vi.fn()} onDelete={vi.fn()} {...overrides} />);
3344
};
3445

35-
it("renders one row of table with 5 columns and 2 buttons and 1 link button", function () {
36-
const tree = TestUtils.renderIntoDocument(
37-
<IntlProvider locale="en" {...intlData}>
38-
<table>
39-
<tbody>
40-
<UserRow user={user} onEdit={onEdit} onDelete={onDelete} deletionLoading={deletionLoading} />
41-
</tbody>
42-
</table>
43-
</IntlProvider>,
44-
);
45-
const td = TestUtils.scryRenderedDOMComponentsWithTag(tree, "td");
46-
expect(td.length).toEqual(5);
47-
const buttons = TestUtils.scryRenderedDOMComponentsWithTag(tree, "Button");
48-
expect(buttons.length).toEqual(3);
46+
beforeEach(() => {
47+
vi.clearAllMocks();
48+
});
49+
50+
it("renders user full name as a link button with correct tooltip", () => {
51+
const { getByRole } = renderComponent();
52+
const fullName = `${mockUser.firstName} ${mockUser.lastName}`;
53+
const nameButton = getByRole("button", { name: new RegExp(fullName, "i") });
54+
expect(nameButton).toBeInTheDocument();
55+
expect(nameButton).toHaveAttribute("title", "View and edit details of this user");
56+
});
57+
58+
it("renders username correctly", () => {
59+
renderComponent();
60+
expect(screen.getByText(mockUser.username)).toBeInTheDocument();
61+
});
62+
63+
it("renders institution name when present", () => {
64+
renderComponent();
65+
expect(screen.getByText(mockUser.institution.name)).toBeInTheDocument();
66+
});
67+
68+
it("renders email address correctly", () => {
69+
renderComponent();
70+
expect(screen.getByText(mockUser.emailAddress)).toBeInTheDocument();
71+
});
72+
73+
it("renders Open button with correct text and tooltip", () => {
74+
const { getByRole } = renderComponent();
75+
const openButton = getByRole("button", { name: /Open/i });
76+
expect(openButton).toBeInTheDocument();
77+
expect(openButton).toHaveAttribute("title", "View and edit details of this user");
78+
});
79+
80+
it("renders Delete button with correct text and tooltip when not using OIDC", () => {
81+
const { getByRole } = renderComponent();
82+
const deleteButton = getByRole("button", { name: /Delete/i });
83+
expect(deleteButton).toBeInTheDocument();
84+
expect(deleteButton).toHaveAttribute("title", "Delete this user");
85+
});
86+
87+
it("calls onEdit when name link button is clicked", () => {
88+
const onEdit = vi.fn();
89+
const fullName = `${mockUser.firstName} ${mockUser.lastName}`;
90+
const { getByRole } = renderComponent(mockUser, { onEdit });
91+
const nameButton = getByRole("button", { name: new RegExp(fullName, "i") });
92+
fireEvent.click(nameButton);
93+
expect(onEdit).toHaveBeenCalledTimes(1);
94+
expect(onEdit).toHaveBeenCalledWith(mockUser);
95+
});
96+
97+
it("calls onEdit when Open button is clicked", () => {
98+
const onEdit = vi.fn();
99+
const { getByRole } = renderComponent(mockUser, { onEdit });
100+
const openButton = getByRole("button", { name: /Open/i });
101+
fireEvent.click(openButton);
102+
expect(onEdit).toHaveBeenCalledTimes(1);
103+
expect(onEdit).toHaveBeenCalledWith(mockUser);
49104
});
50105

51-
it('renders "Open" button and click on it', function () {
52-
const tree = TestUtils.renderIntoDocument(
53-
<IntlProvider locale="en" {...intlData}>
54-
<table>
55-
<tbody>
56-
<UserRow user={user} onEdit={onEdit} onDelete={onDelete} deletionLoading={deletionLoading} />
57-
</tbody>
58-
</table>
59-
</IntlProvider>,
60-
);
61-
const buttons = TestUtils.scryRenderedDOMComponentsWithTag(tree, "Button");
62-
expect(buttons.length).toEqual(3);
63-
64-
TestUtils.Simulate.click(buttons[0]); // Open User
65-
expect(onEdit).toHaveBeenCalled();
106+
it("calls onDelete when Delete button is clicked", () => {
107+
const onDelete = vi.fn();
108+
const { getByRole } = renderComponent(mockUser, { onDelete });
109+
const deleteButton = getByRole("button", { name: /Delete/i });
110+
fireEvent.click(deleteButton);
111+
expect(onDelete).toHaveBeenCalledTimes(1);
112+
expect(onDelete).toHaveBeenCalledWith(mockUser);
66113
});
67114

68-
it("renders name with link and click on it", function () {
69-
const tree = TestUtils.renderIntoDocument(
70-
<IntlProvider locale="en" {...intlData}>
71-
<table>
72-
<tbody>
73-
<UserRow user={user} onEdit={onEdit} onDelete={onDelete} deletionLoading={deletionLoading} />
74-
</tbody>
75-
</table>
76-
</IntlProvider>,
77-
);
78-
79-
const buttons = TestUtils.scryRenderedDOMComponentsWithClass(tree, "btn-link");
80-
expect(buttons.length).toBe(1);
81-
82-
TestUtils.Simulate.click(buttons[0]);
83-
expect(onEdit).toHaveBeenCalled();
115+
it("does not render institution name when user has no institution", () => {
116+
const userWithoutInstitution = { ...mockUser, institution: undefined };
117+
renderComponent(userWithoutInstitution);
118+
expect(screen.queryByText(mockUser.institution.name)).not.toBeInTheDocument();
84119
});
85120

86-
it('renders "Delete" button and click on it', function () {
87-
const tree = TestUtils.renderIntoDocument(
88-
<IntlProvider locale="en" {...intlData}>
89-
<table>
90-
<tbody>
91-
<UserRow user={user} onEdit={onEdit} onDelete={onDelete} deletionLoading={deletionLoading} />
92-
</tbody>
93-
</table>
94-
</IntlProvider>,
95-
);
96-
const buttons = TestUtils.scryRenderedDOMComponentsWithTag(tree, "Button");
97-
expect(buttons.length).toEqual(3);
98-
99-
TestUtils.Simulate.click(buttons[2]); // Delete User
100-
expect(onDelete).toHaveBeenCalled();
121+
it("hides Delete button when using OIDC auth", () => {
122+
vi.mocked(isUsingOidcAuth).mockReturnValue(true);
123+
renderComponent();
124+
expect(screen.queryByRole("button", { name: /Delete/i })).not.toBeInTheDocument();
101125
});
102126
});

0 commit comments

Comments
 (0)