Skip to content

Commit

Permalink
feat: multiple drag end definition on action
Browse files Browse the repository at this point in the history
  • Loading branch information
Zielak committed Jun 1, 2023
1 parent 94bc650 commit 8b296af
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 73 deletions.
32 changes: 16 additions & 16 deletions packages/server/src/__test__/commandsManagerDrag.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ describe("drag action is kept in pending", () => {
end: { interaction: () => [{ type: "pile" }], conditions, command },
})
jest.spyOn(dragAnyToPile.start, "getCommand")
jest.spyOn(dragAnyToPile.end, "getCommand")
jest.spyOn(dragAnyToPile.end[0], "getCommand")
dragAnyToLine = defineDragAction<State>({
name: "OnlyHandToLine",
start: { interaction: () => "*", conditions, command },
end: { interaction: () => [{ type: "line" }], conditions, command },
})
jest.spyOn(dragAnyToLine.start, "getCommand")
jest.spyOn(dragAnyToLine.end, "getCommand")
jest.spyOn(dragAnyToLine.end[0], "getCommand")

state = new State()
room = new TestRoom()
Expand Down Expand Up @@ -106,8 +106,8 @@ describe("drag action is kept in pending", () => {

expect(manager.pendingActions.get(clientID)).toBeUndefined()

expect(dragAnyToPile.end.getCommand).toHaveBeenCalled()
expect(dragAnyToLine.end.getCommand).not.toHaveBeenCalled()
expect(dragAnyToPile.end[0].getCommand).toHaveBeenCalled()
expect(dragAnyToLine.end[0].getCommand).not.toHaveBeenCalled()
})

it("starts with A, and tries to end with B", async () => {
Expand Down Expand Up @@ -144,8 +144,8 @@ describe("drag action is kept in pending", () => {
)
).rejects.toThrow()

expect(dragAnyToPile.end.getCommand).not.toHaveBeenCalled()
expect(dragAnyToLine.end.getCommand).not.toHaveBeenCalled()
expect(dragAnyToPile.end[0].getCommand).not.toHaveBeenCalled()
expect(dragAnyToLine.end[0].getCommand).not.toHaveBeenCalled()

expect(manager.pendingActions.get(clientID)).toBeUndefined()
})
Expand All @@ -171,7 +171,7 @@ describe("start on one action and end in another shouldn't be allowed", () => {
end: { interaction: () => [{ type: "hand" }], conditions, command },
})
jest.spyOn(dragHandToHand.start, "getCommand")
jest.spyOn(dragHandToHand.end, "getCommand")
jest.spyOn(dragHandToHand.end[0], "getCommand")

dragLineToLine = defineDragAction<State>({
name: "OnlyLineToLine",
Expand All @@ -183,7 +183,7 @@ describe("start on one action and end in another shouldn't be allowed", () => {
end: { interaction: () => [{ type: "line" }], conditions, command },
})
jest.spyOn(dragLineToLine.start, "getCommand")
jest.spyOn(dragLineToLine.end, "getCommand")
jest.spyOn(dragLineToLine.end[0], "getCommand")

state = new State()
room = new TestRoom()
Expand Down Expand Up @@ -237,8 +237,8 @@ describe("start on one action and end in another shouldn't be allowed", () => {
)
).resolves.toBe(true)

expect(dragHandToHand.end.getCommand).toHaveBeenCalled()
expect(dragLineToLine.end.getCommand).not.toHaveBeenCalled()
expect(dragHandToHand.end[0].getCommand).toHaveBeenCalled()
expect(dragLineToLine.end[0].getCommand).not.toHaveBeenCalled()

expect(manager.pendingActions.get(clientID)).toBeUndefined()
})
Expand Down Expand Up @@ -275,8 +275,8 @@ describe("start on one action and end in another shouldn't be allowed", () => {
)
).rejects.toThrow()

expect(dragHandToHand.end.getCommand).not.toHaveBeenCalled()
expect(dragLineToLine.end.getCommand).not.toHaveBeenCalled()
expect(dragHandToHand.end[0].getCommand).not.toHaveBeenCalled()
expect(dragLineToLine.end[0].getCommand).not.toHaveBeenCalled()
})
})

Expand Down Expand Up @@ -316,7 +316,7 @@ describe("dragging into not allowed place", () => {
end: { interaction: () => [{ type: "hand" }], conditions, command },
})
jest.spyOn(dragToHand.start, "getCommand")
jest.spyOn(dragToHand.end, "getCommand")
jest.spyOn(dragToHand.end[0], "getCommand")

room.possibleActions = [dragToHand]
manager = new CommandsManager(room)
Expand Down Expand Up @@ -355,7 +355,7 @@ describe("dragging into not allowed place", () => {
)
).rejects.toThrow()

expect(dragToHand.end.getCommand).not.toHaveBeenCalled()
expect(dragToHand.end[0].getCommand).not.toHaveBeenCalled()
expect(manager.pendingActions.get(clientID)).toBeUndefined()
})
})
Expand All @@ -374,7 +374,7 @@ describe("dragging into not allowed place", () => {
},
})
jest.spyOn(dragToHand.start, "getCommand")
jest.spyOn(dragToHand.end, "getCommand")
jest.spyOn(dragToHand.end[0], "getCommand")

room.possibleActions = [dragToHand]
manager = new CommandsManager(room)
Expand Down Expand Up @@ -413,7 +413,7 @@ describe("dragging into not allowed place", () => {
)
).rejects.toThrow()

expect(dragToHand.end.getCommand).not.toHaveBeenCalled()
expect(dragToHand.end[0].getCommand).not.toHaveBeenCalled()
expect(manager.pendingActions.get(clientID)).toBeUndefined()
})
})
Expand Down
68 changes: 40 additions & 28 deletions packages/server/src/actions/drag/__test__/dragAction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ describe("DragActionDefinition", () => {
let messageContext: ClientMessageContext<State>
let player: Player
let def: DragActionDefinition<State>
let context: CollectionContext<DragContext>
let context: CollectionContext<DragContext<State>>

const timestamp = 123

Expand Down Expand Up @@ -183,25 +183,25 @@ describe("DragActionDefinition", () => {
start: { interaction, conditions },
end: { interaction, conditions, command },
})
context = prepareActionContext<DragContext>(def)
context = prepareActionContext<DragContext<State>>(def)
})

describe("checkPrerequisites", () => {
it("checks only start", () => {
def.start.checkPrerequisites = jest.fn()
def.end.checkPrerequisites = jest.fn()
def.end[0].checkPrerequisites = jest.fn()

messageContext = prepareConditionsContext(state, message)

def.checkPrerequisites(messageContext, context)

expect(def.start.checkPrerequisites).toHaveBeenCalledWith(messageContext)
expect(def.end.checkPrerequisites).not.toHaveBeenCalled()
expect(def.end[0].checkPrerequisites).not.toHaveBeenCalled()
})

it("checks only end if pending", () => {
def.start.checkPrerequisites = jest.fn()
def.end.checkPrerequisites = jest.fn()
def.end[0].checkPrerequisites = jest.fn()

context.pending = true

Expand All @@ -210,7 +210,7 @@ describe("DragActionDefinition", () => {
def.checkPrerequisites(messageContext, context)

expect(def.start.checkPrerequisites).not.toHaveBeenCalled()
expect(def.end.checkPrerequisites).toHaveBeenCalledWith(messageContext)
expect(def.end[0].checkPrerequisites).toHaveBeenCalledWith(messageContext)
})

describe("start", () => {
Expand Down Expand Up @@ -248,27 +248,27 @@ describe("DragActionDefinition", () => {
...message,
interaction: "dragend",
})
expect(def.end.checkPrerequisites(messageContext)).toBe(true)
expect(def.end[0].checkPrerequisites(messageContext)).toBe(true)
})

it("accepts tap only if player has initiated tap-dragging", () => {
message.interaction = "tap"
player.isTapDragging = true
messageContext = prepareConditionsContext(state, message)

expect(def.end.checkPrerequisites(messageContext)).toBe(true)
expect(def.end[0].checkPrerequisites(messageContext)).toBe(true)

player.isTapDragging = false

expect(def.end.checkPrerequisites(messageContext)).toBe(false)
expect(def.end[0].checkPrerequisites(messageContext)).toBe(false)
})

it("doesn't accept dragstart", () => {
messageContext = prepareConditionsContext(state, {
...message,
interaction: "dragstart",
})
expect(def.end.checkPrerequisites(messageContext)).toBe(false)
expect(def.end[0].checkPrerequisites(messageContext)).toBe(false)
})
})
})
Expand All @@ -288,64 +288,70 @@ describe("DragActionDefinition", () => {

it("calls conditions of start on dragstart", () => {
def.start.checkConditions = jest.fn()
def.end.checkConditions = jest.fn()
def.end[0].checkConditions = jest.fn()

messageContext = prepareConditionsContext(state, {
...message,
interaction: "dragstart",
})

context.successfulEnd.add(def.end[0])
def.checkConditions(con as any, messageContext, context)

expect(def.start.checkConditions).toHaveBeenCalledWith(
con,
messageContext
)
expect(def.end.checkConditions).not.toHaveBeenCalled()
expect(def.end[0].checkConditions).not.toHaveBeenCalled()

expect(context.finished).toBe(false)
})

it("calls conditions of start on tap start", () => {
def.start.checkConditions = jest.fn()
def.end.checkConditions = jest.fn()
def.end[0].checkConditions = jest.fn()

player.isTapDragging = false
messageContext = prepareConditionsContext(state, {
...message,
interaction: "tap",
})

context.successfulEnd.add(def.end[0])
def.checkConditions(con as any, messageContext, context)

expect(def.start.checkConditions).toHaveBeenCalledWith(
con,
messageContext
)
expect(def.end.checkConditions).not.toHaveBeenCalled()
expect(def.end[0].checkConditions).not.toHaveBeenCalled()

expect(context.finished).toBe(false)
})

it("calls conditions of end on dragend", () => {
def.start.checkConditions = jest.fn()
def.end.checkConditions = jest.fn()
def.end[0].checkConditions = jest.fn()

context.pending = true
messageContext = prepareConditionsContext(state, {
...message,
interaction: "dragend",
})

context.successfulEnd.add(def.end[0])
def.checkConditions(con as any, messageContext, context)

expect(def.end.checkConditions).toHaveBeenCalledWith(con, messageContext)
expect(def.end[0].checkConditions).toHaveBeenCalledWith(
con,
messageContext
)
expect(def.start.checkConditions).not.toHaveBeenCalled()
})

it("calls conditions of end on tap end", () => {
def.start.checkConditions = jest.fn()
def.end.checkConditions = jest.fn()
def.end[0].checkConditions = jest.fn()

context.pending = true
player.isTapDragging = true
Expand All @@ -354,17 +360,21 @@ describe("DragActionDefinition", () => {
interaction: "tap",
})

context.successfulEnd.add(def.end[0])
def.checkConditions(con as any, messageContext, context)

expect(def.end.checkConditions).toHaveBeenCalledWith(con, messageContext)
expect(def.end[0].checkConditions).toHaveBeenCalledWith(
con,
messageContext
)
expect(def.start.checkConditions).not.toHaveBeenCalled()
})
})

describe("getCommand", () => {
it("calls command of start on dragstart", () => {
def.start.getCommand = jest.fn()
def.end.getCommand = jest.fn()
def.end[0].getCommand = jest.fn()

messageContext = prepareConditionsContext(state, {
...message,
Expand All @@ -374,7 +384,7 @@ describe("DragActionDefinition", () => {
def.getCommand(messageContext, context)

expect(def.start.getCommand).toHaveBeenCalledWith(messageContext)
expect(def.end.getCommand).not.toHaveBeenCalled()
expect(def.end[0].getCommand).not.toHaveBeenCalled()

expect(context.finished).toBe(false)
})
Expand All @@ -387,7 +397,7 @@ describe("DragActionDefinition", () => {
})

jest.spyOn(def.start, "getCommand")
def.end.getCommand = jest.fn()
def.end[0].getCommand = jest.fn()

player.dragStartEntity = fromEntity as any
messageContext = prepareConditionsContext(state, {
Expand All @@ -398,14 +408,14 @@ describe("DragActionDefinition", () => {
def.getCommand(messageContext, context)

expect(def.start.getCommand).toHaveBeenCalledWith(messageContext)
expect(def.end.getCommand).not.toHaveBeenCalled()
expect(def.end[0].getCommand).not.toHaveBeenCalled()

expect(context.finished).toBe(false)
})

it("calls command of start on tap start", () => {
def.start.getCommand = jest.fn()
def.end.getCommand = jest.fn()
def.end[0].getCommand = jest.fn()

player.isTapDragging = false
messageContext = prepareConditionsContext(state, {
Expand All @@ -416,32 +426,33 @@ describe("DragActionDefinition", () => {
def.getCommand(messageContext, context)

expect(def.start.getCommand).toHaveBeenCalledWith(messageContext)
expect(def.end.getCommand).not.toHaveBeenCalled()
expect(def.end[0].getCommand).not.toHaveBeenCalled()

expect(context.finished).toBe(false)
})

it("calls command of end on dragend", () => {
def.start.getCommand = jest.fn()
def.end.getCommand = jest.fn()
def.end[0].getCommand = jest.fn()

context.pending = true
messageContext = prepareConditionsContext(state, {
...message,
interaction: "dragend",
})

context.successfulEnd.add(def.end[0])
def.getCommand(messageContext, context)

expect(def.end.getCommand).toHaveBeenCalledWith(messageContext)
expect(def.end[0].getCommand).toHaveBeenCalledWith(messageContext)
expect(def.start.getCommand).not.toHaveBeenCalled()

expect(context.finished).toBe(true)
})

it("calls command of end on tap end", () => {
def.start.getCommand = jest.fn()
def.end.getCommand = jest.fn()
def.end[0].getCommand = jest.fn()

context.pending = true
player.isTapDragging = true
Expand All @@ -450,9 +461,10 @@ describe("DragActionDefinition", () => {
interaction: "tap",
})

context.successfulEnd.add(def.end[0])
def.getCommand(messageContext, context)

expect(def.end.getCommand).toHaveBeenCalledWith(messageContext)
expect(def.end[0].getCommand).toHaveBeenCalledWith(messageContext)
expect(def.start.getCommand).not.toHaveBeenCalled()

expect(context.finished).toBe(true)
Expand Down
7 changes: 6 additions & 1 deletion packages/server/src/actions/drag/context.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { type State } from "../../state/state.js"

import { type DragEndActionDefinition } from "./end.js"

/**
* @ignore
*/
export type DragContext = {
export type DragContext<S extends State> = {
finished: boolean
prerequisitesFailed: boolean
conditionsFailed: boolean
successfulEnd: Set<DragEndActionDefinition<S>>
}

0 comments on commit 8b296af

Please sign in to comment.