Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/show object details #452

Merged
merged 4 commits into from
Sep 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 21 additions & 23 deletions src/__tests__/SubmissionDetailTable.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ const store = mockStore({})

const server = setupServer()

const metadataObjects = [
{
accessionId: "123testid",
schema: "study",
tags: { submissionType: "Form", displayTitle: "Published object" },
},
]

const draftObjects = [
{
accessionId: "456testid",
schema: "draft-study",
tags: { displayTitle: "Draft object" },
},
]

describe("Published folders list", () => {
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
Expand All @@ -32,20 +48,8 @@ describe("Published folders list", () => {
name: "Test unpublished folder",
description: "Test description",
published: false,
metadataObjects: [
{
accessionId: "123testid",
schema: "study",
tags: { submissionType: "Form", displayTitle: "Published object" },
},
],
drafts: [
{
accessionId: "456testid",
schema: "draft-study",
tags: { displayTitle: "Draft object" },
},
],
metadataObjects: metadataObjects,
drafts: draftObjects,
folderId: folderId,
})
)
Expand Down Expand Up @@ -90,10 +94,10 @@ describe("Published folders list", () => {
const editButton = await screen.findByTestId("edit-button")
expect(editButton).toBeInTheDocument()

const publishedObject = await screen.findByTestId("Published object")
const publishedObject = await screen.findByTestId(metadataObjects[0].tags.displayTitle)
expect(publishedObject).toBeInTheDocument()

const draftObject = await screen.findByTestId("Draft object")
const draftObject = await screen.findByTestId(draftObjects[0].tags.displayTitle)
expect(draftObject).toBeInTheDocument()
})

Expand All @@ -106,13 +110,7 @@ describe("Published folders list", () => {
name: "Test published folder",
description: "Test description",
published: true,
metadataObjects: [
{
accessionId: "123testid",
schema: "study",
tags: { submissionType: "Form", displayTitle: "Published object" },
},
],
metadataObjects: metadataObjects,
folderId: folderId,
})
)
Expand Down
216 changes: 216 additions & 0 deletions src/__tests__/WizardObjectDetails.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import React from "react"

import "@testing-library/jest-dom/extend-expect"
import { ThemeProvider } from "@material-ui/core/styles"
import { render, screen, waitForElementToBeRemoved } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { rest } from "msw"
import { setupServer } from "msw/node"
import { Provider } from "react-redux"
import { MemoryRouter } from "react-router-dom"
import configureStore from "redux-mock-store"

import CSCtheme from "../theme"

import SelectedFolderDetails from "components/Home/SelectedFolderDetails"
import WizardObjectDetails from "components/NewDraftWizard/WizardComponents/WizardObjectDetails"

const mockStore = configureStore([])
const store = mockStore({})

const server = setupServer()

const schema = {
title: "Test schema",
type: "object",
properties: {
listItemFields: {
type: "object",
title: "List items section title",
required: ["stringField"],
properties: {
stringField: {
title: "String Field Title",
type: "string",
},
integerField: {
title: "Integer Field Title",
type: "integer",
},
numberField: {
title: "Number Field Title",
type: "number",
},
booleanField: {
title: "Boolean Field Title",
type: "boolean",
},
},
},
arrayFields: {
type: "object",
title: "Array items section title",
properties: {
checkboxArray: {
// Eg. Dataset > Dataset Type
type: "array",
title: "Checkbox array title",
items: {
type: "string",
enum: ["Checkbox item 1", "Checkbox item 2"],
},
},
oneOfArray: {
// Eg. Study > Study Links
type: "array",
title: "OneOf array title",
items: {
title: "Item key",
oneOf: [
{
type: "object",
title: "First oneOf item",
properties: { key1: { type: "string", title: "First item label" } },
required: ["key1"],
},
{
type: "object",
title: "Second oneOf item",
properties: { key2: { type: "string", title: "Second item label" } },
required: ["key2"],
},
],
},
},
},
},
oneOf: {
// Eg. Experiment > Design > Properties > Sample descriptor,
type: "object",
title: "OneOf title",
properties: {
oneOfField: {
title: "Options",
oneOf: [
{
type: "object",
title: "First option",
properties: { firstOption: { type: "string", title: "First oneOf option label" } },
},
{
type: "object",
title: "Second option",
properties: { secondOption: { type: "string", title: "Second oneOf option label" } },
},
],
},
},
},
},
}

