Split up moon counter from the database (#489)
# Description Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. - Create a separate moon counter to track how many moons a user has - This is so we can start a user at a specific counter - Added to the list command a counter to specify how many moons aren't being tracked with the bot #300 ## Type of change Please delete options that are not relevant. - [x] New feature (non-breaking change which adds functionality) # How Has This Been Tested? Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration. # Checklist - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that provide my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules Reviewed-on: #489 Reviewed-by: VylpesTester <tester@vylpes.com> Co-authored-by: Ethan Lane <ethan@vylpes.com> Co-committed-by: Ethan Lane <ethan@vylpes.com>
This commit is contained in:
parent
dfae2fd2e4
commit
93ef8a8ae7
22 changed files with 1218 additions and 21 deletions
|
@ -0,0 +1,8 @@
|
||||||
|
CREATE TABLE `user_setting` (
|
||||||
|
`Id` varchar(255) NOT NULL,
|
||||||
|
`WhenCreated` datetime NOT NULL,
|
||||||
|
`WhenUpdated` datetime NOT NULL,
|
||||||
|
`UserId` varchar(255) NOT NULL,
|
||||||
|
`Key` varchar(255) NOT NULL,
|
||||||
|
`Value` varchar(255) NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE user_setting
|
||||||
|
ADD PRIMARY KEY (Id);
|
|
@ -8,7 +8,7 @@
|
||||||
"clean": "rm -rf node_modules/ dist/",
|
"clean": "rm -rf node_modules/ dist/",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"start": "node ./dist/vylbot",
|
"start": "node ./dist/vylbot",
|
||||||
"test": "jest . --passWithNoTests",
|
"test": "jest",
|
||||||
"db:up": "typeorm migration:run -d dist/database/dataSources/appDataSource.js",
|
"db:up": "typeorm migration:run -d dist/database/dataSources/appDataSource.js",
|
||||||
"db:down": "typeorm migration:revert -d dist/database/dataSources/appDataSource.js",
|
"db:down": "typeorm migration:revert -d dist/database/dataSources/appDataSource.js",
|
||||||
"db:create": "typeorm migration:create ./src/database/migrations",
|
"db:create": "typeorm migration:create ./src/database/migrations",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {ButtonInteraction} from "discord.js";
|
import {ButtonInteraction} from "discord.js";
|
||||||
import {ButtonEvent} from "../type/buttonEvent";
|
import {ButtonEvent} from "../../type/buttonEvent";
|
||||||
import List from "./moons/list";
|
import List from "./moons/list";
|
||||||
|
|
||||||
export default class Moons extends ButtonEvent {
|
export default class Moons extends ButtonEvent {
|
|
@ -1,6 +1,7 @@
|
||||||
import {ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, EmbedBuilder} from "discord.js";
|
import {ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, EmbedBuilder} from "discord.js";
|
||||||
import Moon from "../../database/entities/304276391837302787/Moon";
|
import Moon from "../../../database/entities/304276391837302787/Moon";
|
||||||
import EmbedColours from "../../constants/EmbedColours";
|
import EmbedColours from "../../../constants/EmbedColours";
|
||||||
|
import UserSetting from "../../../database/entities/UserSetting";
|
||||||
|
|
||||||
export default async function List(interaction: ButtonInteraction) {
|
export default async function List(interaction: ButtonInteraction) {
|
||||||
if (!interaction.guild) return;
|
if (!interaction.guild) return;
|
||||||
|
@ -12,26 +13,40 @@ export default async function List(interaction: ButtonInteraction) {
|
||||||
|
|
||||||
const pageNumber = Number(page);
|
const pageNumber = Number(page);
|
||||||
|
|
||||||
const member = interaction.guild.members.cache.find(x => x.user.id == userId);
|
const member = interaction.guild.members.cache.find(x => x.user.id == userId) || await interaction.guild.members.fetch(userId);
|
||||||
|
|
||||||
const pageLength = 10;
|
const pageLength = 10;
|
||||||
|
|
||||||
const moons = await Moon.FetchPaginatedMoonsByUserId(userId, pageLength, pageNumber);
|
const moons = await Moon.FetchPaginatedMoonsByUserId(userId, pageLength, pageNumber);
|
||||||
|
|
||||||
if (!moons || moons[0].length == 0) {
|
if (!moons) {
|
||||||
await interaction.reply(`${member?.user.username ?? "This user"} does not have any moons or page is invalid.`);
|
await interaction.reply(`${member?.user.username ?? "This user"} does not have any moons or page is invalid.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const moonSetting = await UserSetting.FetchOneByKey(userId, "moons");
|
||||||
|
const totalMoons = moonSetting && Number(moonSetting.Value) ? Number(moonSetting.Value) : 0;
|
||||||
|
|
||||||
const totalPages = Math.ceil(moons[1] / pageLength);
|
const totalPages = Math.ceil(moons[1] / pageLength);
|
||||||
|
|
||||||
const description = moons[0].flatMap(x => `**${x.MoonNumber} -** ${x.Description.slice(0, 15)}`);
|
let description = ["*none*"];
|
||||||
|
|
||||||
|
if (moons[0].length > 0) {
|
||||||
|
description = moons[0].flatMap(x => `**${x.MoonNumber} -** ${x.Description.slice(0, 15)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const moonDifference = totalMoons - moons[1];
|
||||||
|
const isLastPage = pageNumber + 1 == totalPages || moons[0].length == 0;
|
||||||
|
|
||||||
|
if (isLastPage && moonDifference > 0) {
|
||||||
|
description.push(`...plus ${moonDifference} more untracked`);
|
||||||
|
}
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setTitle(`${member?.user.username}'s Moons`)
|
.setTitle(`${member.user.username}'s Moons`)
|
||||||
.setColor(EmbedColours.Ok)
|
.setColor(EmbedColours.Ok)
|
||||||
.setDescription(description.join("\n"))
|
.setDescription(description.join("\n"))
|
||||||
.setFooter({ text: `Page ${page + 1} of ${totalPages} · ${moons[1]} moons` });
|
.setFooter({ text: `Page ${pageNumber + 1} of ${totalPages} · ${totalMoons} moons` });
|
||||||
|
|
||||||
const row = new ActionRowBuilder<ButtonBuilder>()
|
const row = new ActionRowBuilder<ButtonBuilder>()
|
||||||
.addComponents(
|
.addComponents(
|
||||||
|
@ -44,7 +59,7 @@ export default async function List(interaction: ButtonInteraction) {
|
||||||
.setCustomId(`moons list ${userId} ${pageNumber + 1}`)
|
.setCustomId(`moons list ${userId} ${pageNumber + 1}`)
|
||||||
.setLabel("Next")
|
.setLabel("Next")
|
||||||
.setStyle(ButtonStyle.Primary)
|
.setStyle(ButtonStyle.Primary)
|
||||||
.setDisabled(pageNumber + 1 == totalPages));
|
.setDisabled(isLastPage));
|
||||||
|
|
||||||
await interaction.update({
|
await interaction.update({
|
||||||
embeds: [ embed ],
|
embeds: [ embed ],
|
|
@ -1,6 +1,7 @@
|
||||||
import {CommandInteraction, EmbedBuilder} from "discord.js";
|
import {CommandInteraction, EmbedBuilder} from "discord.js";
|
||||||
import Moon from "../../../database/entities/304276391837302787/Moon";
|
import Moon from "../../../database/entities/304276391837302787/Moon";
|
||||||
import EmbedColours from "../../../constants/EmbedColours";
|
import EmbedColours from "../../../constants/EmbedColours";
|
||||||
|
import UserSetting from "../../../database/entities/UserSetting";
|
||||||
|
|
||||||
export default async function AddMoon(interaction: CommandInteraction) {
|
export default async function AddMoon(interaction: CommandInteraction) {
|
||||||
const description = interaction.options.get("description", true).value?.toString();
|
const description = interaction.options.get("description", true).value?.toString();
|
||||||
|
@ -10,9 +11,22 @@ export default async function AddMoon(interaction: CommandInteraction) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const moonCount = await Moon.FetchMoonCountByUserId(interaction.user.id);
|
let moonSetting = await UserSetting.FetchOneByKey(interaction.user.id, "moons");
|
||||||
|
const moonCount = moonSetting && Number(moonSetting.Value) ? Number(moonSetting.Value) : 0;
|
||||||
|
|
||||||
const moon = new Moon(moonCount + 1, description, interaction.user.id);
|
if (moonSetting) {
|
||||||
|
moonSetting.UpdateValue(`${moonCount + 1}`);
|
||||||
|
} else {
|
||||||
|
moonSetting = new UserSetting(interaction.user.id, "moons", `${moonCount + 1}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await moonSetting.Save(UserSetting, moonSetting);
|
||||||
|
|
||||||
|
const allMoons = await Moon.FetchMoonCountByUserId(interaction.user.id);
|
||||||
|
|
||||||
|
const moonNumber = allMoons + 1;
|
||||||
|
|
||||||
|
const moon = new Moon(moonNumber, description, interaction.user.id);
|
||||||
|
|
||||||
await moon.Save(Moon, moon);
|
await moon.Save(Moon, moon);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {ActionRowBuilder, ButtonBuilder, ButtonStyle, CommandInteraction, EmbedBuilder} from "discord.js";
|
import {ActionRowBuilder, ButtonBuilder, ButtonStyle, CommandInteraction, EmbedBuilder} from "discord.js";
|
||||||
import Moon from "../../../database/entities/304276391837302787/Moon";
|
import Moon from "../../../database/entities/304276391837302787/Moon";
|
||||||
import EmbedColours from "../../../constants/EmbedColours";
|
import EmbedColours from "../../../constants/EmbedColours";
|
||||||
|
import UserSetting from "../../../database/entities/UserSetting";
|
||||||
|
|
||||||
export default async function ListMoons(interaction: CommandInteraction) {
|
export default async function ListMoons(interaction: CommandInteraction) {
|
||||||
const user = interaction.options.get("user")?.user ?? interaction.user;
|
const user = interaction.options.get("user")?.user ?? interaction.user;
|
||||||
|
@ -10,20 +11,29 @@ export default async function ListMoons(interaction: CommandInteraction) {
|
||||||
|
|
||||||
const moons = await Moon.FetchPaginatedMoonsByUserId(user.id, pageLength, page);
|
const moons = await Moon.FetchPaginatedMoonsByUserId(user.id, pageLength, page);
|
||||||
|
|
||||||
if (!moons || moons[0].length == 0) {
|
const moonSetting = await UserSetting.FetchOneByKey(interaction.user.id, "moons");
|
||||||
await interaction.reply(`${user.username} does not have any moons or page is invalid.`);
|
const totalMoons = moonSetting && Number(moonSetting.Value) ? Number(moonSetting.Value) : 0;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalPages = Math.ceil(moons[1] / pageLength);
|
const totalPages = Math.ceil(moons[1] / pageLength);
|
||||||
|
|
||||||
const description = moons[0].flatMap(x => `**${x.MoonNumber} -** ${x.Description.slice(0, 15)}`);
|
let description = ["*none*"];
|
||||||
|
|
||||||
|
if (moons[0].length > 0) {
|
||||||
|
description = moons[0].flatMap(x => `**${x.MoonNumber} -** ${x.Description.slice(0, 15)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const moonDifference = totalMoons - moons[1];
|
||||||
|
const isLastPage = page + 1 == totalPages || moons[0].length == 0;
|
||||||
|
|
||||||
|
if (isLastPage && moonDifference > 0) {
|
||||||
|
description.push(`...plus ${moonDifference} more untracked`);
|
||||||
|
}
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setTitle(`${user.username}'s Moons`)
|
.setTitle(`${user.username}'s Moons`)
|
||||||
.setColor(EmbedColours.Ok)
|
.setColor(EmbedColours.Ok)
|
||||||
.setDescription(description.join("\n"))
|
.setDescription(description.join("\n"))
|
||||||
.setFooter({ text: `Page ${page + 1} of ${totalPages} · ${moons[1]} moons` });
|
.setFooter({ text: `Page ${page + 1} of ${totalPages} · ${totalMoons} moons` });
|
||||||
|
|
||||||
const row = new ActionRowBuilder<ButtonBuilder>()
|
const row = new ActionRowBuilder<ButtonBuilder>()
|
||||||
.addComponents(
|
.addComponents(
|
||||||
|
@ -36,7 +46,7 @@ export default async function ListMoons(interaction: CommandInteraction) {
|
||||||
.setCustomId(`moons list ${user.id} ${page + 1}`)
|
.setCustomId(`moons list ${user.id} ${page + 1}`)
|
||||||
.setLabel("Next")
|
.setLabel("Next")
|
||||||
.setStyle(ButtonStyle.Primary)
|
.setStyle(ButtonStyle.Primary)
|
||||||
.setDisabled(page + 1 == totalPages));
|
.setDisabled(isLastPage));
|
||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
embeds: [ embed ],
|
embeds: [ embed ],
|
||||||
|
|
35
src/database/entities/UserSetting.ts
Normal file
35
src/database/entities/UserSetting.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import { Column, Entity} from "typeorm";
|
||||||
|
import AppDataSource from "../dataSources/appDataSource";
|
||||||
|
import BaseEntity from "../../contracts/BaseEntity";
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export default class UserSetting extends BaseEntity {
|
||||||
|
constructor(userId: string, key: string, value: string) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.UserId = userId;
|
||||||
|
this.Key = key;
|
||||||
|
this.Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
UserId: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
Key: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
Value: string;
|
||||||
|
|
||||||
|
public UpdateValue(value: string) {
|
||||||
|
this.Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async FetchOneByKey(userId: string, key: string, relations?: string[]): Promise<UserSetting | null> {
|
||||||
|
const repository = AppDataSource.getRepository(UserSetting);
|
||||||
|
|
||||||
|
const single = await repository.findOne({ where: { UserId: userId, Key: key }, relations: relations || {} });
|
||||||
|
|
||||||
|
return single;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
import MigrationHelper from "../../../helpers/MigrationHelper";
|
||||||
|
|
||||||
|
export class CreateUserSetting1727286976268 implements MigrationInterface {
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
MigrationHelper.Up('1727286976268-CreateUserSetting', '3.3.0', [
|
||||||
|
"01-UserSetting",
|
||||||
|
"02-UserSettingKey",
|
||||||
|
], queryRunner);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -43,7 +43,7 @@ import MessageCreate from "./events/MessageEvents/MessageCreate";
|
||||||
|
|
||||||
// Button Event Imports
|
// Button Event Imports
|
||||||
import Verify from "./buttonEvents/verify";
|
import Verify from "./buttonEvents/verify";
|
||||||
import MoonsButtonEvent from "./buttonEvents/moons";
|
import MoonsButtonEvent from "./buttonEvents/304276391837302787/moons";
|
||||||
|
|
||||||
export default class Registry {
|
export default class Registry {
|
||||||
public static RegisterCommands() {
|
public static RegisterCommands() {
|
||||||
|
|
21
tests/buttonEvents/304276391837302787/moons.test.ts
Normal file
21
tests/buttonEvents/304276391837302787/moons.test.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { ButtonInteraction } from "discord.js";
|
||||||
|
import Moons from "../../../src/buttonEvents/304276391837302787/moons";
|
||||||
|
import * as List from "../../../src/buttonEvents/304276391837302787/moons/list";
|
||||||
|
|
||||||
|
describe("GIVEN interaction action is list", () => {
|
||||||
|
const interaction = {
|
||||||
|
customId: "moons list",
|
||||||
|
} as unknown as ButtonInteraction;
|
||||||
|
|
||||||
|
const listSpy = jest.spyOn(List, "default");
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const moons = new Moons();
|
||||||
|
await moons.execute(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT List function to be called", () => {
|
||||||
|
expect(listSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(listSpy).toHaveBeenCalledWith(interaction);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`GIVEN happy flow EXPECT embed to be updated 1`] = `
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"color": 3166394,
|
||||||
|
"description": "**1 -** Test Descriptio",
|
||||||
|
"footer": {
|
||||||
|
"icon_url": undefined,
|
||||||
|
"text": "Page 1 of 1 · 0 moons",
|
||||||
|
},
|
||||||
|
"title": "username's Moons",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`GIVEN happy flow EXPECT row to be updated 1`] = `
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"custom_id": "moons list userId -1",
|
||||||
|
"disabled": true,
|
||||||
|
"emoji": undefined,
|
||||||
|
"label": "Previous",
|
||||||
|
"style": 1,
|
||||||
|
"type": 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"custom_id": "moons list userId 1",
|
||||||
|
"disabled": true,
|
||||||
|
"emoji": undefined,
|
||||||
|
"label": "Next",
|
||||||
|
"style": 1,
|
||||||
|
"type": 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": 1,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
268
tests/buttonEvents/304276391837302787/moons/list.test.ts
Normal file
268
tests/buttonEvents/304276391837302787/moons/list.test.ts
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
import {ActionRowBuilder, ButtonBuilder, ButtonInteraction, EmbedBuilder} from "discord.js";
|
||||||
|
import List from "../../../../src/buttonEvents/304276391837302787/moons/list";
|
||||||
|
import UserSetting from "../../../../src/database/entities/UserSetting";
|
||||||
|
import Moon from "../../../../src/database/entities/304276391837302787/Moon";
|
||||||
|
|
||||||
|
describe("GIVEN happy flow", () => {
|
||||||
|
let updatedWithEmbeds: EmbedBuilder[] | undefined;
|
||||||
|
let updatedWithRows: ActionRowBuilder<ButtonBuilder>[] | undefined;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
guild: {
|
||||||
|
members: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue({
|
||||||
|
user: {
|
||||||
|
username: "username",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
update: jest.fn((options: any) => {
|
||||||
|
updatedWithEmbeds = options.embeds;
|
||||||
|
updatedWithRows = options.components;
|
||||||
|
}),
|
||||||
|
customId: "moons list userId 0",
|
||||||
|
} as unknown as ButtonInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
UserSetting.FetchOneByKey = jest.fn();
|
||||||
|
Moon.FetchPaginatedMoonsByUserId = jest.fn().mockResolvedValue([
|
||||||
|
[
|
||||||
|
{
|
||||||
|
MoonNumber: 1,
|
||||||
|
Description: "Test Description",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT moons to be fetched", () => {
|
||||||
|
expect(Moon.FetchPaginatedMoonsByUserId).toHaveBeenCalledTimes(1);
|
||||||
|
expect(Moon.FetchPaginatedMoonsByUserId).toHaveBeenCalledWith("userId", 10, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT interaction.update to be called", () => {
|
||||||
|
expect(interaction.update).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT embed to be updated", () => {
|
||||||
|
expect(updatedWithEmbeds).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT row to be updated", () => {
|
||||||
|
expect(updatedWithRows).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN interaction.guild is null", () => {
|
||||||
|
const interaction = {
|
||||||
|
guild: null,
|
||||||
|
reply: jest.fn(),
|
||||||
|
update: jest.fn(),
|
||||||
|
} as unknown as ButtonInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
UserSetting.FetchOneByKey = jest.fn();
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT function to return", () => {
|
||||||
|
expect(interaction.reply).not.toHaveBeenCalled();
|
||||||
|
expect(interaction.update).not.toHaveBeenCalled();
|
||||||
|
expect(UserSetting.FetchOneByKey).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN userId parameter is undefined", () => {
|
||||||
|
const interaction = {
|
||||||
|
guild: {},
|
||||||
|
reply: jest.fn(),
|
||||||
|
update: jest.fn(),
|
||||||
|
customId: "moons list",
|
||||||
|
} as unknown as ButtonInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
UserSetting.FetchOneByKey = jest.fn();
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT function to return", () => {
|
||||||
|
expect(interaction.reply).not.toHaveBeenCalled();
|
||||||
|
expect(interaction.update).not.toHaveBeenCalled();
|
||||||
|
expect(UserSetting.FetchOneByKey).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN page parameter is undefined", () => {
|
||||||
|
const interaction = {
|
||||||
|
guild: {},
|
||||||
|
reply: jest.fn(),
|
||||||
|
update: jest.fn(),
|
||||||
|
customId: "moons list userId",
|
||||||
|
} as unknown as ButtonInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
UserSetting.FetchOneByKey = jest.fn();
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT function to return", () => {
|
||||||
|
expect(interaction.reply).not.toHaveBeenCalled();
|
||||||
|
expect(interaction.update).not.toHaveBeenCalled();
|
||||||
|
expect(UserSetting.FetchOneByKey).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN no moons for the user is returned", () => {
|
||||||
|
const interaction = {
|
||||||
|
guild: {
|
||||||
|
members: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue({
|
||||||
|
user: {
|
||||||
|
username: "username",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
update: jest.fn(),
|
||||||
|
customId: "moons list userId 0",
|
||||||
|
} as unknown as ButtonInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
UserSetting.FetchOneByKey = jest.fn();
|
||||||
|
Moon.FetchPaginatedMoonsByUserId = jest.fn().mockResolvedValue(undefined)
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT moons function to be called", () => {
|
||||||
|
expect(Moon.FetchPaginatedMoonsByUserId).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT error replied", () => {
|
||||||
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
||||||
|
expect(interaction.reply).toHaveBeenCalledWith("username does not have any moons or page is invalid.");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN member is not in cache", () => {
|
||||||
|
const interaction = {
|
||||||
|
guild: {
|
||||||
|
members: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue(undefined),
|
||||||
|
},
|
||||||
|
fetch: jest.fn().mockResolvedValue({
|
||||||
|
user: {
|
||||||
|
username: "username",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
update: jest.fn(),
|
||||||
|
customId: "moons list userId 0",
|
||||||
|
} as unknown as ButtonInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
UserSetting.FetchOneByKey = jest.fn();
|
||||||
|
Moon.FetchPaginatedMoonsByUserId = jest.fn().mockResolvedValue(undefined)
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT API to be called", () => {
|
||||||
|
expect(interaction.guild?.members.fetch).toHaveBeenCalledTimes(1);
|
||||||
|
expect(interaction.guild?.members.fetch).toHaveBeenCalledWith("userId");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT error replied with username", () => {
|
||||||
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
||||||
|
expect(interaction.reply).toHaveBeenCalledWith("username does not have any moons or page is invalid.");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN member can not be found", () => {
|
||||||
|
const interaction = {
|
||||||
|
guild: {
|
||||||
|
members: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue(undefined),
|
||||||
|
},
|
||||||
|
fetch: jest.fn().mockResolvedValue(undefined),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
update: jest.fn(),
|
||||||
|
customId: "moons list userId 0",
|
||||||
|
} as unknown as ButtonInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
UserSetting.FetchOneByKey = jest.fn();
|
||||||
|
Moon.FetchPaginatedMoonsByUserId = jest.fn().mockResolvedValue(undefined)
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT API to be called", () => {
|
||||||
|
expect(interaction.guild?.members.fetch).toHaveBeenCalledTimes(1);
|
||||||
|
expect(interaction.guild?.members.fetch).toHaveBeenCalledWith("userId");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT error replied with username", () => {
|
||||||
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
||||||
|
expect(interaction.reply).toHaveBeenCalledWith("This user does not have any moons or page is invalid.");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN no moons on current page", () => {
|
||||||
|
let updatedWith: EmbedBuilder[] | undefined;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
guild: {
|
||||||
|
members: {
|
||||||
|
cache: {
|
||||||
|
find: jest.fn().mockReturnValue({
|
||||||
|
user: {
|
||||||
|
username: "username",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
update: jest.fn((options: any) => {
|
||||||
|
updatedWith = options.embeds;
|
||||||
|
}),
|
||||||
|
customId: "moons list userId 0",
|
||||||
|
} as unknown as ButtonInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
UserSetting.FetchOneByKey = jest.fn();
|
||||||
|
Moon.FetchPaginatedMoonsByUserId = jest.fn().mockResolvedValue([
|
||||||
|
[],
|
||||||
|
0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT description to say so", () => {
|
||||||
|
expect(updatedWith).toBeDefined();
|
||||||
|
expect(updatedWith?.length).toBe(1);
|
||||||
|
|
||||||
|
expect(updatedWith![0].data.description).toBe("*none*");
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,69 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`constructor EXPECT CommandBuilder to be defined correctly 1`] = `
|
||||||
|
{
|
||||||
|
"contexts": undefined,
|
||||||
|
"default_member_permissions": undefined,
|
||||||
|
"default_permission": undefined,
|
||||||
|
"description": "View and create moons",
|
||||||
|
"description_localizations": undefined,
|
||||||
|
"dm_permission": undefined,
|
||||||
|
"integration_types": undefined,
|
||||||
|
"name": "moons",
|
||||||
|
"name_localizations": undefined,
|
||||||
|
"nsfw": undefined,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"description": "List moons you have obtained",
|
||||||
|
"description_localizations": undefined,
|
||||||
|
"name": "list",
|
||||||
|
"name_localizations": undefined,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"description": "The user to view (Defaults to yourself)",
|
||||||
|
"description_localizations": undefined,
|
||||||
|
"name": "user",
|
||||||
|
"name_localizations": undefined,
|
||||||
|
"required": false,
|
||||||
|
"type": 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"autocomplete": undefined,
|
||||||
|
"choices": undefined,
|
||||||
|
"description": "The page to start with",
|
||||||
|
"description_localizations": undefined,
|
||||||
|
"max_value": undefined,
|
||||||
|
"min_value": undefined,
|
||||||
|
"name": "page",
|
||||||
|
"name_localizations": undefined,
|
||||||
|
"required": false,
|
||||||
|
"type": 10,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Add a moon to your count!",
|
||||||
|
"description_localizations": undefined,
|
||||||
|
"name": "add",
|
||||||
|
"name_localizations": undefined,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"autocomplete": undefined,
|
||||||
|
"choices": undefined,
|
||||||
|
"description": "What deserved a moon?",
|
||||||
|
"description_localizations": undefined,
|
||||||
|
"max_length": undefined,
|
||||||
|
"min_length": undefined,
|
||||||
|
"name": "description",
|
||||||
|
"name_localizations": undefined,
|
||||||
|
"required": true,
|
||||||
|
"type": 3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": 1,
|
||||||
|
}
|
||||||
|
`;
|
113
tests/commands/304276391837302787/moons.test.ts
Normal file
113
tests/commands/304276391837302787/moons.test.ts
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
import { ChatInputCommandInteraction, CommandInteraction } from "discord.js";
|
||||||
|
import Moons from "../../../src/commands/304276391837302787/moons";
|
||||||
|
import * as AddMoon from "../../../src/commands/304276391837302787/moons/add";
|
||||||
|
import * as ListMoons from "../../../src/commands/304276391837302787/moons/list";
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.resetAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("constructor", () => {
|
||||||
|
let moons: Moons;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
moons = new Moons();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT CommandBuilder to be defined correctly", () => {
|
||||||
|
expect(moons.CommandBuilder).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("execute", () => {
|
||||||
|
describe("GIVEN interaction is not a chat input command", () => {
|
||||||
|
const moons = new Moons();
|
||||||
|
|
||||||
|
let interaction: CommandInteraction;
|
||||||
|
|
||||||
|
let listMoonsSpy: jest.SpyInstance;
|
||||||
|
let addMoonSpy: jest.SpyInstance;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
listMoonsSpy = jest.spyOn(ListMoons, "default");
|
||||||
|
addMoonSpy = jest.spyOn(AddMoon, "default");
|
||||||
|
|
||||||
|
interaction = {
|
||||||
|
isChatInputCommand: jest.fn().mockReturnValue(false),
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
await moons.execute(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT interaction.isChatInputCommand to have been called", () => {
|
||||||
|
expect(interaction.isChatInputCommand).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT nothing to happen", () => {
|
||||||
|
expect(listMoonsSpy).not.toHaveBeenCalled();
|
||||||
|
expect(addMoonSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN interaction subcommand is list", () => {
|
||||||
|
const moons = new Moons();
|
||||||
|
|
||||||
|
let interaction: ChatInputCommandInteraction;
|
||||||
|
|
||||||
|
let listMoonsSpy: jest.SpyInstance;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
listMoonsSpy = jest.spyOn(ListMoons, "default")
|
||||||
|
.mockImplementation();
|
||||||
|
|
||||||
|
interaction = {
|
||||||
|
isChatInputCommand: jest.fn().mockReturnValue(true),
|
||||||
|
options: {
|
||||||
|
getSubcommand: jest.fn().mockReturnValue("list"),
|
||||||
|
},
|
||||||
|
} as unknown as ChatInputCommandInteraction;
|
||||||
|
|
||||||
|
await moons.execute(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT interaction.options.getSubcommand to have been called", () => {
|
||||||
|
expect(interaction.options.getSubcommand).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT ListMoons to be called", () => {
|
||||||
|
expect(listMoonsSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(listMoonsSpy).toHaveBeenCalledWith(interaction);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN interaction subcommand is add", () => {
|
||||||
|
const moons = new Moons();
|
||||||
|
|
||||||
|
let interaction: ChatInputCommandInteraction;
|
||||||
|
|
||||||
|
let addMoonSpy: jest.SpyInstance;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
addMoonSpy = jest.spyOn(AddMoon, "default")
|
||||||
|
.mockImplementation();
|
||||||
|
|
||||||
|
interaction = {
|
||||||
|
isChatInputCommand: jest.fn().mockReturnValue(true),
|
||||||
|
options: {
|
||||||
|
getSubcommand: jest.fn().mockReturnValue("add"),
|
||||||
|
},
|
||||||
|
} as unknown as ChatInputCommandInteraction;
|
||||||
|
|
||||||
|
await moons.execute(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT interaction.options.getSubcommand to have been called", () => {
|
||||||
|
expect(interaction.options.getSubcommand).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT AddMoon to be called", () => {
|
||||||
|
expect(addMoonSpy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(addMoonSpy).toHaveBeenCalledWith(interaction);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`GIVEN happy flow EXPECT embed to be replied 1`] = `
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"color": 5294200,
|
||||||
|
"description": "**2 -** Test Description",
|
||||||
|
"thumbnail": {
|
||||||
|
"url": "https://cdn.discordapp.com/emojis/374131312182689793.webp?size=96&quality=lossless",
|
||||||
|
},
|
||||||
|
"title": "undefined Got A Moon!",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`GIVEN happy flow EXPECT moon to be saved 1`] = `
|
||||||
|
{
|
||||||
|
"Description": "Test Description",
|
||||||
|
"Id": Any<String>,
|
||||||
|
"MoonNumber": 2,
|
||||||
|
"UserId": "userId",
|
||||||
|
"WhenCreated": Any<Date>,
|
||||||
|
"WhenUpdated": Any<Date>,
|
||||||
|
}
|
||||||
|
`;
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`GIVEN happy flow EXPECT interaction to be replied 1`] = `
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"custom_id": "moons list userId -1",
|
||||||
|
"disabled": true,
|
||||||
|
"emoji": undefined,
|
||||||
|
"label": "Previous",
|
||||||
|
"style": 1,
|
||||||
|
"type": 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"custom_id": "moons list userId 01",
|
||||||
|
"disabled": true,
|
||||||
|
"emoji": undefined,
|
||||||
|
"label": "Next",
|
||||||
|
"style": 1,
|
||||||
|
"type": 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"embeds": [
|
||||||
|
{
|
||||||
|
"color": 3166394,
|
||||||
|
"description": "**1 -** Test Descriptio",
|
||||||
|
"footer": {
|
||||||
|
"icon_url": undefined,
|
||||||
|
"text": "Page 01 of 1 · 0 moons",
|
||||||
|
},
|
||||||
|
"title": "undefined's Moons",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`;
|
194
tests/commands/304276391837302787/moons/add.test.ts
Normal file
194
tests/commands/304276391837302787/moons/add.test.ts
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
import { CommandInteraction, EmbedBuilder } from "discord.js";
|
||||||
|
import AddMoon from "../../../../src/commands/304276391837302787/moons/add";
|
||||||
|
import Moon from "../../../../src/database/entities/304276391837302787/Moon";
|
||||||
|
import UserSetting from "../../../../src/database/entities/UserSetting";
|
||||||
|
|
||||||
|
describe("GIVEN happy flow", () => {
|
||||||
|
let repliedWithEmbed: EmbedBuilder[] | undefined;
|
||||||
|
let savedMoon: Moon | undefined;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
reply: jest.fn((options: any) => {
|
||||||
|
repliedWithEmbed = options.embeds;
|
||||||
|
}),
|
||||||
|
options: {
|
||||||
|
get: jest.fn()
|
||||||
|
.mockReturnValueOnce({
|
||||||
|
value: "Test Description",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
id: "userId",
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
const userSetting = {
|
||||||
|
Value: 1,
|
||||||
|
UpdateValue: jest.fn(),
|
||||||
|
Save: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
Moon.FetchMoonCountByUserId = jest.fn().mockResolvedValue(1);
|
||||||
|
Moon.prototype.Save = jest.fn().mockImplementation((_, entity: Moon) => {
|
||||||
|
savedMoon = entity;
|
||||||
|
});
|
||||||
|
|
||||||
|
UserSetting.FetchOneByKey = jest.fn().mockResolvedValue(userSetting);
|
||||||
|
|
||||||
|
await AddMoon(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT description option to have been fetched", () => {
|
||||||
|
expect(interaction.options.get).toHaveBeenCalledTimes(1);
|
||||||
|
expect(interaction.options.get).toHaveBeenCalledWith("description", true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT UserSetting to have been fetched", () => {
|
||||||
|
expect(UserSetting.FetchOneByKey).toHaveBeenCalledTimes(1);
|
||||||
|
expect(UserSetting.FetchOneByKey).toHaveBeenCalledWith("userId", "moons");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT moonCount to be updated +1", () => {
|
||||||
|
expect(userSetting.UpdateValue).toHaveBeenCalledTimes(1);
|
||||||
|
expect(userSetting.UpdateValue).toHaveBeenCalledWith("2");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT setting to be saved", () => {
|
||||||
|
expect(userSetting.Save).toHaveBeenCalledTimes(1);
|
||||||
|
expect(userSetting.Save).toHaveBeenCalledWith(UserSetting, userSetting);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT moon to be saved", () => {
|
||||||
|
expect(Moon.prototype.Save).toHaveBeenCalledTimes(1);
|
||||||
|
expect(Moon.prototype.Save).toHaveBeenCalledWith(Moon, expect.any(Moon));
|
||||||
|
|
||||||
|
expect(savedMoon).toBeDefined();
|
||||||
|
expect(savedMoon).toMatchSnapshot({
|
||||||
|
Id: expect.any(String),
|
||||||
|
WhenCreated: expect.any(Date),
|
||||||
|
WhenUpdated: expect.any(Date),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT embed to be replied", () => {
|
||||||
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
expect(repliedWithEmbed).toBeDefined();
|
||||||
|
expect(repliedWithEmbed).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN description is null", () => {
|
||||||
|
const interaction = {
|
||||||
|
reply: jest.fn(),
|
||||||
|
options: {
|
||||||
|
get: jest.fn().mockReturnValue({
|
||||||
|
value: null,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await AddMoon(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT error replied", () => {
|
||||||
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
||||||
|
expect(interaction.reply).toHaveBeenCalledWith("Name must be less than 255 characters!");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN description is greater than 255 characters", () => {
|
||||||
|
const optionGet = jest.fn();
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
reply: jest.fn(),
|
||||||
|
options: {
|
||||||
|
get: optionGet,
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
let longString = "";
|
||||||
|
|
||||||
|
for (let i = 0; i < 30; i++) {
|
||||||
|
longString += "1234567890";
|
||||||
|
}
|
||||||
|
|
||||||
|
optionGet.mockReturnValue({
|
||||||
|
value: longString,
|
||||||
|
});
|
||||||
|
|
||||||
|
await AddMoon(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT error replied", () => {
|
||||||
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
||||||
|
expect(interaction.reply).toHaveBeenCalledWith("Name must be less than 255 characters!");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN moon count setting exists", () => {
|
||||||
|
const moonSetting = {
|
||||||
|
Value: "1",
|
||||||
|
UpdateValue: jest.fn(),
|
||||||
|
Save: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
reply: jest.fn(),
|
||||||
|
options: {
|
||||||
|
get: jest.fn().mockReturnValue({
|
||||||
|
value: "Test Description",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
id: "userId",
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
UserSetting.FetchOneByKey = jest.fn().mockResolvedValue(moonSetting);
|
||||||
|
|
||||||
|
await AddMoon(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT existing entity to be updated", () => {
|
||||||
|
expect(moonSetting.UpdateValue).toHaveBeenCalledTimes(1);
|
||||||
|
expect(moonSetting.UpdateValue).toHaveBeenCalledWith("2");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN moon count setting does not exist", () => {
|
||||||
|
let savedSetting: UserSetting | undefined;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
reply: jest.fn(),
|
||||||
|
options: {
|
||||||
|
get: jest.fn().mockReturnValue({
|
||||||
|
value: "Test Description",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
id: "userId",
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
UserSetting.FetchOneByKey = jest.fn().mockResolvedValue(null);
|
||||||
|
UserSetting.prototype.Save = jest.fn().mockImplementation((_, setting: UserSetting) => {
|
||||||
|
savedSetting = setting;
|
||||||
|
});
|
||||||
|
|
||||||
|
await AddMoon(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT new entity to be created", () => {
|
||||||
|
// Expect the entity to have the new entity.
|
||||||
|
// Probably the best way we can really imply a new entity
|
||||||
|
// that I can think of
|
||||||
|
expect(savedSetting).toBeDefined();
|
||||||
|
expect(savedSetting?.Value).toBe("1");
|
||||||
|
});
|
||||||
|
});
|
249
tests/commands/304276391837302787/moons/list.test.ts
Normal file
249
tests/commands/304276391837302787/moons/list.test.ts
Normal file
|
@ -0,0 +1,249 @@
|
||||||
|
import { ActionRowBuilder, APIEmbed, ButtonBuilder, CommandInteraction, EmbedBuilder, InteractionReplyOptions } from "discord.js";
|
||||||
|
import List from "../../../../src/commands/304276391837302787/moons/list";
|
||||||
|
import Moon from "../../../../src/database/entities/304276391837302787/Moon";
|
||||||
|
import UserSetting from "../../../../src/database/entities/UserSetting";
|
||||||
|
|
||||||
|
describe("GIVEN happy flow", () => {
|
||||||
|
let repliedWith: InteractionReplyOptions | undefined;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
reply: jest.fn((options) => {
|
||||||
|
repliedWith = options;
|
||||||
|
}),
|
||||||
|
options: {
|
||||||
|
get: jest.fn()
|
||||||
|
.mockReturnValueOnce(undefined) // User
|
||||||
|
.mockReturnValue({
|
||||||
|
value: "0",
|
||||||
|
}), // Page
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
id: "userId",
|
||||||
|
}
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
Moon.FetchPaginatedMoonsByUserId = jest.fn().mockResolvedValue([
|
||||||
|
[
|
||||||
|
{
|
||||||
|
MoonNumber: 1,
|
||||||
|
Description: "Test Description",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
UserSetting.FetchOneByKey = jest.fn().mockResolvedValue({
|
||||||
|
Value: "0",
|
||||||
|
});
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT interaction to be replied", () => {
|
||||||
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
||||||
|
expect(repliedWith).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN moons returned is empty", () => {
|
||||||
|
let repliedWith: InteractionReplyOptions | undefined;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
reply: jest.fn((options) => {
|
||||||
|
repliedWith = options;
|
||||||
|
}),
|
||||||
|
options: {
|
||||||
|
get: jest.fn()
|
||||||
|
.mockReturnValueOnce(undefined) // User
|
||||||
|
.mockReturnValue({
|
||||||
|
value: "0",
|
||||||
|
}), // Page
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
id: "userId",
|
||||||
|
}
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
Moon.FetchPaginatedMoonsByUserId = jest.fn().mockResolvedValue([
|
||||||
|
[],
|
||||||
|
0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
UserSetting.FetchOneByKey = jest.fn().mockResolvedValue({
|
||||||
|
Value: "0",
|
||||||
|
});
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT none description", () => {
|
||||||
|
expect(repliedWith).toBeDefined();
|
||||||
|
|
||||||
|
expect(repliedWith!.embeds).toBeDefined();
|
||||||
|
expect(repliedWith!.embeds!.length).toBe(1);
|
||||||
|
|
||||||
|
const repliedWithEmbed = repliedWith!.embeds![0] as EmbedBuilder;
|
||||||
|
|
||||||
|
expect(repliedWithEmbed.data.description).toBe("*none*");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN it is the first page", () => {
|
||||||
|
let repliedWith: InteractionReplyOptions | undefined;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
reply: jest.fn((options) => {
|
||||||
|
repliedWith = options;
|
||||||
|
}),
|
||||||
|
options: {
|
||||||
|
get: jest.fn()
|
||||||
|
.mockReturnValueOnce(undefined) // User
|
||||||
|
.mockReturnValue({
|
||||||
|
value: "0",
|
||||||
|
}), // Page
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
id: "userId",
|
||||||
|
}
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
Moon.FetchPaginatedMoonsByUserId = jest.fn().mockResolvedValue([
|
||||||
|
[
|
||||||
|
{
|
||||||
|
MoonNumber: 1,
|
||||||
|
Description: "Test Description",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
UserSetting.FetchOneByKey = jest.fn().mockResolvedValue({
|
||||||
|
Value: "0",
|
||||||
|
});
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT Previous button to be disabled", () => {
|
||||||
|
expect(repliedWith).toBeDefined();
|
||||||
|
|
||||||
|
expect(repliedWith!.components).toBeDefined();
|
||||||
|
expect(repliedWith!.components!.length).toBe(1);
|
||||||
|
|
||||||
|
const repliedWithRow = repliedWith!.components![0] as ActionRowBuilder<ButtonBuilder>;
|
||||||
|
|
||||||
|
expect(repliedWithRow.components[0].data.disabled).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN it is the last page", () => {
|
||||||
|
let repliedWith: InteractionReplyOptions | undefined;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
reply: jest.fn((options) => {
|
||||||
|
repliedWith = options;
|
||||||
|
}),
|
||||||
|
options: {
|
||||||
|
get: jest.fn()
|
||||||
|
.mockReturnValueOnce(undefined) // User
|
||||||
|
.mockReturnValue({
|
||||||
|
value: "0",
|
||||||
|
}), // Page
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
id: "userId",
|
||||||
|
}
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
Moon.FetchPaginatedMoonsByUserId = jest.fn().mockResolvedValue([
|
||||||
|
[
|
||||||
|
{
|
||||||
|
MoonNumber: 1,
|
||||||
|
Description: "Test Description",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
UserSetting.FetchOneByKey = jest.fn().mockResolvedValue({
|
||||||
|
Value: "0",
|
||||||
|
});
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT Next button to be disabled", () => {
|
||||||
|
expect(repliedWith).toBeDefined();
|
||||||
|
|
||||||
|
expect(repliedWith!.components).toBeDefined();
|
||||||
|
expect(repliedWith!.components!.length).toBe(1);
|
||||||
|
|
||||||
|
const repliedWithRow = repliedWith!.components![0] as ActionRowBuilder<ButtonBuilder>;
|
||||||
|
|
||||||
|
expect(repliedWithRow.components[1].data.disabled).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN moon count is greater than the amount of moons in the database", () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
UserSetting.FetchOneByKey = jest.fn().mockResolvedValue({
|
||||||
|
Value: "2",
|
||||||
|
});
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT untracked counter to be shown", () => {
|
||||||
|
const repliedWithEmbed = repliedWith!.embeds![0] as EmbedBuilder;
|
||||||
|
|
||||||
|
expect(repliedWithEmbed.data.description).toContain("...plus 1 more untracked");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("GIVEN moon count is empty", () => {
|
||||||
|
let repliedWith: InteractionReplyOptions | undefined;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
reply: jest.fn((options) => {
|
||||||
|
repliedWith = options;
|
||||||
|
}),
|
||||||
|
options: {
|
||||||
|
get: jest.fn()
|
||||||
|
.mockReturnValueOnce(undefined) // User
|
||||||
|
.mockReturnValue({
|
||||||
|
value: "0",
|
||||||
|
}), // Page
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
id: "userId",
|
||||||
|
}
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
Moon.FetchPaginatedMoonsByUserId = jest.fn().mockResolvedValue([
|
||||||
|
[],
|
||||||
|
0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
UserSetting.FetchOneByKey = jest.fn().mockResolvedValue({
|
||||||
|
Value: "0",
|
||||||
|
});
|
||||||
|
|
||||||
|
await List(interaction);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT Next button to be disabled", () => {
|
||||||
|
expect(repliedWith).toBeDefined();
|
||||||
|
|
||||||
|
expect(repliedWith!.components).toBeDefined();
|
||||||
|
expect(repliedWith!.components!.length).toBe(1);
|
||||||
|
|
||||||
|
const repliedWithRow = repliedWith!.components![0] as ActionRowBuilder<ButtonBuilder>;
|
||||||
|
|
||||||
|
expect(repliedWithRow.components[1].data.disabled).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
65
tests/database/entites/UserSetting.test.ts
Normal file
65
tests/database/entites/UserSetting.test.ts
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import AppDataSource from "../../../src/database/dataSources/appDataSource";
|
||||||
|
import UserSetting from "../../../src/database/entities/UserSetting";
|
||||||
|
|
||||||
|
describe("constructor", () => {
|
||||||
|
let userSetting: UserSetting;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
userSetting = new UserSetting("userId", "key", "value");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT settings to be configured", () => {
|
||||||
|
expect(userSetting).toMatchSnapshot({
|
||||||
|
Id: expect.any(String),
|
||||||
|
WhenCreated: expect.any(Date),
|
||||||
|
WhenUpdated: expect.any(Date),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("UpdateValue", () => {
|
||||||
|
let userSetting: UserSetting;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
userSetting = new UserSetting("userId", "key", "value");
|
||||||
|
|
||||||
|
userSetting.UpdateValue("newValue");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT value to be updated", () => {
|
||||||
|
expect(userSetting.Value).toBe("newValue");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("FetchOneByKey", () => {
|
||||||
|
let result: UserSetting | null;
|
||||||
|
let userSetting: UserSetting;
|
||||||
|
|
||||||
|
let findOneMock: jest.Mock;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
userSetting = new UserSetting("userId", "key", "value");
|
||||||
|
|
||||||
|
findOneMock = jest.fn().mockResolvedValue(userSetting);
|
||||||
|
|
||||||
|
AppDataSource.getRepository = jest.fn().mockReturnValue({
|
||||||
|
findOne: findOneMock,
|
||||||
|
});
|
||||||
|
|
||||||
|
result = await UserSetting.FetchOneByKey("userId", "key");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT getRepository to have been called", () => {
|
||||||
|
expect(AppDataSource.getRepository).toHaveBeenCalledTimes(1);
|
||||||
|
expect(AppDataSource.getRepository).toHaveBeenCalledWith(UserSetting);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("EXPECT repository.findOne to have been called", () => {
|
||||||
|
expect(findOneMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(findOneMock).toHaveBeenCalledWith({ where: { UserId: "userId", Key: "key" }, relations: {}});
|
||||||
|
})
|
||||||
|
|
||||||
|
test("EXPECT single entity returned", () => {
|
||||||
|
expect(result).toBe(userSetting);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`constructor EXPECT settings to be configured 1`] = `
|
||||||
|
{
|
||||||
|
"Id": Any<String>,
|
||||||
|
"Key": "key",
|
||||||
|
"UserId": "userId",
|
||||||
|
"Value": "value",
|
||||||
|
"WhenCreated": Any<Date>,
|
||||||
|
"WhenUpdated": Any<Date>,
|
||||||
|
}
|
||||||
|
`;
|
Loading…
Reference in a new issue