@openneuro/app 4.35.0 → 4.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/client.jsx +1 -0
- package/src/scripts/components/button/button.scss +14 -0
- package/src/scripts/components/page/page.scss +2 -70
- package/src/scripts/components/search-page/SearchResultItem.tsx +3 -1
- package/src/scripts/components/search-page/search-page.scss +1 -13
- package/src/scripts/config.ts +6 -0
- package/src/scripts/dataset/files/__tests__/__snapshots__/file.spec.jsx.snap +2 -2
- package/src/scripts/dataset/files/file.tsx +2 -2
- package/src/scripts/dataset/mutations/__tests__/update-file.spec.tsx +126 -0
- package/src/scripts/dataset/mutations/update-file.jsx +20 -5
- package/src/scripts/dataset/routes/snapshot.tsx +1 -1
- package/src/scripts/errors/errorRoute.tsx +2 -0
- package/src/scripts/pages/admin/__tests__/users.spec.tsx +51 -18
- package/src/scripts/pages/admin/admin.jsx +2 -2
- package/src/scripts/pages/admin/user-fragment.ts +10 -3
- package/src/scripts/pages/admin/user-summary.tsx +100 -0
- package/src/scripts/pages/admin/user-tools.tsx +81 -58
- package/src/scripts/pages/admin/users.module.scss +277 -0
- package/src/scripts/pages/admin/users.tsx +351 -152
- package/src/scripts/queries/user.ts +120 -3
- package/src/scripts/queries/users.ts +247 -0
- package/src/scripts/routes.tsx +7 -15
- package/src/scripts/types/user-types.ts +12 -13
- package/src/scripts/uploader/file-select.tsx +42 -57
- package/src/scripts/uploader/upload-select.jsx +1 -1
- package/src/scripts/users/__tests__/dataset-card.spec.tsx +127 -0
- package/src/scripts/users/__tests__/user-account-view.spec.tsx +150 -67
- package/src/scripts/users/__tests__/user-card.spec.tsx +6 -17
- package/src/scripts/users/__tests__/user-query.spec.tsx +133 -38
- package/src/scripts/users/__tests__/user-routes.spec.tsx +156 -27
- package/src/scripts/users/__tests__/user-tabs.spec.tsx +7 -7
- package/src/scripts/users/components/edit-list.tsx +26 -5
- package/src/scripts/users/components/edit-string.tsx +40 -13
- package/src/scripts/users/components/editable-content.tsx +10 -3
- package/src/scripts/users/components/user-dataset-filters.tsx +205 -121
- package/src/scripts/users/dataset-card.tsx +3 -2
- package/src/scripts/users/github-auth-button.tsx +98 -0
- package/src/scripts/users/scss/datasetcard.module.scss +65 -12
- package/src/scripts/users/scss/useraccountview.module.scss +1 -1
- package/src/scripts/users/user-account-view.tsx +43 -34
- package/src/scripts/users/user-card.tsx +23 -22
- package/src/scripts/users/user-container.tsx +9 -5
- package/src/scripts/users/user-datasets-view.tsx +350 -40
- package/src/scripts/users/user-menu.tsx +4 -9
- package/src/scripts/users/user-notifications-view.tsx +9 -7
- package/src/scripts/users/user-query.tsx +3 -6
- package/src/scripts/users/user-routes.tsx +11 -5
- package/src/scripts/users/user-tabs.tsx +4 -2
- package/src/scripts/users/__tests__/datasest-card.spec.tsx +0 -201
- package/src/scripts/users/fragments/query.js +0 -42
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { vi } from "vitest"
|
|
2
1
|
import React from "react"
|
|
3
2
|
import { MockedProvider } from "@apollo/client/testing"
|
|
4
3
|
import {
|
|
@@ -11,6 +10,7 @@ import {
|
|
|
11
10
|
import { UserAccountView } from "../user-account-view"
|
|
12
11
|
import type { User } from "../../types/user-types"
|
|
13
12
|
import * as userQueries from "../../queries/user"
|
|
13
|
+
import { BrowserRouter } from "react-router-dom"
|
|
14
14
|
|
|
15
15
|
const baseUser: User = {
|
|
16
16
|
id: "1",
|
|
@@ -22,76 +22,93 @@ const baseUser: User = {
|
|
|
22
22
|
avatar: "https://dummyimage.com/200x200/000/fff",
|
|
23
23
|
orcid: "0000-0000-0000-0000",
|
|
24
24
|
links: [],
|
|
25
|
+
admin: false,
|
|
26
|
+
provider: "orcid",
|
|
27
|
+
created: new Date("2025-05-20T14:50:32.424Z").toISOString(),
|
|
28
|
+
lastSeen: new Date("2025-05-20T14:50:32.424Z").toISOString(),
|
|
29
|
+
blocked: false,
|
|
30
|
+
githubSynced: null,
|
|
25
31
|
}
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
useUser: () => ({
|
|
32
|
-
user: baseUser,
|
|
33
|
-
loading: false,
|
|
34
|
-
error: undefined,
|
|
35
|
-
}),
|
|
36
|
-
}
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
const mocks = [
|
|
40
|
-
{
|
|
41
|
-
request: {
|
|
42
|
-
query: userQueries.GET_USER,
|
|
43
|
-
variables: { id: baseUser.orcid },
|
|
44
|
-
},
|
|
45
|
-
result: {
|
|
46
|
-
data: {
|
|
47
|
-
user: baseUser,
|
|
48
|
-
},
|
|
49
|
-
},
|
|
33
|
+
const userMock = {
|
|
34
|
+
request: {
|
|
35
|
+
query: userQueries.GET_USER,
|
|
36
|
+
variables: { id: baseUser.orcid },
|
|
50
37
|
},
|
|
51
|
-
{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
variables: {
|
|
55
|
-
id: baseUser.orcid,
|
|
56
|
-
location: "Marin, CA",
|
|
57
|
-
links: ["https://newlink.com"],
|
|
58
|
-
institution: "New University",
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
result: {
|
|
62
|
-
data: {
|
|
63
|
-
updateUser: {
|
|
64
|
-
id: baseUser.orcid,
|
|
65
|
-
location: "Marin, CA",
|
|
66
|
-
links: ["https://newlink.com"],
|
|
67
|
-
institution: "New University",
|
|
68
|
-
},
|
|
69
|
-
},
|
|
38
|
+
result: {
|
|
39
|
+
data: {
|
|
40
|
+
user: baseUser,
|
|
70
41
|
},
|
|
71
42
|
},
|
|
72
|
-
|
|
43
|
+
}
|
|
73
44
|
|
|
74
45
|
describe("<UserAccountView />", () => {
|
|
75
|
-
it("should render the user details correctly", () => {
|
|
46
|
+
it("should render the user details correctly", async () => {
|
|
47
|
+
const mocks = [
|
|
48
|
+
userMock,
|
|
49
|
+
{
|
|
50
|
+
request: {
|
|
51
|
+
query: userQueries.UPDATE_USER,
|
|
52
|
+
variables: {
|
|
53
|
+
id: baseUser.orcid,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
result: {
|
|
57
|
+
data: {
|
|
58
|
+
updateUser: {
|
|
59
|
+
id: baseUser.orcid,
|
|
60
|
+
location: "Marin, CA",
|
|
61
|
+
links: ["https://newlink.com"],
|
|
62
|
+
institution: "New University",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
]
|
|
76
68
|
render(
|
|
77
|
-
<
|
|
78
|
-
<
|
|
79
|
-
|
|
69
|
+
<BrowserRouter>
|
|
70
|
+
<MockedProvider mocks={mocks} addTypename={false}>
|
|
71
|
+
<UserAccountView orcidUser={baseUser} />
|
|
72
|
+
</MockedProvider>
|
|
73
|
+
</BrowserRouter>,
|
|
80
74
|
)
|
|
81
|
-
expect(screen.getByText("Name:")).toBeInTheDocument()
|
|
82
75
|
expect(screen.getByText("John Doe")).toBeInTheDocument()
|
|
76
|
+
expect(screen.getByText("Name:")).toBeInTheDocument()
|
|
83
77
|
expect(screen.getByText("Email:")).toBeInTheDocument()
|
|
84
78
|
expect(screen.getByText("john.doe@example.com")).toBeInTheDocument()
|
|
85
79
|
expect(screen.getByText("ORCID:")).toBeInTheDocument()
|
|
86
80
|
expect(screen.getByText("0000-0000-0000-0000")).toBeInTheDocument()
|
|
87
|
-
expect(screen.getByText("
|
|
81
|
+
expect(screen.getByText("Link user data from GitHub")).toBeInTheDocument()
|
|
88
82
|
})
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
it("should render location with EditableContent and update", async () => {
|
|
84
|
+
const mocks = [
|
|
85
|
+
userMock,
|
|
86
|
+
{
|
|
87
|
+
request: {
|
|
88
|
+
query: userQueries.UPDATE_USER,
|
|
89
|
+
variables: {
|
|
90
|
+
id: baseUser.orcid,
|
|
91
|
+
location: "Marin, CA",
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
result: {
|
|
95
|
+
data: {
|
|
96
|
+
updateUser: {
|
|
97
|
+
id: baseUser.orcid,
|
|
98
|
+
location: "Marin, CA",
|
|
99
|
+
links: ["https://newlink.com"],
|
|
100
|
+
institution: "New University",
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
]
|
|
91
106
|
render(
|
|
92
|
-
<
|
|
93
|
-
<
|
|
94
|
-
|
|
107
|
+
<BrowserRouter>
|
|
108
|
+
<MockedProvider mocks={mocks} addTypename={false}>
|
|
109
|
+
<UserAccountView orcidUser={baseUser} />
|
|
110
|
+
</MockedProvider>
|
|
111
|
+
</BrowserRouter>,
|
|
95
112
|
)
|
|
96
113
|
const locationSection = within(screen.getByTestId("location-section"))
|
|
97
114
|
expect(screen.getByText("Location")).toBeInTheDocument()
|
|
@@ -106,11 +123,32 @@ describe("<UserAccountView />", () => {
|
|
|
106
123
|
})
|
|
107
124
|
})
|
|
108
125
|
|
|
109
|
-
it("should render institution with EditableContent", async () => {
|
|
126
|
+
it("should render institution with EditableContent and update", async () => {
|
|
127
|
+
const mocks = [userMock, {
|
|
128
|
+
request: {
|
|
129
|
+
query: userQueries.UPDATE_USER,
|
|
130
|
+
variables: {
|
|
131
|
+
id: baseUser.orcid,
|
|
132
|
+
institution: "New University",
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
result: {
|
|
136
|
+
data: {
|
|
137
|
+
updateUser: {
|
|
138
|
+
id: baseUser.orcid,
|
|
139
|
+
location: "Marin, CA",
|
|
140
|
+
links: ["https://newlink.com"],
|
|
141
|
+
institution: "New University",
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
}]
|
|
110
146
|
render(
|
|
111
|
-
<
|
|
112
|
-
<
|
|
113
|
-
|
|
147
|
+
<BrowserRouter>
|
|
148
|
+
<MockedProvider mocks={mocks} addTypename={false}>
|
|
149
|
+
<UserAccountView orcidUser={baseUser} />
|
|
150
|
+
</MockedProvider>,
|
|
151
|
+
</BrowserRouter>,
|
|
114
152
|
)
|
|
115
153
|
const institutionSection = within(screen.getByTestId("institution-section"))
|
|
116
154
|
expect(screen.getByText("Institution")).toBeInTheDocument()
|
|
@@ -125,11 +163,32 @@ describe("<UserAccountView />", () => {
|
|
|
125
163
|
})
|
|
126
164
|
})
|
|
127
165
|
|
|
128
|
-
it("should render links with EditableContent and
|
|
166
|
+
it("should render links with EditableContent and handle valid URL input", async () => {
|
|
167
|
+
const mocks = [userMock, {
|
|
168
|
+
request: {
|
|
169
|
+
query: userQueries.UPDATE_USER,
|
|
170
|
+
variables: {
|
|
171
|
+
id: baseUser.orcid,
|
|
172
|
+
links: ["https://newlink.com"],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
result: {
|
|
176
|
+
data: {
|
|
177
|
+
updateUser: {
|
|
178
|
+
id: baseUser.orcid,
|
|
179
|
+
location: "Marin, CA",
|
|
180
|
+
links: ["https://newlink.com"],
|
|
181
|
+
institution: "New University",
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
}]
|
|
129
186
|
render(
|
|
130
|
-
<
|
|
131
|
-
<
|
|
132
|
-
|
|
187
|
+
<BrowserRouter>
|
|
188
|
+
<MockedProvider mocks={mocks} addTypename={false}>
|
|
189
|
+
<UserAccountView orcidUser={baseUser} />
|
|
190
|
+
</MockedProvider>,
|
|
191
|
+
</BrowserRouter>,
|
|
133
192
|
)
|
|
134
193
|
const linksSection = within(screen.getByTestId("links-section"))
|
|
135
194
|
expect(screen.getByText("Links")).toBeInTheDocument()
|
|
@@ -145,11 +204,33 @@ describe("<UserAccountView />", () => {
|
|
|
145
204
|
})
|
|
146
205
|
|
|
147
206
|
it("should show an error message when invalid URL is entered in links section", async () => {
|
|
207
|
+
const mocks = [{
|
|
208
|
+
request: {
|
|
209
|
+
query: userQueries.UPDATE_USER,
|
|
210
|
+
variables: {
|
|
211
|
+
id: baseUser.orcid,
|
|
212
|
+
links: ["https://newlink.com"],
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
result: {
|
|
216
|
+
data: {
|
|
217
|
+
updateUser: {
|
|
218
|
+
id: baseUser.orcid,
|
|
219
|
+
location: "Marin, CA",
|
|
220
|
+
links: ["https://newlink.com"],
|
|
221
|
+
institution: "New University",
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
}]
|
|
148
226
|
render(
|
|
149
|
-
<
|
|
150
|
-
<
|
|
151
|
-
|
|
227
|
+
<BrowserRouter>
|
|
228
|
+
<MockedProvider mocks={mocks} addTypename={false}>
|
|
229
|
+
<UserAccountView orcidUser={baseUser} />
|
|
230
|
+
</MockedProvider>,
|
|
231
|
+
</BrowserRouter>,
|
|
152
232
|
)
|
|
233
|
+
|
|
153
234
|
const linksSection = within(screen.getByTestId("links-section"))
|
|
154
235
|
const editButton = linksSection.getByText("Edit")
|
|
155
236
|
fireEvent.click(editButton)
|
|
@@ -159,7 +240,9 @@ describe("<UserAccountView />", () => {
|
|
|
159
240
|
fireEvent.click(saveButton)
|
|
160
241
|
await waitFor(() => {
|
|
161
242
|
expect(
|
|
162
|
-
linksSection.getByText(
|
|
243
|
+
linksSection.getByText(
|
|
244
|
+
"Invalid URL format. Please start with http:// or https://",
|
|
245
|
+
),
|
|
163
246
|
).toBeInTheDocument()
|
|
164
247
|
})
|
|
165
248
|
})
|
|
@@ -1,18 +1,7 @@
|
|
|
1
1
|
import React from "react"
|
|
2
2
|
import { render, screen } from "@testing-library/react"
|
|
3
3
|
import { UserCard } from "../user-card"
|
|
4
|
-
|
|
5
|
-
interface User {
|
|
6
|
-
id: string
|
|
7
|
-
name: string
|
|
8
|
-
location: string
|
|
9
|
-
github?: string
|
|
10
|
-
institution: string
|
|
11
|
-
email: string
|
|
12
|
-
avatar: string
|
|
13
|
-
orcid: string
|
|
14
|
-
links: string[]
|
|
15
|
-
}
|
|
4
|
+
import type { User } from "../../types/user-types"
|
|
16
5
|
|
|
17
6
|
describe("UserCard Component", () => {
|
|
18
7
|
const baseUser: User = {
|
|
@@ -28,7 +17,7 @@ describe("UserCard Component", () => {
|
|
|
28
17
|
}
|
|
29
18
|
|
|
30
19
|
it("renders all user details when all data is provided", () => {
|
|
31
|
-
render(<UserCard
|
|
20
|
+
render(<UserCard orcidUser={baseUser} />)
|
|
32
21
|
|
|
33
22
|
const orcidLink = screen.getByRole("link", {
|
|
34
23
|
name: "ORCID profile of John Doe",
|
|
@@ -67,7 +56,7 @@ describe("UserCard Component", () => {
|
|
|
67
56
|
institution: "",
|
|
68
57
|
}
|
|
69
58
|
|
|
70
|
-
render(<UserCard
|
|
59
|
+
render(<UserCard orcidUser={minimalUser} />)
|
|
71
60
|
|
|
72
61
|
const orcidLink = screen.getByRole("link", {
|
|
73
62
|
name: "ORCID profile of Jane Doe",
|
|
@@ -91,13 +80,13 @@ describe("UserCard Component", () => {
|
|
|
91
80
|
name: "John Smith",
|
|
92
81
|
email: "johnsmith@example.com",
|
|
93
82
|
orcid: "0000-0003-4567-8901",
|
|
94
|
-
links: [],
|
|
83
|
+
links: [],
|
|
95
84
|
avatar: "https://example.com/avatar.jpg",
|
|
96
85
|
location: "New York, NY",
|
|
97
86
|
institution: "NYU",
|
|
98
87
|
}
|
|
99
88
|
|
|
100
|
-
render(<UserCard
|
|
89
|
+
render(<UserCard orcidUser={userWithEmptyLinks} />)
|
|
101
90
|
|
|
102
91
|
expect(screen.queryByRole("link", { name: "https://example.com" })).not
|
|
103
92
|
.toBeInTheDocument()
|
|
@@ -117,7 +106,7 @@ describe("UserCard Component", () => {
|
|
|
117
106
|
institution: "",
|
|
118
107
|
}
|
|
119
108
|
|
|
120
|
-
render(<UserCard
|
|
109
|
+
render(<UserCard orcidUser={userWithoutLocationAndInstitution} />)
|
|
121
110
|
|
|
122
111
|
const orcidLink = screen.getByRole("link", {
|
|
123
112
|
name: "ORCID profile of Emily Doe",
|
|
@@ -1,44 +1,137 @@
|
|
|
1
|
+
import { vi } from "vitest"
|
|
1
2
|
import React from "react"
|
|
2
|
-
import { render, screen
|
|
3
|
+
import { render, screen } from "@testing-library/react"
|
|
3
4
|
import { MockedProvider } from "@apollo/client/testing"
|
|
4
5
|
import { MemoryRouter, Route, Routes } from "react-router-dom"
|
|
6
|
+
|
|
7
|
+
// Component
|
|
5
8
|
import { UserQuery } from "../user-query"
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
9
|
+
import { isValidOrcid } from "../../utils/validationUtils"
|
|
10
|
+
import { getProfile } from "../../authentication/profile"
|
|
11
|
+
import { isAdmin } from "../../authentication/admin-user"
|
|
12
|
+
import { useCookies } from "react-cookie"
|
|
13
|
+
import { useUser } from "../../queries/user"
|
|
14
|
+
import type { User } from "../../types/user-types"
|
|
15
|
+
import type { UserRoutesProps } from "../../types/user-types"
|
|
8
16
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
17
|
+
// --- generate a random valid ORCID - maybe unnecessary ---
|
|
18
|
+
const generateRandomValidOrcid = (): string => {
|
|
19
|
+
const segments = Array.from(
|
|
20
|
+
{ length: 4 },
|
|
21
|
+
() => Math.floor(1000 + Math.random() * 9000).toString(),
|
|
22
|
+
)
|
|
23
|
+
return segments.join("-")
|
|
24
|
+
}
|
|
13
25
|
|
|
14
|
-
|
|
26
|
+
vi.mock("./user-routes", () => ({
|
|
27
|
+
UserRoutes: vi.fn((props: UserRoutesProps) => (
|
|
28
|
+
<div data-testid="mock-user-routes">
|
|
29
|
+
Mocked UserRoutes Component
|
|
30
|
+
<p>User ORCID: {props.orcidUser?.orcid}</p>
|
|
31
|
+
<p>Has Edit: {props.hasEdit ? "true" : "false"}</p>
|
|
32
|
+
<p>Is User: {props.isUser ? "true" : "false"}</p>
|
|
33
|
+
</div>
|
|
34
|
+
)),
|
|
35
|
+
}))
|
|
15
36
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
vi.mock("../../utils/validationUtils", () => ({
|
|
38
|
+
isValidOrcid: vi.fn<typeof isValidOrcid>(),
|
|
39
|
+
}))
|
|
40
|
+
|
|
41
|
+
vi.mock("react-cookie", () => ({
|
|
42
|
+
useCookies: vi.fn<typeof useCookies>(),
|
|
43
|
+
}))
|
|
44
|
+
|
|
45
|
+
vi.mock("../../authentication/profile", () => ({
|
|
46
|
+
getProfile: vi.fn<typeof getProfile>(),
|
|
47
|
+
}))
|
|
48
|
+
|
|
49
|
+
vi.mock("../../authentication/admin-user", () => ({
|
|
50
|
+
isAdmin: vi.fn<typeof isAdmin>(),
|
|
51
|
+
}))
|
|
52
|
+
|
|
53
|
+
vi.mock("../../queries/user", () => ({
|
|
54
|
+
useUser: vi.fn<typeof useUser>(),
|
|
55
|
+
ADVANCED_SEARCH_DATASETS_QUERY: {
|
|
56
|
+
kind: "Document",
|
|
57
|
+
definitions: [
|
|
58
|
+
{
|
|
59
|
+
kind: "OperationDefinition",
|
|
60
|
+
operation: "query",
|
|
61
|
+
name: { kind: "Name", value: "AdvancedSearchDatasets" },
|
|
62
|
+
variableDefinitions: [],
|
|
63
|
+
selectionSet: { kind: "SelectionSet", selections: [] },
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
loc: {
|
|
67
|
+
start: 0,
|
|
68
|
+
end: 0,
|
|
69
|
+
source: {
|
|
70
|
+
body: "",
|
|
71
|
+
name: "Mocked",
|
|
72
|
+
locationOffset: { line: 1, column: 1 },
|
|
30
73
|
},
|
|
31
74
|
},
|
|
32
75
|
},
|
|
76
|
+
}))
|
|
77
|
+
|
|
78
|
+
export interface OpenNeuroTokenProfile {
|
|
79
|
+
sub: string
|
|
80
|
+
admin: boolean
|
|
81
|
+
iat: number
|
|
82
|
+
exp: number
|
|
83
|
+
scopes?: string[]
|
|
33
84
|
}
|
|
34
85
|
|
|
35
|
-
|
|
86
|
+
describe("UserQuery component - Dynamic ORCID Loading", () => {
|
|
87
|
+
const mockedIsValidOrcid = vi.mocked(isValidOrcid)
|
|
88
|
+
const mockedGetProfile = vi.mocked(getProfile)
|
|
89
|
+
const mockedIsAdmin = vi.mocked(isAdmin)
|
|
90
|
+
const mockedUseCookies = vi.mocked(useCookies)
|
|
91
|
+
const mockedUseUser = vi.mocked(useUser)
|
|
92
|
+
|
|
93
|
+
let testOrcid: string
|
|
36
94
|
|
|
37
|
-
|
|
38
|
-
|
|
95
|
+
beforeEach(() => {
|
|
96
|
+
vi.clearAllMocks()
|
|
97
|
+
vi.resetAllMocks()
|
|
98
|
+
mockedIsValidOrcid.mockReturnValue(true)
|
|
99
|
+
|
|
100
|
+
mockedGetProfile.mockReturnValue({
|
|
101
|
+
sub: "11111",
|
|
102
|
+
admin: false,
|
|
103
|
+
iat: Date.now(),
|
|
104
|
+
exp: Date.now() + (1000 * 60 * 60),
|
|
105
|
+
scopes: [],
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
mockedIsAdmin.mockReturnValue(false)
|
|
109
|
+
mockedUseCookies.mockReturnValue([{}, vi.fn(), vi.fn()])
|
|
110
|
+
testOrcid = generateRandomValidOrcid()
|
|
111
|
+
|
|
112
|
+
mockedUseUser.mockImplementation((orcidParam: string) => {
|
|
113
|
+
const dynamicUser: User = {
|
|
114
|
+
id: orcidParam,
|
|
115
|
+
name: `Mock User for ${orcidParam}`,
|
|
116
|
+
location: "Dynamic Location",
|
|
117
|
+
institution: "Dynamic Institution",
|
|
118
|
+
email: `${orcidParam}@example.com`,
|
|
119
|
+
avatar: "https://dummyimage.com/200x200/000/fff",
|
|
120
|
+
orcid: orcidParam,
|
|
121
|
+
links: [],
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
user: dynamicUser,
|
|
125
|
+
loading: false,
|
|
126
|
+
error: undefined,
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it("loads the page and displays user data for a valid ORCID from the URL", async () => {
|
|
39
132
|
render(
|
|
40
|
-
<MockedProvider mocks={
|
|
41
|
-
<MemoryRouter initialEntries={[`/user/${
|
|
133
|
+
<MockedProvider mocks={[]} addTypename={true}>
|
|
134
|
+
<MemoryRouter initialEntries={[`/user/${testOrcid}`]}>
|
|
42
135
|
<Routes>
|
|
43
136
|
<Route path="/user/:orcid" element={<UserQuery />} />
|
|
44
137
|
</Routes>
|
|
@@ -46,26 +139,28 @@ describe("UserQuery component", () => {
|
|
|
46
139
|
</MockedProvider>,
|
|
47
140
|
)
|
|
48
141
|
|
|
49
|
-
|
|
50
|
-
expect(screen.queryByText("Loading...")).not.toBeInTheDocument()
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
expect(screen.getByText(validOrcid)).toBeInTheDocument()
|
|
142
|
+
expect(screen.getByText(`${testOrcid}`)).toBeInTheDocument()
|
|
54
143
|
})
|
|
55
144
|
|
|
56
|
-
it("
|
|
145
|
+
it("displays 404 if the ORCID in the URL is invalid", async () => {
|
|
146
|
+
const invalidOrcid = "invalid-orcid-string"
|
|
147
|
+
|
|
148
|
+
mockedUseUser.mockReturnValue({
|
|
149
|
+
user: undefined,
|
|
150
|
+
loading: false,
|
|
151
|
+
error: undefined,
|
|
152
|
+
})
|
|
57
153
|
render(
|
|
58
154
|
<MockedProvider mocks={[]} addTypename={true}>
|
|
59
|
-
<MemoryRouter initialEntries={[`/user
|
|
155
|
+
<MemoryRouter initialEntries={[`/user/${invalidOrcid}`]}>
|
|
60
156
|
<Routes>
|
|
61
157
|
<Route path="/user/:orcid" element={<UserQuery />} />
|
|
62
158
|
</Routes>
|
|
63
159
|
</MemoryRouter>
|
|
64
160
|
</MockedProvider>,
|
|
65
161
|
)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
expect(screen.getByText(/404/i)).toBeInTheDocument()
|
|
162
|
+
expect(
|
|
163
|
+
screen.getByText(/404: The page you are looking for does not exist./i),
|
|
164
|
+
).toBeInTheDocument()
|
|
70
165
|
})
|
|
71
166
|
})
|