@openneuro/app 4.34.2 → 4.35.0-alpha.1

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.
Files changed (50) hide show
  1. package/package.json +4 -4
  2. package/src/scripts/authentication/profile.ts +3 -5
  3. package/src/scripts/common/containers/header.tsx +1 -2
  4. package/src/scripts/common/partials/freshdesk-widget.jsx +5 -1
  5. package/src/scripts/components/header/Header.tsx +4 -10
  6. package/src/scripts/components/header/LandingExpandedHeader.tsx +11 -9
  7. package/src/scripts/components/header/header.scss +4 -2
  8. package/src/scripts/components/logo/Logo.tsx +1 -1
  9. package/src/scripts/components/modal/UserLoginModal.tsx +12 -11
  10. package/src/scripts/components/modal/__tests__/UserLoginModal.spec.tsx +1 -1
  11. package/src/scripts/components/page/Page.tsx +1 -2
  12. package/src/scripts/components/scss/upload-modal.scss +6 -0
  13. package/src/scripts/components/search-page/SearchResultItem.tsx +14 -13
  14. package/src/scripts/components/search-page/SearchResultsList.tsx +0 -19
  15. package/src/scripts/dataset/draft-container.tsx +0 -1
  16. package/src/scripts/dataset/fragments/__tests__/dataset-history.spec.tsx +155 -0
  17. package/src/scripts/dataset/fragments/dataset-history.jsx +6 -7
  18. package/src/scripts/dataset/snapshot-container.tsx +13 -11
  19. package/src/scripts/errors/errorRoute.tsx +2 -0
  20. package/src/scripts/errors/freshdesk-widget.jsx +5 -1
  21. package/src/scripts/errors/orcid/email-warning.tsx +21 -0
  22. package/src/scripts/index.tsx +15 -2
  23. package/src/scripts/pages/__tests__/orcid-link.spec.tsx +13 -0
  24. package/src/scripts/pages/orcid-link.tsx +60 -0
  25. package/src/scripts/queries/user.ts +71 -0
  26. package/src/scripts/routes.tsx +2 -0
  27. package/src/scripts/scss/variables.scss +13 -9
  28. package/src/scripts/search/search-container.tsx +2 -12
  29. package/src/scripts/search/search-params-ctx.tsx +6 -3
  30. package/src/scripts/search/use-search-results.tsx +1 -1
  31. package/src/scripts/types/user-types.ts +2 -0
  32. package/src/scripts/uploader/file-select.tsx +3 -1
  33. package/src/scripts/uploader/upload-select.jsx +40 -24
  34. package/src/scripts/users/__tests__/user-account-view.spec.tsx +36 -22
  35. package/src/scripts/users/__tests__/user-query.spec.tsx +3 -3
  36. package/src/scripts/users/__tests__/user-routes.spec.tsx +28 -11
  37. package/src/scripts/users/__tests__/user-tabs.spec.tsx +12 -9
  38. package/src/scripts/users/scss/user-menu.scss +133 -0
  39. package/src/scripts/users/scss/usernotifications.module.scss +1 -1
  40. package/src/scripts/users/user-account-view.tsx +35 -21
  41. package/src/scripts/users/user-container.tsx +2 -1
  42. package/src/scripts/users/user-menu.tsx +114 -0
  43. package/src/scripts/users/user-notification-accordion.tsx +2 -2
  44. package/src/scripts/users/user-query.tsx +6 -36
  45. package/src/scripts/users/user-routes.tsx +7 -5
  46. package/src/scripts/users/user-tabs.tsx +4 -3
  47. package/src/scripts/validation/__tests__/__snapshots__/validation-issues.spec.tsx.snap +10 -1
  48. package/src/scripts/validation/validation-issues.tsx +7 -3
  49. package/src/scripts/components/user/UserMenu.tsx +0 -72
  50. package/src/scripts/components/user/user-menu.scss +0 -88
@@ -80,7 +80,7 @@ export const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
80
80
  dataset.snapshots[dataset.snapshots.length - 1].hexsha
81
81
  const modality: string = summary?.modalities[0] || ""
82
82
  const hasDerivatives = dataset?.derivatives.length > 0
