Skip to content

Commit

Permalink
Expose functionality via the gql layer
Browse files Browse the repository at this point in the history
It's all in, I think. I added a new test to cover name uniqueness but no
doubt more cases will come up.
  • Loading branch information
CocoisBuggy committed Nov 28, 2024
1 parent ffd4363 commit 79511ee
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 8 deletions.
23 changes: 23 additions & 0 deletions src/__tests__/areas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,28 @@ describe('areas API', () => {

expect(response.statusCode).toBe(200)
})

it('should allow calling of the setAreaParent gql endpoint.', async () => {
const testArea = await areas.addArea(muuid.from(userUuid), 'A Rolling Stone', usa.metadata.area_id)

const response = await queryAPI({
query: `
mutation SetAreaParent($area: ID!, $newParent: ID!) {
setAreaParent(area: $area, newParent: $newParent) {
areaName
area_name
}
}
`,
operationName: 'SetAreaParent',
userUuid,
app,
// Move it to canada
variables: { area: testArea.metadata.area_id, newParent: ca.metadata.area_id }
})

console.log(response.body)
expect(response.statusCode).toBe(200)
})
})
})
18 changes: 18 additions & 0 deletions src/graphql/area/AreaMutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { AreaType } from '../../db/AreaTypes.js'
import { ContextWithAuth } from '../../types.js'
import type MutableAreaDataSource from '../../model/MutableAreaDataSource.js'
import { BulkImportInputType, BulkImportResultType } from '../../db/BulkImportTypes.js'
import { UserInputError } from 'apollo-server-core'

const AreaMutations = {

Expand Down Expand Up @@ -70,6 +71,23 @@ const AreaMutations = {
)
},

setAreaParent: async (_, { input }, { dataSources, user }: ContextWithAuth): Promise<AreaType | null> => {
const { areas } = dataSources

if (user?.uuid == null) throw new UserInputError('Missing user uuid')
if (input?.area == null) throw new UserInputError('Missing area uuid')
if (input?.newParent == null) throw new UserInputError('Missing area new parent uuid')

const areaUuid = muuid.from(input.uuid)
const newParentUuid = muuid.from(input.newParent)

return await areas.setAreaParent(
user.uuid,
areaUuid,
newParentUuid
)
},

updateAreasSortingOrder: async (_, { input }, { dataSources, user }: ContextWithAuth): Promise<string[] | null> => {
const { areas } = dataSources

Expand Down
18 changes: 18 additions & 0 deletions src/graphql/schema/AreaEdit.gql
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@ type Mutation {
"""
addArea(input: AreaInput): Area

"""
Move an area from one parent to another.
When areas are created, an initial parent must be assigned. this is to prevent a buildup of floating orphan
nodes that haven't been organized. Nevertheless, you may find that an area and its children may need to be
re-organized. This could happen for any number of reasons, but when it does need to happen you will need to
tap this mutation to update the areas parent.
When you migrate an area, it will move (along with all the sub-areas inside it) to the targeted area.
The best way to conceptualize this is as a directory, so the usual rules will apply. If you could not
create the area as a child of the target (for example, because a name is already taken), then you should
not reasonably be able to move the area into this new parent.
Caveats
- This mutation does not affect countries
"""
setAreaParent(area: ID!, newParent: ID!): Area

"""
Update area attributes
"""
Expand Down
3 changes: 3 additions & 0 deletions src/model/MutableAreaDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,9 @@ export default class MutableAreaDataSource extends AreaDataSource {
throw new AreaStructureError('CIRCULAR STRUCTURE: The requested parent is already a descendant, and so cannot also be a parent.')
}

// the name of the area being moved into this area must be unique in its new context
await this.validateUniqueAreaName(area.area_name, nextParent)

// By this point we are satisfied that there are no obvious reasons to reject this request, so we can begin saving
// and producing effects in the context of this transaction.
area.parent = nextParent._id
Expand Down
28 changes: 20 additions & 8 deletions src/model/__tests__/MutableAreaDataSource.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,14 +199,26 @@ describe("Test area mutations", () => {
}))

describe("cases for changing an areas parent",() => {
test('Can update an areas parent reference', async () => addArea()
.then(parent => addArea(undefined, { parent }))
.then(async area => {
let otherArea = await addArea()
await areas.setAreaParent(testUser, area.metadata.area_id, otherArea.metadata.area_id)
expect(area.parent).toBeDefined()
expect(area.parent!.equals(otherArea._id))
}))
test('Can update an areas parent reference', async () => addArea()
.then(parent => addArea(undefined, { parent }))
.then(async area => {
let otherArea = await addArea()
await areas.setAreaParent(testUser, area.metadata.area_id, otherArea.metadata.area_id)
expect(area.parent).toBeDefined()
expect(area.parent!.equals(otherArea._id))
}))

test('Updating an area will not produce duplicate named children in the target', async () => addArea()
.then(async parent => addArea(undefined, { parent }))
.then(async area => {
let otherArea = await addArea()
// put a duplicate name inside otherArea
addArea(area.area_name, { parent: otherArea })

await expect(
() => areas.setAreaParent(testUser, area.metadata.area_id, otherArea.metadata.area_id)
).rejects.toThrowError(UserInputError)
}))

test('Updating an areas parents reference to the one already specified should throw', async () => addArea()
.then(async parent => [ await addArea(undefined, { parent }), parent])
Expand Down

0 comments on commit 79511ee

Please sign in to comment.