Skip to content

Commit 576328e

Browse files
committed
Support local IDs for overlay of MARC records.
refs #3555
1 parent e38de3d commit 576328e

27 files changed

+592
-50
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
[
2+
{
3+
"@id": "http://localhost:3000/resource/ae93cff4-d272-43b2-a4ee-fb8651907e51",
4+
"@type": [
5+
"http://sinopia.io/vocabulary/LocalAdminMetadata"
6+
],
7+
"http://id.loc.gov/ontologies/bibframe/identifier": [
8+
{
9+
"@id": "_:Nfe4b29df32004cc1b097a218f69df09f"
10+
}
11+
],
12+
"http://sinopia.io/vocabulary/exportDate": [
13+
{
14+
"@value": "2022-08-01T15:49:44.558203"
15+
}
16+
],
17+
"http://sinopia.io/vocabulary/hasResourceTemplate": [
18+
{
19+
"@value": "pcc:sinopia:localAdminMetadata"
20+
}
21+
],
22+
"http://sinopia.io/vocabulary/localAdminMetadataFor": [
23+
{
24+
"@id": "http://localhost:3000/resource/a5c5f4c0-e7cd-4ca5-a20f-2a37fe1080d5"
25+
}
26+
]
27+
},
28+
{
29+
"@id": "_:Nfe4b29df32004cc1b097a218f69df09f",
30+
"@type": [
31+
"http://id.loc.gov/ontologies/bibframe/Local"
32+
],
33+
"http://id.loc.gov/ontologies/bibframe/source": [
34+
{
35+
"@id": "_:Nf65f353d6fb64adeb6aa6040d21fb88c"
36+
}
37+
],
38+
"http://www.w3.org/1999/02/22-rdf-syntax-ns#value": [
39+
{
40+
"@value": "13714202"
41+
}
42+
]
43+
},
44+
{
45+
"@id": "_:Nf65f353d6fb64adeb6aa6040d21fb88c",
46+
"@type": [
47+
"http://id.loc.gov/ontologies/bibframe/Source"
48+
],
49+
"http://www.w3.org/2000/01/rdf-schema#label": [
50+
{
51+
"@value": "SIRSI"
52+
}
53+
]
54+
}
55+
]