describe("Object details", () => {
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

it("should render object details component on 'Show details' button click", async () => {
server.use(
rest.get("/schemas/:schema", (req, res, ctx) => {
return res(ctx.json(schema))
}),
rest.get("/folders/:folderId", (req, res, ctx) => {
return res(
ctx.json({
name: "Test Folder",
description: "Folder description",
published: true,
metadataObjects: [
{
accessionId: "objectAccessionId",
schema: "study",
tags: { submissionType: "Form", displayTitle: "Published object" },
},
],
drafts: [],
folderId: "testaccessionid",
dateCreated: 1111111111,
})
)
}),
rest.get("/objects/study/:accessionId", (req, res, ctx) => {
return res(
ctx.json({
descriptor: { studyTitle: "Published object", studyType: "Synthetic Genomics" },
accessionId: "edd227d34a4f4340a206ef48c87848da",
dateCreated: "2021-09-09T05:16:36.002000",
dateModified: "2021-09-09T05:16:36.002000",
publishDate: "2021-11-09T05:16:36.002000",
})
)
})
)

render(
<MemoryRouter initialEntries={[{ pathname: "/home/published/testaccessionid" }]}>
<Provider store={store}>
<ThemeProvider theme={CSCtheme}>
<SelectedFolderDetails />
</ThemeProvider>
</Provider>
</MemoryRouter>
)

await waitForElementToBeRemoved(() => screen.getByRole("progressbar"))
userEvent.click(screen.getByTestId("toggle-details"))

await waitForElementToBeRemoved(() => screen.getByRole("progressbar"))
expect(screen.getByText("Hide details")).toBeInTheDocument()
expect(screen.getByTestId("section")).toBeInTheDocument()
})

it("should render object details by object data and schema", async () => {
server.use(
rest.get("/schemas/:schema", (req, res, ctx) => {
return res(ctx.json(schema))
})
)

const objectData = {
listItemFields: {
stringField: "String label",
integerField: "Integer label",
numberField: "Number label",
booleanField: "Boolean label",
},
arrayFields: { checkboxArray: ["Checkbox item 1", "Checkbox item 2"], oneOfArray: [{ key2: "Test item" }] },
oneOf: { oneOfField: { firstOption: "Test label" } },
}

render(
<Provider store={store}>
<WizardObjectDetails objectType="study" objectData={objectData} />
</Provider>
)

await waitForElementToBeRemoved(() => screen.getByRole("progressbar"))

// Sections
// Note: Nested properties have at least 2 sections
expect(screen.getAllByTestId("section")).toHaveLength(6)

// List items
for (const item of Object.keys(objectData.listItemFields)) {
expect(screen.getByTestId(`listItemFields.${item}`)).toBeInTheDocument()
}

// Array items
expect(screen.getAllByTestId("checkbox-item")).toHaveLength(2)
expect(screen.queryByText("First oneOf item")).not.toBeInTheDocument()
expect(screen.getByTestId("arrayFields.oneOfArray[0].key2")).toBeInTheDocument()

// OneOf
expect(screen.getByTestId("oneOf.oneOfField.firstOption")).toBeInTheDocument()
expect(screen.queryByText("Second oneOf option label")).not.toBeInTheDocument()
})
})
67 changes: 30 additions & 37 deletions src/components/Home/SelectedFolderDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,30 @@ const SelectedFolderDetails = (): React$Element<typeof Grid> => {
// Fetch folder data and map objects
useEffect(() => {
let isMounted = true

const handleObject = async (data: any, draft: boolean, objectType: string, objectInFolder: any) => {
const service = draft ? draftAPIService : objectAPIService

const response = await service.getObjectByAccessionId(objectType, objectInFolder.accessionId)

if (response.ok) {
const objectDetails = {
accessionId: objectInFolder.accessionId,
title: getItemPrimaryText(objectInFolder),
objectType,
submissionType: objectInFolder.tags.submissionType || ObjectSubmissionTypes.form, // Fallback for 'Form'. Used in drafts
status: draft ? ObjectStatus.draft : ObjectStatus.submitted,
lastModified: response.data.dateModified,
objectData: response.data,
}
objectsArr.push(objectDetails)
} else {
setConnError(true)
setResponseError(response)
setErrorPrefix("Object fetching error.")
}
}

const getFolder = async () => {
const response = await folderAPIService.getFolderById(folderId)
if (isMounted) {
Expand All @@ -72,46 +96,15 @@ const SelectedFolderDetails = (): React$Element<typeof Grid> => {
const objectType = data.drafts[i].schema.includes("draft-")
? data.drafts[i].schema.substr(6)
: data.drafts[i].schema
const response = await draftAPIService.getObjectByAccessionId(objectType, data.drafts[i].accessionId)
if (response.ok) {
const draftObjectDetails = {
accessionId: data.drafts[i].accessionId,
title: response.data.descriptor?.studyTitle,
objectType,
submissionType: ObjectSubmissionTypes.form, // Only forms can be drafts
status: ObjectStatus.draft,
lastModified: response.data.dateModified,
}
objectsArr.push(draftObjectDetails)
} else {
setConnError(true)
setResponseError(response)
setErrorPrefix("Fetching folder error.")
}

await handleObject(data, true, objectType, data.drafts[i])
}
}
for (let j = 0; j < data.metadataObjects?.length; j += 1) {
const objectType = data.metadataObjects[j].schema
const response = await objectAPIService.getObjectByAccessionId(
objectType,
data.metadataObjects[j].accessionId
)
if (response.ok) {
const submittedObjectDetails = {
accessionId: data.metadataObjects[j].accessionId,
title: getItemPrimaryText(data.metadataObjects[j]),
objectType,
submissionType: data.metadataObjects[j].tags.submissionType,
status: ObjectStatus.submitted,
lastModified: response.data.dateModified,
}
objectsArr.push(submittedObjectDetails)
} else {
setConnError(true)
setResponseError(response)
setErrorPrefix("Fetching folder error.")
}
for (let i = 0; i < data.metadataObjects?.length; i += 1) {
const objectType = data.metadataObjects[i].schema
await handleObject(data, false, objectType, data.metadataObjects[i])
}

setSelectedFolder({
originalFolderData: data,
folderTitle: data.name,
Expand Down
Loading