83
-
83
+ const isAnonymousReviewer = profile?.scopes?.includes("dataset:reviewer")
84
84
  return (
85
85
  <>
86
86
  <Helmet>
@@ -263,16 +263,18 @@ export const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
263
263
  />
264
264
  </>
265
265
  ))}
266
-
267
- <MetaDataBlock
268
- heading="Uploaded by"
269
- item={
270
- <>
271
- <Username user={dataset.uploader} /> on{" "}
272
- <DateDistance date={dataset.created} />
273
- </>
274
- }
275
- />
266
+ {!isAnonymousReviewer &&
267
+ (
268
+ <MetaDataBlock
269
+ heading="Uploaded by"
270
+ item={
271
+ <>
272
+ <Username user={dataset.uploader} /> on{" "}
273
+ <DateDistance date={dataset.created} />
274
+ </>
275
+ }
276
+ />
277
+ )}
276
278
 
277
279
  {dataset.snapshots.length && (
278
280
  <MetaDataBlock
@@ -4,6 +4,7 @@
4
4
  import React from "react"
5
5
  import { Route, Routes } from "react-router-dom"
6
6
  import OrcidGeneral from "./orcid/general.jsx"
7
+ import { OrcidEmailWarning } from "./orcid/email-warning.js"
7
8
  import FourOFourPage from "./404page.js"
8
9
 
9
10
  function ErrorRoute() {
@@ -12,6 +13,7 @@ function ErrorRoute() {
12
13
  <div className="panel">
13
14
  <Routes>
14
15
  <Route path="orcid" element={<OrcidGeneral />} />
16
+ <Route path="email-warning" element={<OrcidEmailWarning />} />
15
17
  <Route path="*" element={<FourOFourPage />} />
16
18
  </Routes>
17
19
  </div>
@@ -3,6 +3,7 @@ import PropTypes from "prop-types"
3
3
  import { useCookies } from "react-cookie"
4
4
  import { getProfile } from "../authentication/profile"
5
5
  import { config } from "../config"
6
+ import { useUser } from "../queries/user"
6
7
 
7
8
  const buildCustomQuery = (customText, prepopulatedFields) => {
8
9
  const customizerQueries = [
@@ -31,8 +32,11 @@ function FreshdeskWidget({ subject, error, sentryId, description }) {
31
32
  screenshot: "No",
32
33
  captcha: "yes",
33
34
  }
35
+
36
+ const { user } = useUser()
37
+
34
38
  const prepopulatedFields = {
35
- requester: profile && profile.email,
39
+ requester: profile && user?.email,
36
40
  subject,
37
41
  description: joinedDescription,
38
42
  }
@@ -0,0 +1,21 @@
1
+ import React from "react"
2
+
3
+ export const OrcidEmailWarning = () => (
4
+ <div className="panel-heading">
5
+ <h2>No Email Provided</h2>
6
+ <p>
7
+ To make contributions to OpenNeuro, please provide a contact email
8
+ address.
9
+ </p>
10
+ <p>
11
+ Verify an email and make it available either publicly or to trusted
12
+ institutions to make contributions to OpenNeuro. See our{" "}
13
+ <a href="https://docs.openneuro.org/orcid.html#enabling-trusted-access-to-emails">
14
+ ORCID documentation
15
+ </a>{" "}
16
+ for detailed instructions.
17
+ </p>
18
+ </div>
19
+ )
20
+
21
+ export default OrcidEmailWarning
@@ -1,4 +1,4 @@
1
- import React from "react"
1
+ import React, { useEffect } from "react"
2
2
  import Uploader from "./uploader/uploader.jsx"
3
3
  import AppRoutes from "./routes"
4
4
  import HeaderContainer from "./common/containers/header"
@@ -6,11 +6,24 @@ import FooterContainer from "./common/containers/footer"
6
6
  import { SearchParamsProvider } from "./search/search-params-ctx"
7
7
  import { UserModalOpenProvider } from "./utils/user-login-modal-ctx"
8
8
  import { useAnalytics } from "./utils/analytics"
9
-
9
+ import { useLocation, useNavigate } from "react-router-dom"
10
10
  import "../assets/email-header.png"
11
+ import { useUser } from "./queries/user.js"
11
12
 
12
13
  const Index = (): React.ReactElement => {
13
14
  useAnalytics()
15
+ // Redirect authenticated Google users to the migration step if they are in any other route
16
+ const navigate = useNavigate()
17
+ const location = useLocation()
18
+ const { user, loading, error } = useUser()
19
+ useEffect(() => {
20
+ if (
21
+ !loading && !error && location.pathname !== "/orcid-link" &&
22
+ user?.provider === "google"
23
+ ) {
24
+ navigate("/orcid-link")
25
+ }
26
+ }, [location.pathname, user])
14
27
  return (
15
28
  <Uploader>
16
29
  <SearchParamsProvider>
@@ -0,0 +1,13 @@
1
+ import React from "react"
2
+ import { render, screen } from "@testing-library/react"
3
+ import { OrcidLinkPage } from "../orcid-link"
4
+ import { vitest } from "vitest"
5
+
6
+ vitest.mock("../../config")
7
+
8
+ describe("OrcidLinkPage", () => {
9
+ it("renders orcid link button", () => {
10
+ render(<OrcidLinkPage />)
11
+ expect(screen.getByRole("button")).toHaveTextContent("Link ORCID")
12
+ })
13
+ })
@@ -0,0 +1,60 @@
1
+ import React from "react"
2
+ import Helmet from "react-helmet"
3
+ import { frontPage } from "./front-page/front-page-content"
4
+ import loginUrls from "../authentication/loginUrls"
5
+ import { Button } from "../components/button/Button"
6
+ import orcidIcon from "../../assets/orcid_24x24.png"
7
+ import styled from "@emotion/styled"
8
+
9
+ const OrcidLinkPageStyle = styled.div`
10
+ background: white;
11
+
12
+ .container {
13
+ max-width: 60em;
14
+ min-height: calc(100vh - 152px);
15
+ }
16
+ `
17
+
18
+ export function OrcidLinkPage() {
19
+ return (
20
+ <OrcidLinkPageStyle>
21
+ <Helmet>
22
+ <title>
23
+ Link ORCID to your existing account - {frontPage.pageTitle}
24
+ </title>
25
+ <meta
26
+ name="description"
27
+ content="How to link your ORCID account to your Google based OpenNeuro account"
28
+ />
29
+ </Helmet>
30
+ <div className="container">
31
+ <h2>ORCID account migration</h2>
32
+ <p>
33
+ OpenNeuro is moving to ORCID for all accounts. Please link an ORCID to
34
+ your account to continue and use ORCID for future logins. If you have
35
+ used Google login before, any datasets, comments, and permissions you
36
+ have will be merged into the combined OpenNeuro account linked to your
37
+ ORCID iD.
38
+ </p>
39
+ <h3>Why are we making this change?</h3>
40
+ <p>
41
+ ORCID allows richer researcher metadata for contributions and
42
+ optionally sharing contributions to datasets as works on your ORCID
43
+ profile.
44
+ </p>
45
+ <h3>Will Google accounts continue to work?</h3>
46
+ <p>
47
+ To make new contributions you will need link an ORCID but any existing
48
+ contributions will remain available.
49
+ </p>
50
+ <a href={loginUrls.orcid + `?migrate`}>
51
+ <Button
52
+ className="login-button"
53
+ label="Link ORCID"
54
+ imgSrc={orcidIcon}
55
+ />
56
+ </a>
57
+ </div>
58
+ </OrcidLinkPageStyle>
59
+ )
60
+ }
@@ -0,0 +1,71 @@
1
+ import { gql, useQuery } from "@apollo/client"
2
+ import { useCookies } from "react-cookie"
3
+ import { getProfile } from "../authentication/profile"
4
+ import * as Sentry from "@sentry/react"
5
+
6
+ // GraphQL query to fetch user data
7
+ export const GET_USER = gql`
8
+ query User($userId: ID!) {
9
+ user(id: $userId) {
10
+ id
11
+ name
12
+ orcid
13
+ email
14
+ avatar
15
+ location
16
+ institution
17
+ links
18
+ provider
19
+ admin
20
+ created
21
+ lastSeen
22
+ blocked
23
+ }
24
+ }
25
+ `
26
+
27
+ export const UPDATE_USER = gql`
28
+ mutation updateUser(
29
+ $id: ID!
30
+ $location: String
31
+ $links: [String]
32
+ $institution: String
33
+ ) {
34
+ updateUser(
35
+ id: $id
36
+ location: $location
37
+ links: $links
38
+ institution: $institution
39
+ ) {
40
+ id
41
+ location
42
+ links
43
+ institution
44
+ }
45
+ }
46
+ `
47
+
48
+ // Reusable hook to fetch user data
49
+ export const useUser = () => {
50
+ const [cookies] = useCookies()
51
+ const profile = getProfile(cookies)
52
+ const profileSub = profile?.sub
53
+
54
+ const { data: userData, loading: userLoading, error: userError } = useQuery(
55
+ GET_USER,
56
+ {
57
+ variables: { userId: profileSub },
58
+ skip: !profileSub,
59
+ },
60
+ )
61
+
62
+ if (userError) {
63
+ Sentry.captureException(userError)
64
+ }
65
+
66
+ return {
67
+ user: userData?.user,
68
+ loading: userLoading,
69
+ error: userError,
70
+ }
71
+ }
@@ -22,6 +22,7 @@ import { UserQuery } from "./users/user-query"
22
22
  import LoggedIn from "../scripts/authentication/logged-in"
23
23
  import LoggedOut from "../scripts/authentication/logged-out"
24
24
  import FourOThreePage from "./errors/403page"
25
+ import { OrcidLinkPage } from "./pages/orcid-link"
25
26
 
26
27
  const AppRoutes: React.VoidFunctionComponent = () => (
27
28
  <Routes>
@@ -39,6 +40,7 @@ const AppRoutes: React.VoidFunctionComponent = () => (
39
40
  <Route path="/import" element={<ImportDataset />} />
40
41
  <Route path="/metadata" element={<DatasetMetadata />} />
41
42
  <Route path="/public" element={<Navigate to="/search" replace />} />
43
+ <Route path="/orcid-link" element={<OrcidLinkPage />} />
42
44
  <Route
43
45
  path="/user/:orcid/*"
44
46
  element={
@@ -85,6 +85,16 @@ $on-light-orange: rgb(255, 110, 43);
85
85
  $primary: $on-dark-aqua;
86
86
 
87
87
  $chiclet-color: #a2059e;
88
+ //Base unit used for spacing gutters
89
+ $base-unit: 20px;
90
+
91
+ //Screen Sizes
92
+ $screen-sm: 480px;
93
+ $screen-md: 767px;
94
+ $screen-lg: 989px;
95
+
96
+ $border-radius-default: 4px;
97
+
88
98
 
89
99
  /* CSS HEX */
90
100
  :root {
@@ -105,6 +115,9 @@ $chiclet-color: #a2059e;
105
115
  --current-theme-primary-light: #{$on-dark-aqua-light};
106
116
  --current-theme-header: #333;
107
117
  --current-theme-header-dark: #333;
118
+ --font-sans: #{$font-sans};
119
+ --border-radius-default: #{$border-radius-default};
120
+ --newspaper: #{$newspaper};
108
121
  }
109
122
 
110
123
  .mri-theme {
@@ -139,15 +152,6 @@ $chiclet-color: #a2059e;
139
152
  background: #f3f3f3;
140
153
  }
141
154
 
142
- //Base unit used for spacing gutters
143
- $base-unit: 20px;
144
-
145
- //Screen Sizes
146
- $screen-sm: 480px;
147
- $screen-md: 767px;
148
- $screen-lg: 989px;
149
-
150
- $border-radius-default: 4px;
151
155
 
152
156
  .search-page-mri,
153
157
  .dataset-page-mri {
@@ -4,10 +4,6 @@ import { useLocation } from "react-router-dom"
4
4
  import { SearchPage } from "../components/search-page/SearchPage"
5
5
  import { SearchResultsList } from "../components/search-page/SearchResultsList"
6
6
  import { NeurobagelSearch } from "../components/search-page/NeurobagelSearch"
7
- import {
8
- getUnexpiredProfile,
9
- hasEditPermissions,
10
- } from "../authentication/profile"
11
7
  import { Button } from "../components/button/Button"
12
8
  import { Loading } from "../components/loading/Loading"
13
9
  import {
@@ -36,7 +32,6 @@ import {
36
32
  } from "./inputs"
37
33
  import FiltersBlockContainer from "./filters-block-container"
38
34
  import AggregateCountsContainer from "../pages/front-page/aggregate-queries/aggregate-counts-container"
39
- import { useCookies } from "react-cookie"
40
35
  import { useSearchResults } from "./use-search-results"
41
36
  import { SearchParamsCtx } from "./search-params-ctx"
42
37
  import type { SearchParams } from "./initial-search-params"
@@ -113,8 +108,6 @@ export const setDefaultSearch = (
113
108
  }
114
109
 
115
110
  const SearchContainer: FC<SearchContainerProps> = ({ portalContent }) => {
116
- const [cookies] = useCookies()
117
- const profile = getUnexpiredProfile(cookies)
118
111
  const location = useLocation()
119
112
 
120
113
  const { searchParams, setSearchParams } = useContext(SearchParamsCtx)
@@ -238,16 +231,13 @@ const SearchContainer: FC<SearchContainerProps> = ({ portalContent }) => {
238
231
  : (
239
232
  <>
240
233
  <SearchResultsList
241
- hasEditPermissions={hasEditPermissions}
242
234
  items={resultsList}
243
- profile={profile}
244
235
  datasetTypeSelected={searchParams.datasetType_selected}
245
236
  />
246
237
  {/* TODO: make div below into display component. */}
247
238
  <div className="grid grid-nogutter" style={{ width: "100%" }}>
248
- {resultsList.length > 0 || !hasNextPage
249
- ? null
250
- : (
239
+ {hasNextPage && resultsList.length > 0 &&
240
+ (
251
241
  <div className="col col-12 load-more m-t-10">
252
242
  <Button label="Load More" onClick={loadMore} />
253
243
  </div>
@@ -24,7 +24,7 @@ export const SearchParamsProvider: React.FC<SearchParamsProviderProps> = ({
24
24
  Sentry.addBreadcrumb({
25
25
  category: "routing",
26
26
  message: "No query found in URL. Using initialSearchParams.",
27
- level: "info"
27
+ level: "info",
28
28
  })
29
29
  }
30
30
  } catch (err) {
@@ -79,8 +79,11 @@ export const removeFilterItem = (setSearchParams) => (param, value) => {
79
79
  /* Handle simple filter resets. */
80
80
  case "datasetType_selected":
81
81
  // when datasetType is unset, unset datasetStatus as well
82
- updatedParams["datasetStatus_selected"] =
83
- initialSearchParams["datasetStatus_selected"]
82
+ setSearchParams((prevState) => ({
83
+ ...prevState,
84
+ [param]: initialSearchParams[param],
85
+ "datasetStatus_selected": initialSearchParams["datasetStatus_selected"],
86
+ }))
84
87
  break
85
88
  case "modality_selected":
86
89
  case "brain_initiative":
@@ -266,7 +266,7 @@ export const useSearchResults = () => {
266
266
  matchQuery(
267
267
  "latestSnapshot.description.Authors",
268
268
  joinWithOR(authors),
269
- "3",
269
+ "2",
270
270
  ),
271
271
  )
272
272
  }
@@ -13,6 +13,7 @@ export interface User {
13
13
  export interface UserRoutesProps {
14
14
  user: User
15
15
  hasEdit: boolean
16
+ isUser: boolean
16
17
  }
17
18
  export interface UserCardProps {
18
19
  user: User
@@ -69,4 +70,5 @@ export interface UserDatasetsViewProps {
69
70
  export interface AccountContainerProps {
70
71
  user: User
71
72
  hasEdit: boolean
73
+ isUser: boolean
72
74
  }
@@ -24,7 +24,9 @@ class Upload extends React.Component<UploadProps> {
24
24
  const text = this.props.resume ? "Resume" : "Select folder"
25
25
 
26
26
  return (
27
- <div className="fileupload-btn">
27
+ <div
28
+ className={"fileupload-btn" + (this.props.disabled ? " disabled" : "")}
29
+ >
28
30
  <span>
29
31
  {icon}
30
32
  {text}
@@ -1,30 +1,46 @@
1
1
  import React from "react"
2
2
  import FileSelect from "./file-select"
3
3
  import UploaderContext from "./uploader-context.js"
4
+ import { useUser } from "../queries/user"
4
5
 
5
- const UploadSelect = () => (
6
- <div>
7
- <UploaderContext.Consumer>
8
- {(uploader) => (
9
- <div className="message fade-in">
10
- <p>
11
- To protect the privacy of the individuals who have been scanned, we
12
- require that all scan data be defaced before publishing a dataset.
13
- </p>
14
- Select a{" "}
15
- <a
16
- href="http://bids.neuroimaging.io"
17
- target="_blank"
18
- rel="noopener noreferrer"
19
- >
20
- BIDS dataset
21
- </a>{" "}
22
- to upload
23
- <FileSelect onChange={uploader.selectFiles} />
24
- </div>
25
- )}
26
- </UploaderContext.Consumer>
27
- </div>
28
- )
6
+ const UploadSelect = () => {
7
+ const { user, loading, error } = useUser()
8
+ const disabled = loading || Boolean(error) || !user || !user.email
9
+ const noEmail = !user.email
10
+ return (
11
+ <div>
12
+ <UploaderContext.Consumer>
13
+ {(uploader) => (
14
+ <div className="message fade-in">
15
+ <p>
16
+ To protect the privacy of the individuals who have been scanned,
17
+ we require that all scan data be defaced before publishing a
18
+ dataset.
19
+ </p>
20
+ Select a{" "}
21
+ <a
22
+ href="http://bids.neuroimaging.io"
23
+ target="_blank"
24
+ rel="noopener noreferrer"
25
+ >
26
+ BIDS dataset
27
+ </a>{" "}
28
+ to upload
29
+ <FileSelect onChange={uploader.selectFiles} disabled={disabled} />
30
+ {noEmail && (
31
+ <p>
32
+ Connect a contact email to upload. See our{" "}
33
+ <a href="https://docs.openneuro.org/orcid.html#enabling-trusted-access-to-emails">
34
+ ORCID documentation
35
+ </a>{" "}
36
+ for instructions.
37
+ </p>
38
+ )}
39
+ </div>
40
+ )}
41
+ </UploaderContext.Consumer>
42
+ </div>
43
+ )
44
+ }
29
45
 
30
46
  export default UploadSelect
@@ -1,3 +1,4 @@
1
+ import { vi } from "vitest"
1
2
  import React from "react"
2
3
  import { MockedProvider } from "@apollo/client/testing"
3
4
  import {
@@ -8,24 +9,38 @@ import {
8
9
  within,
9
10
  } from "@testing-library/react"
10
11
  import { UserAccountView } from "../user-account-view"
11
- import { GET_USER_BY_ORCID, UPDATE_USER } from "../user-query"
12
+ import type { User } from "../../types/user-types"
13
+ import * as userQueries from "../../queries/user"
12
14
 
13
- const baseUser = {
15
+ const baseUser: User = {
14
16
  id: "1",
15
17
  name: "John Doe",
16
- email: "johndoe@example.com",
17
- orcid: "0000-0001-2345-6789",
18
- location: "San Francisco, CA",
19
- institution: "University of California",
20
- links: ["https://example.com", "https://example.org"],
21
- github: "johndoe",
18
+ location: "Unknown",
19
+ github: "",
20
+ institution: "Unknown Institution",
21
+ email: "john.doe@example.com",
22
+ avatar: "https://dummyimage.com/200x200/000/fff",
23
+ orcid: "0000-0000-0000-0000",
24
+ links: [],
22
25
  }
23
26
 
27
+ vi.mock("../../queries/user", async () => {
28
+ const actual = await vi.importActual("../../queries/user")
29
+ return {
30
+ ...actual,
31
+ useUser: () => ({
32
+ user: baseUser,
33
+ loading: false,
34
+ error: undefined,
35
+ }),
36
+ }
37
+ })
38
+
24
39
  const mocks = [
25
40
  {
26
41
  request: {
27
- query: GET_USER_BY_ORCID,
28
- variables: { userId: baseUser.id },
42
+ query: userQueries.GET_USER,
43
+ variables: { id: baseUser.orcid },
29
44
  },
30
45
  result: {
31
46
  data: {
@@ -35,9 +50,9 @@ const mocks = [
35
50
  },
36
51
  {
37
52
  request: {
38
- query: UPDATE_USER,
53
+ query: userQueries.UPDATE_USER,
39
54
  variables: {
40
- id: baseUser.id,
55
+ id: baseUser.orcid,
41
56
  location: "Marin, CA",
42
57
  links: ["https://newlink.com"],
43
58
  institution: "New University",
@@ -46,7 +61,7 @@ const mocks = [
46
61
  result: {
47
62
  data: {
48
63
  updateUser: {
49
- id: baseUser.id,
64
+ id: baseUser.orcid,
50
65
  location: "Marin, CA",
51
66
  links: ["https://newlink.com"],
52
67
  institution: "New University",
@@ -60,23 +75,22 @@ describe("<UserAccountView />", () => {
60
75
  it("should render the user details correctly", () => {
61
76
  render(
62
77
  <MockedProvider mocks={mocks} addTypename={false}>
63
- <UserAccountView user={baseUser} />
78
+ <UserAccountView />
64
79
  </MockedProvider>,
65
80
  )
66
81
  expect(screen.getByText("Name:")).toBeInTheDocument()
67
82
  expect(screen.getByText("John Doe")).toBeInTheDocument()
68
83
  expect(screen.getByText("Email:")).toBeInTheDocument()
69
- expect(screen.getByText("johndoe@example.com")).toBeInTheDocument()
84
+ expect(screen.getByText("john.doe@example.com")).toBeInTheDocument()
70
85
  expect(screen.getByText("ORCID:")).toBeInTheDocument()
71
- expect(screen.getByText("0000-0001-2345-6789")).toBeInTheDocument()
72
- expect(screen.getByText("GitHub:")).toBeInTheDocument()
73
- expect(screen.getByText("johndoe")).toBeInTheDocument()
86
+ expect(screen.getByText("0000-0000-0000-0000")).toBeInTheDocument()
87
+ expect(screen.getByText("Connect your GitHub")).toBeInTheDocument()
74
88
  })
75
89
 
76
90
  it("should render location with EditableContent", async () => {
77
91
  render(
78
92
  <MockedProvider mocks={mocks} addTypename={false}>
79
- <UserAccountView user={baseUser} />
93
+ <UserAccountView />
80
94
  </MockedProvider>,
81
95
  )
82
96
  const locationSection = within(screen.getByTestId("location-section"))
@@ -95,7 +109,7 @@ describe("<UserAccountView />", () => {
95
109
  it("should render institution with EditableContent", async () => {
96
110
  render(
97
111
  <MockedProvider mocks={mocks} addTypename={false}>
98
- <UserAccountView user={baseUser} />
112
+ <UserAccountView />
99
113
  </MockedProvider>,
100
114
  )
101
115
  const institutionSection = within(screen.getByTestId("institution-section"))
@@ -114,7 +128,7 @@ describe("<UserAccountView />", () => {
114
128
  it("should render links with EditableContent and validation", async () => {
115
129
  render(
116
130
  <MockedProvider mocks={mocks} addTypename={false}>
117
- <UserAccountView user={baseUser} />
131
+ <UserAccountView />
118
132
  </MockedProvider>,
119
133
  )
120
134
  const linksSection = within(screen.getByTestId("links-section"))
@@ -133,7 +147,7 @@ describe("<UserAccountView />", () => {
133
147
  it("should show an error message when invalid URL is entered in links section", async () => {
134
148
  render(
135
149
  <MockedProvider mocks={mocks} addTypename={false}>
136
- <UserAccountView user={baseUser} />
150
+ <UserAccountView />
137
151
  </MockedProvider>,
138
152
  )
139
153
  const linksSection = within(screen.getByTestId("links-section"))
@@ -3,7 +3,7 @@ import { render, screen, waitFor } from "@testing-library/react"
3
3
  import { MockedProvider } from "@apollo/client/testing"
4
4
  import { MemoryRouter, Route, Routes } from "react-router-dom"
5
5
  import { UserQuery } from "../user-query"
6
- import { GET_USER_BY_ORCID } from "../user-query"
6
+ import { GET_USER } from "../../queries/user"
7
7
  import * as ProfileUtils from "../../authentication/profile"
8
8
 
9
9
  Object.defineProperty(ProfileUtils, "getProfile", {
@@ -15,8 +15,8 @@ const validOrcid = "0009-0001-9689-7232"
15
15
 
16
16
  const userMock = {
17
17
  request: {
18
- query: GET_USER_BY_ORCID,
19
- variables: { userId: validOrcid },
18
+ query: GET_USER,
19
+ variables: { userId: "1" },
20
20
  },
21
21
  result: {
22
22
  data: {