Skip to content

Commit

Permalink
feat(gethelditems): add getHeldItems method
Browse files Browse the repository at this point in the history
  • Loading branch information
trezy committed Aug 30, 2021
1 parent ebd8fda commit 95c316a
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 22 deletions.
1 change: 1 addition & 0 deletions .mocharc.cjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = {
parallel: true,
recursive: true,
require: ['test/setup.js']
}
Binary file not shown.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
},
"dependencies": {
"@pokebag/pokemon-unite-data": "^1.1.1",
"chai-as-promised": "^7.1.1",
"dirname-filename-esm": "^1.1.1",
"lodash-es": "^4.17.21"
}
Expand Down
49 changes: 49 additions & 0 deletions src/api/getEntities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Local imports
import { getDirectory } from './getDirectory.js'
import { getFile } from './getFile.js'





/**
* Returns data for entities
*
* @param {Object} options An object containing filtering options
* @param {string[]} [options.ids] Array of entity IDs to be returned
* @param {string} [options.patch] Maximum patch version to return data for
* @param {string} options.type Entity type to return
*
* @returns {Promise<Object[]>} An array containing data for each item requested
*/
export async function getEntities(options) {
const {
patch,
type,
} = options
let { ids } = options

// If no ids provided, get all entities
if (typeof ids === 'undefined') {
ids = await getDirectory(type, patch)
}

// If ids isn't an array of strings, throw an error
if (!Array.isArray(ids) || ids.some(item => typeof item !== 'string')) {
throw new TypeError(`ids must be an array of strings`)
}

// Convert IDs to filenames
ids = ids.map(id => {
if (!id.endsWith('.json')) {
return `${id}.json`
}

return id
})

// If ids is an array of strings, get
return Promise.all(ids.map(filename => {
return getFile(`${type}/${filename}`)
}))
}
4 changes: 2 additions & 2 deletions src/api/getFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import { patchReduce } from '../helpers/patchReduce.js'
* @param {string} file Relative path to a file inside of the dataset
* @param {string} version The version of the dataset to use
*
* @returns {Promise<Record<string,*>>} An array containing a compiled version of the contents of the requested directory
* @returns {Promise<Object>} An array containing a compiled version of the contents of the requested directory
*/
export async function getFile(file, version = 'latest') {
export async function getFile(file, version = 'latest') {
const PATCHES = await getPatches()
const FILTERED_PATCHES = await filterPatches(PATCHES, version)

Expand Down
1 change: 1 addition & 0 deletions src/api/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { getPatches } from './getPatches.js'
export { getDirectory } from './getDirectory.js'
export { getEntities } from './getEntities.js'
export { getFile } from './getFile.js'
30 changes: 29 additions & 1 deletion src/getHeldItems.js
Original file line number Diff line number Diff line change
@@ -1 +1,29 @@
export async function getHeldItems() {}
// Local imports
import './models/HeldItem.js'
import { getEntities } from './api/index.js'





/**
* Returns data for held items
*
* @param {Object} [options] An object containing filtering options
* @param {string[]} [options.items] Array of item IDs to be returned
* @param {string} [options.patch] Maximum patch version to return data for
*
* @returns {Promise<HeldItem[]>} An array containing data for each item requested
*/
export async function getHeldItems(options = {}) {
const {
items,
patch,
} = options

return getEntities({
ids: items,
patch,
type: 'held-items',
})
}
33 changes: 33 additions & 0 deletions src/models/HeldItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/** Held item stat
* @typedef {Object} HeldItemStat
* @property {string} [formula] A formula that can be evaluated to determine the value of this item's stat, usually based on the item's level
* @property {'flat'|'percentage'} [type] Whether the result of the stat's formula should be interpreted as a flat value or a percentage
*/

/** Held item stats
* @typedef {Object} HeldItemStats
* @property {HeldItemStat} [attack] Describes how this item modifies the Pokémon's attack damage.
* @property {HeldItemStat} [attackSpeed] Describes how this item modifies the Pokémon's attack speed.
* @property {HeldItemStat} [cooldown] Describes how this item modifies the Pokémon's attack cooldown.
* @property {HeldItemStat} [critDamage] Describes how this item modifies the Pokémon's damage when it scores a critical hit.
* @property {HeldItemStat} [critRate] Describes how this item modifies the Pokémon's likelihood of scoring a critical hit.
* @property {HeldItemStat} [defense] Describes how this item modifies the Pokémon's defense.
* @property {HeldItemStat} [hp] Describes how this item modifies the Pokémon's hit points.
* @property {HeldItemStat} [hpRecovery] Describes how this item modifies the Pokémon's hit point recovery speed.
* @property {HeldItemStat} [movementSpeed] Describes how this item modifies the Pokémon's movement speed.
* @property {HeldItemStat} [spAttack] Describes how this item modifies the Pokémon's special attack damage.
* @property {HeldItemStat} [spDefense] Describes how this item modifies the Pokémon's special defense.
* @property {HeldItemStat} [uniteMoveChargeRate] Describes how this item modifies the Pokémon's Unite move charge rate.
*/

/**
* A held item
* @typedef {Object} HeldItem
* @property {string} displayName The display name of the item
* @property {string} description A description of the item
* @property {['attack'|'defense'|'other'|'score']} tags An array of tags that apply to the
* @property {Object} special An object containing information about the passive bonus provided by the item
* @property {string} special.description A template string for the description of the item's passive bonus
* @property {Object} special.boons An object representing the item's passive bonus and how it changes with the item's level
* @property {HeldItemStats} stats An object containing information about how the item affects the holding Pokémon's stats
*/
54 changes: 54 additions & 0 deletions test/api/getEntities.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Module imports
import { expect } from 'chai'





// Local imports
import {
mockData,
useMockFS,
} from '../test-helpers/useMockFS.js'
import { getEntities } from '../../src/api/getEntities.js'





describe('getEntities', function () {
useMockFS()

it('is a function', () => {
expect(getEntities).to.be.a('function')
})

it('given an array of IDs, returns each entity in the array', async () => {
const IDS = ['aeos-cookie', 'buddy-barrier']
const ENTITY_DATA = IDS.map(id => mockData.heldItems[id])
const RESPONSE = await getEntities({
ids: IDS,
type: 'held-items',
})

expect(RESPONSE).to.be.an('array')
RESPONSE.forEach((item, index) => {
expect(item).to.deep.equal(ENTITY_DATA[index])
})
})

it('given anything other than an array, throws an error', async () => {
const errorStuff = [TypeError, 'First argument must be an array of strings.']

// @ts-ignore
expect(getEntities(undefined)).to.eventually.throw(...errorStuff)
// @ts-ignore
expect(getEntities(null)).to.eventually.throw(...errorStuff)
// @ts-ignore
expect(getEntities(456)).to.eventually.throw(...errorStuff)
// @ts-ignore
expect(getEntities({})).to.eventually.throw(...errorStuff)
// @ts-ignore
expect(getEntities('mr-mime')).to.eventually.throw(...errorStuff)
})
})
39 changes: 20 additions & 19 deletions test/getHeldItems.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,33 @@ describe('getHeldItems', function () {
})

it('given no arguments, returns all held items', async () => {
const HELD_ITEMS_ARRAY = Object.values(mockData.heldItems)
const RESPONSE = await getHeldItems()

expect(RESPONSE).to.have.ordered.members(mockData.heldItems)
})

it('given an item ID, returns the held item', async () => {
const HELD_ITEM_ID = 'eject-button'
const EJECT_BUTTON_DATA = mockData.heldItems[HELD_ITEM_ID]
const RESPONSE = await getHeldItems(HELD_ITEM_ID)

expect(RESPONSE).to.be.an('object')
expect(RESPONSE).to.deep.equal(EJECT_BUTTON_DATA)
expect(RESPONSE).to.deep.equal(HELD_ITEMS_ARRAY)
})

it('given an array of item IDs, returns each held item in the array', async () => {
const HELD_ITEM_IDS = ['eject-button', 'x-attack']
const HELD_ITEM_DATA = [
mockData.heldItems[HELD_ITEM_IDS[0]],
mockData.heldItems[HELD_ITEM_IDS[1]],
]
const RESPONSE = await getHeldItems(HELD_ITEM_IDS)
const HELD_ITEM_IDS = ['aeos-cookie', 'buddy-barrier']
const HELD_ITEM_DATA = HELD_ITEM_IDS.map(id => mockData.heldItems[id])
const RESPONSE = await getHeldItems({ items: HELD_ITEM_IDS })

expect(RESPONSE).to.be.an('array')
RESPONSE.forEach(item => {
expect(item).to.be.an('object')
expect(item).to.deep.equal(HELD_ITEM_DATA)
RESPONSE.forEach((item, index) => {
expect(item).to.deep.equal(HELD_ITEM_DATA[index])
})
})

it('given anything other than an array, throws an error', async () => {
const errorStuff = [TypeError, 'First argument must be an array of strings.']

// @ts-ignore
expect(getHeldItems(null)).to.eventually.throw(...errorStuff)
// @ts-ignore
expect(getHeldItems(456)).to.eventually.throw(...errorStuff)
// @ts-ignore
expect(getHeldItems({})).to.eventually.throw(...errorStuff)
// @ts-ignore
expect(getHeldItems('mr-mime')).to.eventually.throw(...errorStuff)
})
})
12 changes: 12 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1464,6 +1464,7 @@ __metadata:
"@pokebag/pokemon-unite-data": ^1.1.1
all-contributors-cli: ^6.20.0
chai: ^4.3.4
chai-as-promised: ^7.1.1
coveralls: ^3.1.1
dirname-filename-esm: ^1.1.1
jsdoc: ^3.6.7
Expand Down Expand Up @@ -2276,6 +2277,17 @@ __metadata:
languageName: node
linkType: hard

"chai-as-promised@npm:^7.1.1":
version: 7.1.1
resolution: "chai-as-promised@npm:7.1.1"
dependencies:
check-error: ^1.0.2
peerDependencies:
chai: ">= 2.1.2 < 5"
checksum: 7262868a5b51a12af4e432838ddf97a893109266a505808e1868ba63a12de7ee1166e9d43b5c501a190c377c1b11ecb9ff8e093c89f097ad96c397e8ec0f8d6a
languageName: node
linkType: hard

"chai@npm:^4.3.4":
version: 4.3.4
resolution: "chai@npm:4.3.4"
Expand Down

0 comments on commit 95c316a

Please sign in to comment.