Last active
November 25, 2021 17:31
-
-
Save EmmaB/6b998fc9bb2e710f73cd1f72a9fbef8b to your computer and use it in GitHub Desktop.
WIP contribs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useContext } from "react" | |
import * as yup from "yup" | |
import WorkContext from "contexts/work_context" | |
import Link from "components/external_link" | |
import Form from "components/editable_area/components/form" | |
import NumberField from "components/editable_area/components/number_field" | |
import ProductIdsCheckboxField from "./form/product_ids_checkbox_field" | |
import OnixCodeField from "./form/onix_code_field" | |
import { ContactSelectField } from "components/editable_area/components/contact_select_field" | |
const OnixCode = ({ code, description }) => ( | |
<> | |
<span | |
className="pill pill--label pill--green" | |
dangerouslySetInnerHTML={{ __html: code }} | |
/> | |
<span dangerouslySetInnerHTML={{ __html: description }} /> | |
</> | |
) | |
const onixCode = () => | |
yup.string().transform(function (value, originalValue) { | |
if (this.isType(value)) return value | |
return originalValue?.value | |
}) | |
const ContributionFormSchema = yup | |
.object() | |
.shape({ | |
productIds: yup.array().nullable().default([]).of(yup.number().nullable()), | |
sequenceNumber: yup | |
.number() | |
.min(1) | |
.default(1) | |
.nullable() | |
.required("You need a position") | |
.label("Position"), | |
contributor: yup | |
.mixed() | |
.required("You need a contributor") | |
.label("Contributor") | |
.transform(values => { | |
if (values) { | |
return values.value | |
} else { | |
return undefined | |
} | |
}), | |
onixContributorRole: yup.object().nullable(), | |
onixContributorRoleCode: onixCode().nullable(), | |
}) | |
.from("onixContributorRole", "onixContributorRoleCode") | |
.noUnknown() | |
export const ShowComponent = ({ | |
contributor, | |
productIds, | |
onixContributorRole, | |
}) => { | |
const work = useContext(WorkContext) | |
return ( | |
<ul> | |
<li> | |
{onixContributorRole ? <OnixCode {...onixContributorRole} /> : null}{" "} | |
</li> | |
<li> | |
<Link href={`/contacts/${contributor?.id}`}> | |
{contributor?.personName} {contributor?.organisationName} | |
</Link> | |
</li> | |
<li> | |
Products: | |
{/* Need to copy the array first, as sorting tries to mutate the original */} | |
{[...productIds].sort().map((product, index) => ( | |
<span key={index}> | |
{" "} | |
{work.products.find(x => x.id === product).isbn?.isbn13} | |
</span> | |
))} | |
</li> | |
</ul> | |
) | |
} | |
export const FormComponent = props => { | |
const work = useContext(WorkContext) | |
// Says whether the checkbox is checked or not, depending on whether the product id is already | |
// in the productIds array | |
const checked = product => | |
props.attributes | |
? props.attributes.productIds.includes(product) | |
? true | |
: false | |
: false | |
return ( | |
<Form schema={ContributionFormSchema} {...props}> | |
{work && | |
work.products.map((product, index) => ( | |
<ProductIdsCheckboxField | |
key={index} | |
label={`${product.isbn?.isbn13}`} | |
name={product.id} | |
value={product.id} | |
defaultChecked={checked(product.id)} | |
hint={`Check the box if this contact contributed to ${product.isbn?.isbn13}`} | |
/> | |
))} | |
<NumberField name="sequenceNumber" label="Position" /> | |
{work && ( | |
<ContactSelectField | |
name="contributor" | |
label="Contributor" | |
clientId={work.clientId} | |
className="form__input--half" | |
/> | |
)} | |
<OnixCodeField | |
name="onixContributorRole" | |
label="Contributor role" | |
hint="The role done by this contributor on this work" | |
listNumber={17} | |
isClearable={true} | |
/> | |
</Form> | |
) | |
} | |
# test | |
import { screen, waitFor, within, prettyDOM } from "@testing-library/react" | |
import { graphql } from "msw" | |
import userEvent from "@testing-library/user-event" | |
import { | |
workFactory, | |
contributionFactory, | |
contactFactory, | |
onixCodeFactory, | |
} from "../../factories" | |
import { server } from "../../msw/server" | |
import renderComponent from "./render_component" | |
import { selectFrom, clearSelect } from "../../support/utils" | |
const ONIX_CODE_DESCRIPTIONS = { | |
A01: "By (author)", | |
B01: "Edited by", | |
E02: "Dancer", | |
} | |
const buildOnixCode = (code, description) => | |
onixCodeFactory.build({ | |
code, | |
description, | |
value: !isNaN(code) ? `_${code}` : code, | |
}) | |
const buildOnixCodeFromValue = value => | |
value | |
? buildOnixCode(value.replace("_", ""), ONIX_CODE_DESCRIPTIONS[value]) | |
: null | |
it("has the Contributors region", () => { | |
renderComponent() | |
expect( | |
screen.getByRole("region", { name: "Contributors" }) | |
).toBeInTheDocument() | |
}) | |
it("shows a loading message in the Contributors region", () => { | |
renderComponent() | |
const region = screen.getByRole("region", { name: "Contributors" }) | |
expect(region).toHaveTextContent("Loading...") | |
}) | |
describe("shows the contributor information", () => { | |
let work | |
beforeEach(() => { | |
work = workFactory.build({ | |
contributions: [ | |
contributionFactory.build({ | |
contributor: contactFactory.build(), | |
onixContributorRole: buildOnixCode("A01", "By (author)"), | |
}), | |
], | |
}) | |
server.use( | |
graphql.query("GetWork", (_req, res, ctx) => { | |
return res( | |
ctx.data({ | |
work, | |
}) | |
) | |
}) | |
) | |
}) | |
it("shows the contributor's role in the Contributors region", async () => { | |
renderComponent() | |
const region = screen.getByRole("region", { name: "Contributors" }) | |
await waitFor(() => { | |
expect(region).toHaveTextContent("A01: By (author)") | |
}) | |
}) | |
}) | |
describe("updates the contributor", () => { | |
let work | |
beforeEach(() => { | |
work = workFactory.build({ | |
contributions: [ | |
contributionFactory.build({ | |
contributor: contactFactory.build({ | |
label: "Alain Marley", | |
personName: "Alain Marley", | |
}), | |
onixContributorRole: buildOnixCode("A01", "By (author)"), | |
}), | |
], | |
}) | |
server.use( | |
graphql.query("GetWork", (_req, res, ctx) => { | |
return res( | |
ctx.data({ | |
work, | |
}) | |
) | |
}), | |
graphql.mutation("UpdateContribution", (req, res, ctx) => { | |
const { ...contributionAttributes } = req.variables.input | |
const updatedContribution = { | |
...contributionAttributes, | |
} | |
return res( | |
ctx.data({ | |
updateContribution: { | |
contribution: updatedContribution, | |
errors: [], | |
}, | |
}) | |
) | |
}) | |
) | |
}) | |
it("updates the contribution with a new role", async () => { | |
renderComponent() | |
const region = screen.getByRole("region", { name: "Contributors" }) | |
await waitFor(() => { | |
userEvent.click(within(region).getByRole("button", { name: "Edit" })) | |
}) | |
await selectFrom(region, "Contributor role", "Edited by") | |
userEvent.click(screen.getByRole("button", { name: "Save" })) | |
await waitFor(() => { | |
expect(region).toHaveTextContent("B01: Edited by") | |
// Ensure the form has been closed | |
expect( | |
screen.queryByRole("button", { name: "Save" }) | |
).not.toBeInTheDocument() | |
}) | |
}) | |
}) | |
# Cucumber | |
@javascript | |
Feature: Work metadata contributions | |
Background: | |
Given I'm logged in as a user of "Fauxbooks" | |
And the client "Fauxbooks" has the following work: | |
| title | | |
| Tales of Monkey Island | | |
And the work "Tales of Monkey Island" has the following products: | |
| isbn | | |
| 9781905005123 | | |
| 9781905005888 | | |
And the following onix code lists: | |
| list_number | list_description | | |
| 17 | Contributor role code | | |
And the onix code list with a description of "Contributor role code" has the following onix codes: | |
| value | description | notes | | |
| A01 | By (author) | a | | |
| B01 | Edited by | aa | | |
| A04 | Libretto by | aa | | |
| B06 | Translated by | aa | | |
| E03 | Narrator | aa | | |
Scenario: Add a contribution | |
Given the client "Fauxbooks" has the following contact: | |
| names_before_key | keynames | | |
| Captain | Marley | | |
And I am on the editable metadata page for "Tales of Monkey Island" | |
When I begin to add the following contribution: | |
| Position | 1 | | |
| Contributor role | Libretto by | | |
| Contributor | Captain Marley | | |
And I mark the following as included products: | |
| isbn | | |
| 9781905005123 | | |
| 9781905005888 | | |
Then I should see the following contribution: | |
""" | |
Products: 9781905005123 9781905005888 | |
A04: Libretto by | |
Name: Captain Marley | |
""" | |
And the work "Tales of Monkey Island" should have the following contributions: | |
| contact | work_contact_role | products_count | | |
| Captain Marley | A04 | 2 | | |
# Scenario: Add a contribution with conflicting data | |
# Given the client "Fauxbooks" has the following contact: | |
# | names_before_key | keynames | | |
# | Captain | Marley | | |
# And the work "Tales of Monkey Island" has the following contributions: | |
# | contact | work_contact_role | sequence_number | | |
# | Captain Marley | B01 | 1 | | |
# And I am on the editable metadata page for "Tales of Monkey Island" | |
# When I add the following contribution: | |
# | Position | 1 | | |
# | Role | Libretto by | | |
# | Contributor | Captain Marley | | |
# Then I should see a validation error on "Position" that says "Sequence number has already been taken" | |
Scenario: Attempt to add a contribution with invalid fields | |
Given the client "Fauxbooks" has the following contact: | |
| names_before_key | keynames | | |
| Captain | Marley | | |
And the work "Tales of Monkey Island" has the following contributions: | |
| contact | work_contact_role | sequence_number | | |
| Captain Marley | B01 | 1 | | |
And I am on the editable metadata page for "Tales of Monkey Island" | |
When I add the following contribution: | |
| Position | 0 | | |
Then I should see a validation error on "Position" that says "Position must be greater than or equal to 1" | |
And I should see a validation error on "Contributor" that says "You need a contributor" | |
Scenario: Edit a contribution | |
Given the client "Fauxbooks" has the following contact: | |
| names_before_key | keynames | | |
| Elaine | Marley | | |
| Capt | Marley | | |
And the work "Tales of Monkey Island" has the following contributions: | |
| contact | work_contact_role | | |
| Elaine Marley | B01 | | |
| Capt Marley | B06 | | |
And I am on the editable metadata page for "Tales of Monkey Island" | |
When I edit the "Edited by" contribution to: | |
| Contributor role | Narrator | | |
Then I should see the following contribution: | |
""" | |
E03: Narrator | |
Name: Elaine Marley | |
""" | |
Scenario: Remove a contribution | |
Given the client "Fauxbooks" has the following contact: | |
| names_before_key | keynames | | |
| Elaine | Marley | | |
| Herman | Toothrot | | |
And the work "Tales of Monkey Island" has the following contributions: | |
| contact | work_contact_role | | |
| Elaine Marley | B01 | | |
| Herman Toothrot | B06 | | |
And I am on the editable metadata page for "Tales of Monkey Island" | |
When I delete the "Edited by" contribution of "Elaine Marley" | |
Then I should not see the following contribution: | |
""" | |
Name: Elaine Marley | |
Contributor role: Edited by | |
""" | |
And the work "Tales of Monkey Island" should have the following contributions: | |
| contact | work_contact_role | | |
| Herman Toothrot | B06 | | |
Scenario: Reorder a contribution | |
Given the client "Fauxbooks" has the following contact: | |
| names_before_key | keynames | | |
| Elaine | Marley | | |
| Capt | Marley | | |
| Capt | Snarley | | |
| Sgt | Barley | | |
And the work "Tales of Monkey Island" has the following contributions: | |
| contact | work_contact_role | | |
| Elaine Marley | B01 | | |
| Capt Snarley | B03 | | |
| Capt Marley | B06 | | |
| Sgt Barley | B02 | | |
And I am on the editable metadata page for "Tales of Monkey Island" | |
When I drag the "B01" contribution to after "B06" | |
Then the work "Tales of Monkey Island" should have the following sorted contributions: | |
| contact | | |
| Capt Snarley | | |
| Capt Marley | | |
| Elaine Marley | | |
| Sgt Barley | | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment