From 53a1cd0184ef7bbb7509f229866ffa6ab1b14190 Mon Sep 17 00:00:00 2001 From: DasithKuruppu Date: Wed, 28 Sep 2022 22:07:43 +0530 Subject: [PATCH] feat(unit_test_coverage #13): Unit tests added --- bot/configs/index.ts | 6 + bot/configs/tests/index.spec.ts | 28 ++++ .../templates/neverwinter/classesList.ts | 157 ++++++++++++++---- .../neverwinter/tests/classesList.spec.ts | 28 ++++ docs/README.md | 94 +++++++++++ 5 files changed, 283 insertions(+), 30 deletions(-) create mode 100644 bot/configs/tests/index.spec.ts create mode 100644 bot/embeds/templates/neverwinter/tests/classesList.spec.ts create mode 100644 docs/README.md diff --git a/bot/configs/index.ts b/bot/configs/index.ts index 3ce007e..d712ba3 100644 --- a/bot/configs/index.ts +++ b/bot/configs/index.ts @@ -1,3 +1,9 @@ +export enum availableEnvVariables { + DISCORD_APPLICATION_ID = "DISCORD_APPLICATION_ID", + DISCORD_TOKEN = "DISCORD_TOKEN", + DISCORD_SERVER_ID = "DISCORD_SERVER_ID" +} + export const getEnvironmentVariables = () => { const discordApplicationID = process.env.DISCORD_APPLICATION_ID as string; const discordBotToken = process.env.DISCORD_TOKEN as string; diff --git a/bot/configs/tests/index.spec.ts b/bot/configs/tests/index.spec.ts new file mode 100644 index 0000000..b58da82 --- /dev/null +++ b/bot/configs/tests/index.spec.ts @@ -0,0 +1,28 @@ +import { beforeEach, describe, expect, test, vi } from "vitest"; +import { getEnvironmentVariables, availableEnvVariables } from "../index"; + +describe("Configs", () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.restoreAllMocks(); + vi.resetModules(); + }); + + test("getEnvironmentVariables", () => { + vi.stubGlobal("process", { + ...process, + env: { + ...process.env, + [availableEnvVariables.DISCORD_APPLICATION_ID]: "mockTest", + [availableEnvVariables.DISCORD_SERVER_ID]: "mockTest", + [availableEnvVariables.DISCORD_TOKEN]: "mockTest", + }, + }); + const envVariables = getEnvironmentVariables(); + expect(envVariables).toStrictEqual({ + discordApplicationID: "mockTest", + discordBotToken: "mockTest", + discordServerId: "mockTest", + }); + }); +}); diff --git a/bot/embeds/templates/neverwinter/classesList.ts b/bot/embeds/templates/neverwinter/classesList.ts index 631b16b..a4a3fa9 100644 --- a/bot/embeds/templates/neverwinter/classesList.ts +++ b/bot/embeds/templates/neverwinter/classesList.ts @@ -1,39 +1,136 @@ // using native map or other functions causes serios pulumi serialization issues so values are hardcoded atm +export const enum ClassNames { + RANGER_DPS = "Ranger(DPS)", + PALADIN_TANK = "Paladin(Tank)", + PALADIN_HEAL = "Paladin(Heal)", + BARB_TANK = "Barbarian(Tank)", + BARB_DPS = "Barbarian(DPS)", + ROUGE_DPS = "Rouge(DPS)", + WIZARD_DPS = "Wizard(DPS)", + CLERIC_HEAL = "Cleric(Heal)", + CLERIC_DPS = "Cleric(DPS)", + BARD_DPS = "Bard(DPS)", + BARD_HEAL = "Bard(Heal)", + WARLOCK_DPS = "Warlock(DPS)", + WARLOCK_HEAL = "Warlock(Heal)", + FIGHTER_DPS = "Fighter(DPS)", + FIGHTER_TANK = "Fighter(TANK)", +} + export const NeverwinterClassesMap: [ string, { type: string; emoji: string } ][] = [ - ["Ranger(DPS)", { type: "DPS", emoji: "<:ranger:456150278975127553>" }], - ["Paladin(Tank)", { type: "TANK", emoji: "<:palatank:911695915637686382>" }], - ["Paladin(Heal)", { type: "HEAL", emoji: "<:palatank:911695915637686382>" }], - ["Barbarian(Tank)", { type: "TANK", emoji: "<:Ranger:922502874917904454>" }], - ["Barbarian(DPS)", { type: "DPS", emoji: "<:Ranger:922502874917904454>" }], - ["Rouge(DPS)", { type: "DPS", emoji: "<:Ranger:922502874917904454>" }], - ["Wizard(DPS)", { type: "DPS", emoji: "<:Ranger:922502874917904454>" }], - ["Cleric(Heal)", { type: "HEAL", emoji: "<:Ranger:922502874917904454>" }], - ["Cleric(DPS)", { type: "DPS", emoji: "<:Ranger:922502874917904454>" }], - ["Bard(DPS)", { type: "DPS", emoji: "<:Ranger:922502874917904454>" }], - ["Bard(Heal)", { type: "HEAL", emoji: "<:Ranger:922502874917904454>" }], - ["Warlock(DPS)", { type: "DPS", emoji: "<:Ranger:922502874917904454>" }], - ["Warlock(Heal)", { type: "HEAL", emoji: "<:Ranger:922502874917904454>" }], - ["Fighter(DPS)", { type: "DPS", emoji: "<:Ranger:922502874917904454>" }], - ["Fighter(Tank)", { type: "TANK", emoji: "<:Ranger:922502874917904454>" }], + [ + ClassNames.RANGER_DPS, + { type: "DPS", emoji: "<:ranger:456150278975127553>" }, + ], + [ + ClassNames.PALADIN_TANK, + { type: "TANK", emoji: "<:palatank:911695915637686382>" }, + ], + [ + ClassNames.PALADIN_HEAL, + { type: "HEAL", emoji: "<:palatank:911695915637686382>" }, + ], + [ + ClassNames.BARB_TANK, + { type: "TANK", emoji: "<:Ranger:922502874917904454>" }, + ], + [ClassNames.BARB_DPS, { type: "DPS", emoji: "<:Ranger:922502874917904454>" }], + [ + ClassNames.ROUGE_DPS, + { type: "DPS", emoji: "<:Ranger:922502874917904454>" }, + ], + [ + ClassNames.WIZARD_DPS, + { type: "DPS", emoji: "<:Ranger:922502874917904454>" }, + ], + [ + ClassNames.CLERIC_HEAL, + { type: "HEAL", emoji: "<:Ranger:922502874917904454>" }, + ], + [ + ClassNames.CLERIC_DPS, + { type: "DPS", emoji: "<:Ranger:922502874917904454>" }, + ], + [ClassNames.BARB_DPS, { type: "DPS", emoji: "<:Ranger:922502874917904454>" }], + [ + ClassNames.BARD_HEAL, + { type: "HEAL", emoji: "<:Ranger:922502874917904454>" }, + ], + [ + ClassNames.WARLOCK_DPS, + { type: "DPS", emoji: "<:Ranger:922502874917904454>" }, + ], + [ + ClassNames.WARLOCK_HEAL, + { type: "HEAL", emoji: "<:Ranger:922502874917904454>" }, + ], + [ + ClassNames.FIGHTER_DPS, + { type: "DPS", emoji: "<:Ranger:922502874917904454>" }, + ], + [ + ClassNames.FIGHTER_TANK, + { type: "TANK", emoji: "<:Ranger:922502874917904454>" }, + ], ]; export const getOptionsList = () => [ - { label: "Ranger(DPS)", value: "Ranger(DPS)", default: false }, - { label: "Wizard(DPS)", value: "Wizard(DPS)", default: false }, - { label: "Paladin(Tank)", value: "Paladin(Tank)", default: false }, - { label: "Paladin(Heal)", value: "Paladin(Heal)", default: false }, - { label: "Barbarian(Tank)", value: "Barbarian(Tank)", default: false }, - { label: "Barbarian(DPS)", value: "Barbarian(DPS)", default: false }, - { label: "Rouge(DPS)", value: "Rouge(DPS)", default: false }, - { label: "Cleric(Heal)", value: "Cleric(Heal)", default: false }, - { label: "Cleric(DPS)", value: "Cleric(DPS)", default: false }, - { label: "Bard(DPS)", value: "Bard(DPS)", default: false }, - { label: "Bard(Heal)", value: "Bard(Heal)", default: false }, - { label: "Warlock(DPS)", value: "Warlock(DPS)", default: false }, - { label: "Warlock(Heal)", value: "Warlock(Heal)", default: false }, - { label: "Fighter(DPS)", value: "Fighter(DPS)", default: false }, - { label: "Fighter(Tank)", value: "Fighter(Tank)", default: false }, + { + label: ClassNames.RANGER_DPS, + value: ClassNames.RANGER_DPS, + default: false, + }, + { + label: ClassNames.WIZARD_DPS, + value: ClassNames.WIZARD_DPS, + default: false, + }, + { + label: ClassNames.PALADIN_TANK, + value: ClassNames.PALADIN_TANK, + default: false, + }, + { + label: ClassNames.PALADIN_HEAL, + value: ClassNames.PALADIN_HEAL, + default: false, + }, + { label: ClassNames.BARB_TANK, value: ClassNames.BARB_TANK, default: false }, + { label: ClassNames.BARB_DPS, value: ClassNames.BARB_DPS, default: false }, + { label: ClassNames.ROUGE_DPS, value: ClassNames.ROUGE_DPS, default: false }, + { + label: ClassNames.CLERIC_HEAL, + value: ClassNames.CLERIC_HEAL, + default: false, + }, + { + label: ClassNames.CLERIC_DPS, + value: ClassNames.CLERIC_DPS, + default: false, + }, + { label: ClassNames.BARB_DPS, value: ClassNames.BARB_DPS, default: false }, + { label: ClassNames.BARD_HEAL, value: ClassNames.BARD_HEAL, default: false }, + { + label: ClassNames.WARLOCK_DPS, + value: ClassNames.WARLOCK_DPS, + default: false, + }, + { + label: ClassNames.WARLOCK_HEAL, + value: ClassNames.WARLOCK_HEAL, + default: false, + }, + { + label: ClassNames.FIGHTER_DPS, + value: ClassNames.FIGHTER_DPS, + default: false, + }, + { + label: ClassNames.FIGHTER_TANK, + value: ClassNames.FIGHTER_TANK, + default: false, + }, ]; diff --git a/bot/embeds/templates/neverwinter/tests/classesList.spec.ts b/bot/embeds/templates/neverwinter/tests/classesList.spec.ts new file mode 100644 index 0000000..8b5b15a --- /dev/null +++ b/bot/embeds/templates/neverwinter/tests/classesList.spec.ts @@ -0,0 +1,28 @@ +import { beforeEach, describe, expect, test, vi } from "vitest"; +import { getOptionsList, NeverwinterClassesMap, ClassNames } from "../classesList"; + +describe("Configs", () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.restoreAllMocks(); + vi.resetModules(); + }); + + test("getOptionsList", () => { + const classOptionsList = getOptionsList(); + expect(classOptionsList.length).toBe(15); + expect(classOptionsList).toBeInstanceOf(Array); + }); + + test("NeverwinterClassesMap", () => { + const [[className, { type , emoji }]] = NeverwinterClassesMap; + expect(NeverwinterClassesMap.length).toBe(15); + expect(NeverwinterClassesMap).toBeInstanceOf(Array); + expect(typeof className).toBe('string'); + expect(typeof type).toBe('string'); + }); + + test("ClassNames", () => { + expect(typeof ClassNames.BARB_DPS).toBe('string'); + }); +}); diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..ddff47c --- /dev/null +++ b/docs/README.md @@ -0,0 +1,94 @@ +# Introduction + +This is a simple discord bot buit to interact with some discord users. + +[![forthebadge](https://forthebadge.com/images/badges/contains-technical-debt.svg)](https://forthebadge.com) [![forthebadge](https://forthebadge.com/images/badges/it-works-why.svg)](https://forthebadge.com) + +## Built using + +[![Node][node.js]][node-url] +[![Typescript][typescript]][typescript-url] +[![Pulumi][pulumi]][pulumi-url] +[![AWS][aws]][pulumi-url] + +## Test coverage + +![](https://img.shields.io/badge/Coverage-86%25-83A603.svg?style=for-the-badge&logo=tsnode&logoColor=white&color=blue&label=Total&prefix=$coverage$) ![](https://img.shields.io/badge/Coverage-79%25-5A7302.svg?style=for-the-badge&logo=codereview&logoColor=white&color=blue&label=Statements&prefix=$statements$) ![](https://img.shields.io/badge/Coverage-94%25-83A603.svg?style=for-the-badge&logo=diagramsdotnet&logoColor=white&color=blue&label=Branches&prefix=$branches$) ![](https://img.shields.io/badge/Coverage-92%25-83A603.svg?style=for-the-badge&logo=awslambda&logoColor=white&color=blue&label=Functions&prefix=$functions$) ![](https://img.shields.io/badge/Coverage-79%25-5A7302.svg?style=for-the-badge&logo=codefactor&logoColor=white&color=blue&label=Lines&prefix=$lines$) + +## Architecture + +![Architecture](./_media/UglyBotArchitectureWhiteBg.png) + +## Prerequisites + +- Pulumi installed ([see instructions](https://www.pulumi.com/docs/get-started/aws/begin/)). +- Nodejs 16.x or latest installed [see instructions](https://nodejs.org/en/download/). +- An [AWS account](https://aws.amazon.com/). +- An [Discord account](https://discord.com/). +- A discord bot created on [Discord developer portal](https://discord.com/developers/applications) +- Git installed ([see instructions](https://github.com/git-guides/install-git)) + + +## Configuration + +You need to create an environment config in the following way. + +``` +DISCORD_TOKEN='yourDiscordToken' +DISCORD_PUBLIC_KEY='yourDiscordPublickey' +DISCORD_APPLICATION_ID='yourDiscordApplicationId' +DISCORD_SERVER_ID='yourDiscordServerId' +``` + +And save it as any or all of the following files within the folder `/environmentConfigs` + +``` +develop.env +production.env +lambdadevelop.env +``` + +Your default environment is `develop.env` and default deployed environment would be `lambdadevelop.env` + +## Running it locally. + +1. Clone this repo using SSH or Github Cli ([guide](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository)). +2. Navigate to the cloned repo/folder(uglyBot) using a terminal or shell and run the following. +3. `npm install` +4. `npm run build` +5. `npm run start` + +## Deploying and running it + +1. `cd pulumi` +2. `npm install` +3. `pulumi up` +4. Review and accept the deployment. (note that this will automatically create required services and resources in AWS lambda). +5. Copy the URL on the output `apiGatewayEndpointUrl` and append it with `discordEvents`. Example: `https://example.execute-api.us-east-1.amazonaws.com/stage/discordEvents` and set the `INTERACTIONS ENDPOINT URL` on your application to the URL you just constructed. +6. Add your discord bot to one of your servers. (make sure the server ID is the same as the one you specified on Configuration). +7. Try the command `/info` on your server. + +## Test coverage report generation + +`npm run coverage` + +## Update readme with latest coverage + +`npm run updateReadmeCoverage` + +## License + +Distributed under the MIT License. See LICENSE.txt for more information. + +## Contact + +Project Owner - [Dasith Kuruppu](https://github.com/DasithKuruppu) + +[node.js]: https://img.shields.io/badge/Nodejs-000000?style=for-the-badge&logo=node.js&logoColor=white +[node-url]: https://nodejs.org/ +[pulumi]: https://img.shields.io/badge/Pulumi-000000?style=for-the-badge&logo=pulumi&logoColor=white +[pulumi-url]: https://www.pulumi.com/ +[aws]: https://img.shields.io/badge/AWS-000000?style=for-the-badge&logo=amazonaws&logoColor=#232F3E +[aws-url]: https://nodejs.org/ +[typescript]: https://img.shields.io/badge/Typescript-000000?style=for-the-badge&logo=typescript&logoColor=white +[typescript-url]: https://typescript.org/