Skip to content

Commit

Permalink
[misc] fix linting issues and missing jsdoc
Browse files Browse the repository at this point in the history
  • Loading branch information
mrhyde committed May 29, 2024
1 parent d81410f commit 8e15bca
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ rules:
'@typescript-eslint/non-nullable-type-assertion-style': 'off'
'@typescript-eslint/promise-function-async': 'off'
'@typescript-eslint/strict-boolean-expressions': ['error', allowNullableObject: true]
'@typescript-eslint/space-before-function-paren': 'off'
'@typescript-eslint/member-delimiter-style': 'off'
'import/no-default-export': 'error'
'import/no-unresolved': 'error'
'jsdoc/check-param-names': ['error', checkDestructured: false]
Expand Down
14 changes: 13 additions & 1 deletion source/dice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const compute = ({ quantity, separator, sides, modifier }: RollSpec): num
/**
* A factory function for creating dice rolls.
*
* @param notation The notation string representing the type of roll to create, e.g. "2d6+3".
* @param notation - The notation string representing the type of roll to create, e.g. "2d6+3".
* @returns An object with methods and properties representing the result of a dice roll.
*/
export const Roll = (notation: string): RollResult => {
Expand All @@ -39,15 +39,27 @@ export const Roll = (notation: string): RollResult => {

return {
values: rolls,
/**
* The sum of all dice rolls.
*/
get sum(): number {
return rolls.reduce(sum, 0)
},
/**
* The min value of all dice rolls.
*/
get min(): number {
return rolls.sort(sortAsc)[0] ?? 0
},
/**
* The max value of all dice rolls.
*/
get max(): number {
return rolls.sort(sortDesc)[0] ?? 0
},
/**
* Is any of the dice rolls a critical hit or a critical failure.
*/
get isCritical(): boolean {
return rolls.includes(1) || rolls.includes(20)
}
Expand Down
23 changes: 22 additions & 1 deletion source/dice.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ describe('dice', () => {

describe('roll', () => {
it('should return a number when given a valid dice string with only one die', () => {
expect.assertions(3)

const spy = vi.spyOn(parser, 'parse')

const shape = '1d6'
Expand All @@ -19,21 +21,27 @@ describe('dice', () => {
})

it('should return a number when given a valid dice string with multiple dice', () => {
expect.assertions(1)

const shape = '2d10'
expect(typeof roll(shape)).toBe('number')
})

it('should correctly sum the rolls', () => {
expect.assertions(2)

// mock the rand function to return known values
const spy = vi.spyOn(random, 'rand').mockReturnValueOnce(3).mockReturnValueOnce(5)

const result = roll('2d6')

expect(result).toStrictEqual(8)
expect(result).toBe(8)
expect(spy).toHaveBeenCalledTimes(2)
})

it('should change min value when given `z` as separator', () => {
expect.assertions(2)

// mock the rand function to return known values
const spy = vi.spyOn(random, 'rand')
const shape = '3z8'
Expand All @@ -43,6 +51,8 @@ describe('dice', () => {
})

it('should throw an error when given an invalid dice string', () => {
expect.assertions(1)

const shape = 'invalid'
expect(() => roll(shape)).toThrow(`Invalid dice notation '${shape}'`)
})
Expand All @@ -51,6 +61,8 @@ describe('dice', () => {
describe('roll factory', () => {
describe('sum', () => {
it('should correctly calculate the sum of the rolls', () => {
expect.assertions(2)

const roll = Roll('2d6')
expect(roll.sum).toBeGreaterThanOrEqual(2)
expect(roll.sum).toBeLessThanOrEqual(12)
Expand All @@ -59,6 +71,8 @@ describe('dice', () => {

describe('min', () => {
it('should correctly identify the minimum roll', () => {
expect.assertions(1)

vi.spyOn(random, 'rand')
.mockReturnValueOnce(1)
.mockReturnValueOnce(2)
Expand All @@ -72,6 +86,8 @@ describe('dice', () => {

describe('max', () => {
it('should correctly identify the maximum roll', () => {
expect.assertions(1)

vi.spyOn(random, 'rand')
.mockReturnValueOnce(1)
.mockReturnValueOnce(2)
Expand All @@ -85,20 +101,25 @@ describe('dice', () => {

describe('isCritical', () => {
it('should return true if a critical roll was made with nat 20', () => {
expect.assertions(1)

vi.spyOn(random, 'rand').mockReturnValueOnce(20)

const roll = Roll('1d20')
expect(roll.isCritical).toBeTruthy()
})

it('should return true if a critical roll was made with nat 1', () => {
expect.assertions(1)

vi.spyOn(random, 'rand').mockReturnValueOnce(1)

const roll = Roll('1d20')
expect(roll.isCritical).toBeTruthy()
})

it('should return false if a critical roll was not made', () => {
expect.assertions(1)
vi.spyOn(random, 'rand').mockReturnValueOnce(2)

const roll = Roll('1d20')
Expand Down
1 change: 0 additions & 1 deletion source/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const regex = /^(?:(?<quantity>\d+)|)(?<separator>d|z)(?<sides>[1-9]\d*)(?<modif
* @param notation - The dice notation string to be parsed. Ex: "2d6", "3d8", "1d20".
* @throws Throws an error when it is not possible to parse the dice shape string.
*/

export const parse = (notation: string): RollSpec => {
const match = regex.exec(notation.toLowerCase())
if (match?.groups == null) {
Expand Down
8 changes: 6 additions & 2 deletions source/parser.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,20 @@ describe('parse', () => {
]

it.each(validInputs)(
`should return the correct Dice object when passed a valid shape - '%j'`,
"should return the correct Dice object when passed a valid shape - '%j'",
({ input, expected }) => {
expect.assertions(1)

const actual = parse(input)
expect(actual).toStrictEqual(expected)
}
)

const invalidInputs = ['', 'd', '4', '1dx', 'xd1', '-2d10', 'd-1', '2d0', '2d6d', '3d+2']

it.each(invalidInputs)(`should throw an error when passed an invalid shape - '%s'`, (input) => {
it.each(invalidInputs)("should throw an error when passed an invalid shape - '%s'", (input) => {
expect.assertions(1)

expect(() => parse(input)).toThrow(`Invalid dice notation '${input}'`)
})
})
23 changes: 23 additions & 0 deletions source/utils/array.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
/**
* A compare function that can be used with Array.prototype.sort to sort an array of numbers in ascending order.
*
* @param a - The first number for comparison.
* @param b - The second number for comparison.
* @returns The difference between `a` and `b`.
*/
export const sortAsc = (a: number, b: number): number => a - b

/**
* A compare function that can be used with Array.prototype.sort to sort an array of numbers in descending order.
*
* @param a - The first number for comparison.
* @param b - The second number for comparison.
* @returns The difference between `b` and `a`.
*/
export const sortDesc = (a: number, b: number): number => b - a

/**
* Calculates the sum of two numbers.
*
* @param accumulator - The initial value of the sum.
* @param value - The value to be added to the sum.
* @returns The sum of the accumulator and the value.
*/
export const sum = (accumulator: number, value: number): number => accumulator + value

0 comments on commit 8e15bca

Please sign in to comment.