__tests__/actionCreators/relationships.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ describe("loadRelationships()", () => {
7171
bfAdminMetadataRefs: [
7272
"http://localhost:3000/resource/72f2f457-31f5-432c-8acf-b4037f7754g",
7373
],
74+
sinopiaLocalAdminMetadataRefs: [],
7475
bfItemRefs: [],
7576
bfInstanceRefs: [],
7677
bfWorkRefs: [

__tests__/actionCreators/resources.loadResource.test.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ describe("loadResource", () => {
4747
sinopiaSearch.getSearchResultsByUris = jest
4848
.fn()
4949
.mockResolvedValue({ results: [] })
50-
jest.spyOn(relationshipActionCreators, "loadRelationships")
5150

5251
it("dispatches actions", async () => {
5352
const result = await store.dispatch(
@@ -75,20 +74,26 @@ describe("loadResource", () => {
7574
group: "stanford",
7675
modified: "2020-08-20T11:34:40.887Z",
7776
})
77+
expect(actions).toHaveAction("SET_RELATIONSHIPS", {
78+
resourceKey: "abc123",
79+
relationships: {
80+
bfAdminMetadataRefs: [],
81+
sinopiaLocalAdminMetadataRefs: [
82+
"http://localhost:3000/resource/ae93cff4-d272-43b2-a4ee-fb8651907e51",
83+
],
84+
bfItemRefs: [],
85+
bfInstanceRefs: [],
86+
bfWorkRefs: [],
87+
},
88+
})
89+
expect(actions).toHaveAction("CLEAR_LOCAL_IDS", "abc123")
7890

7991
expect(sinopiaApi.putUserHistory).toHaveBeenCalledWith(
8092
"Foo McBar",
8193
"resource",
8294
"87d27b05d48874c9f80cd4b7e8fc0dcc",
8395
uri
8496
)
85-
86-
// loadRelationships is invoked async and do not wait for results
87-
expect(relationshipActionCreators.loadRelationships).toHaveBeenCalledWith(
88-
"abc123",
89-
uri,
90-
"testerrorkey"
91-
)
9297
})
9398
})
9499

__tests__/actionCreators/transfer.test.js

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,42 @@ import configureMockStore from "redux-mock-store"
33
import thunk from "redux-thunk"
44
import * as sinopiaApi from "sinopiaApi"
55
import { createState } from "stateUtils"
6-
import { transfer } from "actionCreators/transfer"
6+
import { transfer, loadLocalIds } from "actionCreators/transfer"
7+
import Config from "Config"
78

89
const mockStore = configureMockStore([thunk])
910

1011
const resourceUri =
1112
"https://api.development.sinopia.io/resource/7b4c275d-b0c7-40a4-80b3-e95a0d9d987c"
1213

14+
// This forces Sinopia server to use fixtures
15+
jest.spyOn(Config, "useResourceTemplateFixtures", "get").mockReturnValue(true)
16+
1317
describe("transfer", () => {
1418
describe("successful", () => {
1519
it("dispatches actions to add user", async () => {
1620
sinopiaApi.postTransfer = jest.fn().mockResolvedValue()
1721
const store = mockStore(createState())
1822
await store.dispatch(
19-
transfer(resourceUri, "stanford", "ils", "testerrorkey")
23+
transfer(resourceUri, "stanford", "FOLIO", "abc123", "testerrorkey")
2024
)
2125

2226
expect(store.getActions()).toHaveLength(0)
2327
expect(sinopiaApi.postTransfer).toHaveBeenCalledWith(
2428
resourceUri,
2529
"stanford",
26-
"ils"
30+
"FOLIO",
31+
"abc123"
2732
)
2833
})
2934
})
30-
describe("failure", () => {
35+
36+
describe("transfer failure", () => {
3137
it("dispatches actions to remove user", async () => {
3238
sinopiaApi.postTransfer = jest.fn().mockRejectedValue("Ooops!")
3339
const store = mockStore(createState())
3440
await store.dispatch(
35-
transfer(resourceUri, "stanford", "ils", "testerrorkey")
41+
transfer(resourceUri, "stanford", "", "abc123", "testerrorkey")
3642
)
3743

3844
expect(store.getActions()).toHaveAction("ADD_ERROR", {
@@ -41,4 +47,29 @@ describe("transfer", () => {
4147
})
4248
})
4349
})
50+
51+
describe("loadLocalIds()", () => {
52+
it("dispatches actions to set local id", async () => {
53+
const store = mockStore(createState())
54+
await store.dispatch(
55+
loadLocalIds(
56+
"abc123",
57+
[
58+
"http://localhost:3000/resource/ae93cff4-d272-43b2-a4ee-fb8651907e51",
59+
],
60+
"testerrorkey"
61+
)
62+
)
63+
64+
const actions = store.getActions()
65+
66+
expect(actions).toHaveAction("CLEAR_LOCAL_IDS", "abc123")
67+
expect(actions).toHaveAction("SET_LOCAL_ID", {
68+
resourceKey: "abc123",
69+
target: "SIRSI",
70+
group: "stanford",
71+
localId: "13714202",
72+
})
73+
})
74+
})
4475
})

__tests__/feature/editing/transfer.test.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jest.spyOn(Config, "transferConfig", "get").mockReturnValue({
2020
},
2121
})
2222

23-
describe("transfer saved bf:Instance when user belongs to a transfer group", () => {
23+
describe("transfer saved bf:Instance when user belongs to a transfer group and no local ID", () => {
2424
it("allows transfer", async () => {
2525
const state = createState()
2626
const store = createStore(state)
@@ -42,6 +42,37 @@ describe("transfer saved bf:Instance when user belongs to a transfer group", ()
4242

4343
const transferBtn = screen.getByText("Export to Catalog")
4444
fireEvent.click(transferBtn)
45+
fireEvent.click(await screen.findByText("Create a new record in catalog."))
46+
await screen.findByText("Requesting")
47+
}, 15000)
48+
})
49+
50+
describe("transfer saved bf:Instance when user belongs to a transfer group and provided local ID", () => {
51+
it("allows transfer", async () => {
52+
const state = createState()
53+
const store = createStore(state)
54+
renderApp(store)
55+
56+
fireEvent.click(screen.getByText("Linked Data Editor", { selector: "a" }))
57+
58+
fireEvent.change(screen.getByLabelText("Search"), {
59+
target: { value: bfUri },
60+
})
61+
fireEvent.click(screen.getByTestId("Submit search"))
62+
63+
await screen.findByText(bfUri)
64+
fireEvent.click(screen.getByRole("button", { name: `Edit ${bfUri}` }))
65+
66+
await screen.findByText("The Practitioner's Guide to Graph Data", {
67+
selector: resourceHeaderSelector,
68+
})
69+
70+
const transferBtn = screen.getByText("Export to Catalog")
71+
fireEvent.click(transferBtn)
72+
fireEvent.change(await screen.findByLabelText("Enter local system id"), {
73+
target: { value: "abc123" },
74+
})
75+
fireEvent.click(await screen.findByText("Go"))
4576
await screen.findByText("Requesting")
4677
}, 15000)
4778
})

__tests__/feature/editing/viewRelationships.test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ describe("relationships", () => {
2020
],
2121
bfInstanceInferredRefs: [],
2222
bfWorkInferredRefs: [],
23+
sinopiaHasLocalAdminMetadataInferredRefs: [],
2324
})
2425

2526
jest.spyOn(sinopiaSearch, "getSearchResultsByUris").mockResolvedValue({
@@ -75,6 +76,7 @@ describe("relationships", () => {
7576
bfItemInferredRefs: [],
7677
bfInstanceInferredRefs: [],
7778
bfWorkInferredRefs: [],
79+
sinopiaHasLocalAdminMetadataInferredRefs: [],
7880
})
7981
})
8082

__tests__/feature/searchAndPreviewResource.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,8 @@ describe("searching and preview a resource", () => {
246246
).toHaveLength(1)
247247

248248
screen.getByText("MARC", { selector: "button" })
249-
screen.getByText(/Export to/, { selector: "button" })
249+
screen.getByText("Export to Symphony", { selector: "button" })
250+
screen.getByText("Export to Folio", { selector: "button" })
250251

251252
// Switch to relationships
252253
fireEvent.change(screen.getByLabelText(/Format/), {

__tests__/reducers/resources.test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,11 @@ describe("clearResource()", () => {
940940
bfInstanceRefs: [],
941941
bfWorkRefs: [],
942942
}
943+
oldState.entities.localIds.t9zVwg2zO = {
944+
FOLIO: {
945+
stanford: "123456",
946+
},
947+
}
943948

944949
const action = {
945950
type: "CLEAR_RESOURCE",
@@ -952,6 +957,7 @@ describe("clearResource()", () => {
952957
expect(Object.keys(newState.values)).toHaveLength(0)
953958
expect(Object.keys(newState.versions)).toHaveLength(0)
954959
expect(Object.keys(newState.relationships)).toHaveLength(0)
960+
expect(Object.keys(newState.localIds)).toHaveLength(0)
955961
})
956962
})
957963

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { clearLocalIds, setLocalId } from "reducers/transfer"
2+
import { createReducer } from "reducers/index"
3+
4+
const handlers = {
5+
CLEAR_LOCAL_IDS: clearLocalIds,
6+
SET_LOCAL_ID: setLocalId,
7+
}
8+
const reducer = createReducer(handlers)
9+
10+
describe("clearLocalIds", () => {
11+
it("removes local ids for resource", () => {
12+
const oldState = {
13+
localIds: {
14+
abc123: {
15+
FOLIO: {
16+
stanford: "123456",
17+
},
18+
},
19+
def456: {
20+
FOLIO: {
21+
stanford: "234567",
22+
},
23+
},
24+
},
25+
}
26+
const action = {
27+
type: "CLEAR_LOCAL_IDS",
28+
payload: "abc123",
29+
}
30+
31+
const newState = reducer(oldState, action)
32+
expect(newState).toStrictEqual({
33+
localIds: {
34+
def456: {
35+
FOLIO: {
36+
stanford: "234567",
37+
},
38+
},
39+
},
40+
})
41+
})
42+
})
43+
44+
describe("setLocalId", () => {
45+
describe("when resource does not have existing local ids", () => {
46+
it("adds local ids for resource", () => {
47+
const oldState = {
48+
localIds: {},
49+
}
50+
const action = {
51+
type: "SET_LOCAL_ID",
52+
payload: {
53+
resourceKey: "abc123",
54+
target: "FOLIO",
55+
group: "stanford",
56+
localId: "123456",
57+
},
58+
}
59+
60+
const newState = reducer(oldState, action)
61+
expect(newState).toStrictEqual({
62+
localIds: {
63+
abc123: {
64+
FOLIO: {
65+
stanford: "123456",
66+
},
67+
},
68+
},
69+
})
70+
})
71+
})
72+
73+
describe("when resource has existing local ids", () => {
74+
it("appends local ids for resource", () => {
75+
const oldState = {
76+
localIds: {
77+
abc123: {
78+
SYMPHONY: {
79+
stanford: "234567",
80+
},
81+
},
82+
},
83+
}
84+
const action = {
85+
type: "SET_LOCAL_ID",
86+
payload: {
87+
resourceKey: "abc123",
88+
target: "FOLIO",
89+
group: "stanford",
90+
localId: "123456",
91+
},
92+
}
93+
94+
const newState = reducer(oldState, action)
95+
expect(newState).toStrictEqual({
96+
localIds: {
97+
abc123: {
98+
SYMPHONY: {
99+
stanford: "234567",
100+
},
101+
FOLIO: {
102+
stanford: "123456",
103+
},
104+
},
105+
},
106+
})
107+
})
108+
})
109+
})

0 commit comments

Comments
 (0)