368 lines
11 KiB
JavaScript
368 lines
11 KiB
JavaScript
/* eslint-env mocha */
|
|
|
|
const { describe, it, afterEach } = require('mocha')
|
|
const assert = require('assert')
|
|
|
|
const mcVersion = '1.8'
|
|
const registry = require('prismarine-registry')(mcVersion)
|
|
const windows = require('..')(registry)
|
|
const Item = require('prismarine-item')(registry)
|
|
|
|
function getAssertFunctions (slot) {
|
|
return {
|
|
isEmpty: function () {
|
|
assert.equal(slot, null, 'slot is not empty')
|
|
return this
|
|
},
|
|
isNotEmpty: function () {
|
|
assert.notEqual(slot, null, 'slot is empty')
|
|
return this
|
|
},
|
|
hasCount: function (count) {
|
|
this.isNotEmpty()
|
|
assert.equal(slot.count, count, 'slot count doesn\'t match')
|
|
return this
|
|
},
|
|
hasMaxCount: function () {
|
|
this.isNotEmpty()
|
|
assert.equal(slot.count, slot.stackSize, 'slot doesn\'t have max count')
|
|
return this
|
|
},
|
|
hasType: function (type) {
|
|
this.isNotEmpty()
|
|
assert.equal(slot.type, type, `slot doesn't have type ${type}`)
|
|
return this
|
|
}
|
|
}
|
|
}
|
|
|
|
function getActualSlot (slotShorthand, inventoryEnd) {
|
|
// negative values start from the end of the inventory
|
|
return slotShorthand < 0 ? inventoryEnd + slotShorthand : slotShorthand
|
|
}
|
|
|
|
function getSlotShorthand (actualSlot, inventoryEnd) {
|
|
const negativeSlotShorthand = actualSlot - inventoryEnd
|
|
return Math.abs(negativeSlotShorthand) < actualSlot ? negativeSlotShorthand : actualSlot
|
|
}
|
|
|
|
function createTestWindow (type, slotCount = undefined) {
|
|
const testWindow = windows.createWindow(1, 'minecraft:' + type, type, slotCount ?? (type === 'chest' ? 27 : undefined))
|
|
|
|
testWindow.prepareSlot = function (slotShorthand, count, type) {
|
|
testWindow.updateSlot(getActualSlot(slotShorthand, testWindow.inventoryEnd), new Item(type, count))
|
|
|
|
return testWindow
|
|
}
|
|
|
|
testWindow.prepareSelectedItem = function (count, type) {
|
|
testWindow.selectedItem = new Item(type, count)
|
|
|
|
return testWindow
|
|
}
|
|
|
|
testWindow.executeClick = function (mode, mouseButton, slotShorthand, gamemode) {
|
|
const slot = getActualSlot(slotShorthand, testWindow.inventoryEnd)
|
|
const click = {
|
|
slot,
|
|
mouseButton,
|
|
mode,
|
|
windowId: testWindow.id,
|
|
item: slot === -999 ? null : testWindow.slots[slot]
|
|
}
|
|
|
|
testWindow.updatedSlots = []
|
|
testWindow.assertedSlots = []
|
|
const onSlotUpdate = (slot) => {
|
|
slot = +slot
|
|
if (!testWindow.updatedSlots.includes(slot)) {
|
|
testWindow.updatedSlots.push(slot)
|
|
}
|
|
}
|
|
|
|
testWindow.on('updateSlot', onSlotUpdate)
|
|
|
|
const changedSlots = testWindow.acceptClick(click, gamemode)
|
|
|
|
testWindow.removeListener('updateSlot', onSlotUpdate)
|
|
|
|
return changedSlots
|
|
}
|
|
|
|
testWindow.assertSlot = function (slotShorthand) {
|
|
let slot = getActualSlot(slotShorthand, testWindow.inventoryEnd)
|
|
if (!testWindow.assertedSlots.includes(slot)) {
|
|
testWindow.assertedSlots.push(slot)
|
|
}
|
|
slot = testWindow.slots[slot]
|
|
return getAssertFunctions(slot)
|
|
}
|
|
|
|
testWindow.assertSelectedItem = function () {
|
|
return getAssertFunctions(testWindow.selectedItem)
|
|
}
|
|
|
|
return testWindow
|
|
}
|
|
|
|
// item ids
|
|
const firstItem = 1
|
|
const secondItem = 2
|
|
|
|
let testWindow = null
|
|
|
|
afterEach(function () {
|
|
testWindow.updatedSlots.forEach((slot) => {
|
|
if (!testWindow.assertedSlots.includes(slot)) {
|
|
const slotShorthand = getSlotShorthand(slot, testWindow.inventoryEnd)
|
|
assert.fail(`slot ${slotShorthand}${slotShorthand !== slot ? ` (actual: ${slot})` : ''} updated, but has not been asserted`)
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('mode 0 | normal click', () => {
|
|
describe('mouseButton 0', () => {
|
|
it('pickup item', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSlot(0, 64, firstItem)
|
|
|
|
testWindow.executeClick(0, 0, 0)
|
|
|
|
testWindow.assertSlot(0).isEmpty()
|
|
testWindow.assertSelectedItem().hasCount(64).hasType(firstItem)
|
|
})
|
|
})
|
|
|
|
describe('mouseButton 1', () => {
|
|
it('drop one of selected Item into a slot (same item)', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSelectedItem(64, firstItem)
|
|
.prepareSlot(0, 1, firstItem)
|
|
|
|
testWindow.executeClick(0, 1, 0)
|
|
|
|
testWindow.assertSelectedItem().hasCount(63)
|
|
testWindow.assertSlot(0).hasCount(2)
|
|
})
|
|
|
|
it('drop one of selected Item into a slot (empty slot)', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSelectedItem(64, firstItem)
|
|
|
|
testWindow.executeClick(0, 1, 0)
|
|
|
|
testWindow.assertSelectedItem().hasCount(63)
|
|
testWindow.assertSlot(0).hasCount(1)
|
|
})
|
|
|
|
it('drop selected Item into a slot (empty slot)', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSelectedItem(1, firstItem)
|
|
|
|
testWindow.executeClick(0, 1, 0)
|
|
|
|
testWindow.assertSelectedItem().isEmpty()
|
|
testWindow.assertSlot(0).hasCount(1)
|
|
})
|
|
})
|
|
|
|
describe('mouseButton 0', () => {
|
|
it('drop all of selected Item into a slot (almost full with same item)', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSelectedItem(64, firstItem)
|
|
.prepareSlot(0, 60, firstItem)
|
|
|
|
testWindow.executeClick(0, 0, 0)
|
|
|
|
testWindow.assertSelectedItem().hasCount(60)
|
|
testWindow.assertSlot(0).hasCount(64)
|
|
})
|
|
|
|
it('drop selected Item into empty slot', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSelectedItem(1, firstItem)
|
|
|
|
testWindow.executeClick(0, 0, 0)
|
|
|
|
testWindow.assertSelectedItem().isEmpty()
|
|
testWindow.assertSlot(0).isNotEmpty().hasCount(1).hasType(firstItem)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('mode 1 | shift click', () => {
|
|
describe('mouseButton 0', () => {
|
|
it('shift out of chest into inventory', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSlot(0, 64, firstItem)
|
|
|
|
testWindow.executeClick(1, 0, 0)
|
|
|
|
testWindow.assertSlot(0).isEmpty()
|
|
testWindow.assertSlot(-1).isNotEmpty().hasCount(64).hasType(firstItem)
|
|
})
|
|
|
|
it('shift out of inventory into chest', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSlot(-1, 64, firstItem)
|
|
|
|
testWindow.executeClick(1, 0, -1)
|
|
|
|
testWindow.assertSlot(0).isNotEmpty().hasCount(64).hasType(firstItem)
|
|
testWindow.assertSlot(-1).isEmpty()
|
|
})
|
|
|
|
it.skip('shift out of inventory into armor slot (unimplemented)', () => {
|
|
const someBoots = registry.itemsByName.leather_boots.id
|
|
testWindow = createTestWindow('inventory')
|
|
.prepareSlot(-1, 1, someBoots)
|
|
|
|
testWindow.executeClick(1, 0, -1)
|
|
|
|
testWindow.assertSlot(-1).isEmpty()
|
|
// 8 is the slot for boots
|
|
testWindow.assertSlot(8).isNotEmpty().hasType(someBoots).hasCount(1)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('mode 2 | number click', () => {
|
|
describe('mouseButton 0', () => {
|
|
it('from full slot into empty slot', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSlot(0, 64, firstItem)
|
|
|
|
// mouseButton 0 = hotbarStart
|
|
// slot 0 = windowStart
|
|
testWindow.executeClick(2, 0, 0)
|
|
|
|
testWindow.assertSlot(-9).isNotEmpty().hasCount(64).hasType(firstItem)
|
|
testWindow.assertSlot(0).isEmpty()
|
|
})
|
|
|
|
it('from empty slot into full slot', () => {
|
|
testWindow = createTestWindow('chest')
|
|
// -9 = hotbarStart
|
|
.prepareSlot(-9, 64, firstItem)
|
|
|
|
// mouseButton 0 = hotbarStart
|
|
// slot 0 = windowStart
|
|
testWindow.executeClick(2, 0, 0)
|
|
|
|
testWindow.assertSlot(-9).isEmpty()
|
|
testWindow.assertSlot(0).isNotEmpty().hasCount(64).hasType(firstItem)
|
|
})
|
|
|
|
it('from slot with item to slot with same item', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSlot(-9, 32, firstItem)
|
|
.prepareSlot(0, 32, firstItem)
|
|
|
|
testWindow.executeClick(2, 0, 0)
|
|
|
|
if (registry.version['>=']('1.9')) {
|
|
// expect nothing to happen
|
|
testWindow.assertSlot(0).hasCount(32)
|
|
testWindow.assertSlot(-9).hasCount(32)
|
|
} else {
|
|
testWindow.assertSlot(0).isEmpty()
|
|
testWindow.assertSlot(-9).isNotEmpty().hasCount(64).hasType(firstItem)
|
|
testWindow.assertSlot(-8).isEmpty()
|
|
}
|
|
})
|
|
|
|
it('from slot with item to slot with different item', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSlot(0, 64, firstItem)
|
|
.prepareSlot(-1, 64, secondItem)
|
|
|
|
// mouseButton 8 = hotbarEnd
|
|
// slot 0 = windowStart
|
|
testWindow.executeClick(2, 8, 0)
|
|
|
|
if (registry.version['>=']('1.9')) {
|
|
testWindow.assertSlot(0).isNotEmpty().hasCount(64).hasType(secondItem)
|
|
testWindow.assertSlot(-1).isNotEmpty().hasCount(64).hasType(firstItem)
|
|
} else {
|
|
testWindow.assertSlot(0).isEmpty()
|
|
testWindow.assertSlot(-1).isNotEmpty().hasCount(64).hasType(firstItem)
|
|
testWindow.assertSlot(-9).isNotEmpty().hasCount(64).hasType(secondItem)
|
|
}
|
|
})
|
|
|
|
it('same slot click does nothing', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSlot(62, 64, firstItem)
|
|
|
|
// slot 62 = hotbarEnd
|
|
// mouseButton 8 = hotbarEnd
|
|
// slot 0 = windowStart
|
|
testWindow.executeClick(2, 8, 62)
|
|
|
|
// no asserts, test would fail regardless
|
|
// if something did change
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('mode 3 | middle click', () => {
|
|
describe('mouseButton 2', () => {
|
|
it('get stack into selectedItem (gamemode 0)', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSlot(0, 1, firstItem)
|
|
|
|
testWindow.executeClick(3, 2, 0)
|
|
|
|
// expect no change
|
|
testWindow.assertSelectedItem().isEmpty()
|
|
})
|
|
|
|
it('get stack into selectedItem (gamemode 1)', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSlot(0, 1, firstItem)
|
|
|
|
testWindow.executeClick(3, 2, 0, /* gamemode = */1)
|
|
|
|
testWindow.assertSelectedItem().isNotEmpty().hasCount(64).hasType(firstItem)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('mode 4 | drop click', () => {
|
|
describe('mouseButton 0', () => {
|
|
it('drop 1 of stack', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSlot(0, 64, firstItem)
|
|
|
|
testWindow.executeClick(4, 0, 0)
|
|
|
|
testWindow.assertSlot(0).isNotEmpty().hasCount(64 - 1).hasType(firstItem)
|
|
})
|
|
})
|
|
|
|
describe('mouseButton 1', () => {
|
|
it('drop full stack', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSlot(0, 64, firstItem)
|
|
|
|
testWindow.executeClick(4, 1, 0)
|
|
|
|
testWindow.assertSlot(0).isEmpty()
|
|
})
|
|
})
|
|
})
|
|
|
|
it('returning changed slots works', () => {
|
|
testWindow = createTestWindow('chest')
|
|
.prepareSlot(0, 64, firstItem)
|
|
|
|
const changedSlots = testWindow.executeClick(0, 0, 0)
|
|
|
|
testWindow.assertSlot(0).isEmpty()
|
|
testWindow.assertSelectedItem().isNotEmpty()
|
|
|
|
assert.equal(changedSlots.length, 1)
|
|
assert.equal(changedSlots[0], 0)
|
|
// selectedItem isn't included in changedSlots
|
|
})
|