From 05d3dc3e9ea1cd5e51fd17549fe72fe8806a4191 Mon Sep 17 00:00:00 2001 From: XkijuX Date: Sat, 6 May 2023 21:12:58 +0200 Subject: [PATCH 01/12] Added test script and installed jest --- package.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package.json b/package.json index aab2c03..b44dbc2 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "Official Top.gg Node SDK", "main": "./dist/index.js", "scripts": { + "test": "jest --verbose", "build": "tsc", "build:ci": "npm i --include=dev && tsc", "docs": "typedoc", @@ -25,6 +26,7 @@ "devDependencies": { "@top-gg/eslint-config": "^0.0.3", "@types/express": "^4.17.17", + "@types/jest": "^29.5.1", "@types/node": "^18.15.5", "@typescript-eslint/eslint-plugin": "^5.56.0", "@typescript-eslint/parser": "^5.56.0", @@ -33,8 +35,11 @@ "eslint-plugin-jest": "^27.2.1", "express": "^4.18.2", "husky": "^8.0.3", + "jest": "^29.5.0", "lint-staged": "^13.2.0", + "msw": "^1.2.1", "prettier": "^2.8.6", + "ts-jest": "^29.1.0", "typedoc": "^0.23.28", "typescript": "^5.0.2" }, From 58098691aeb55887434cfe06c24b5dfcfdde21b2 Mon Sep 17 00:00:00 2001 From: XkijuX Date: Sat, 6 May 2023 21:14:00 +0200 Subject: [PATCH 02/12] Added mocks for API.ts --- tests/mocks/data.ts | 79 ++++++++++++++++++++++++++++++++++++++++ tests/mocks/endpoints.ts | 69 +++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 tests/mocks/data.ts create mode 100644 tests/mocks/endpoints.ts diff --git a/tests/mocks/data.ts b/tests/mocks/data.ts new file mode 100644 index 0000000..7f9e5bb --- /dev/null +++ b/tests/mocks/data.ts @@ -0,0 +1,79 @@ +// https://docs.top.gg/api/bot/#find-one-bot +export const BOT = { + "defAvatar": "6debd47ed13483642cf09e832ed0bc1b", + "invite": "", + "website": "https://discordbots.org", + "support": "KYZsaFb", + "github": "https://github.com/DiscordBotList/Luca", + "longdesc": "Luca only works in the **Discord Bot List** server. \r\nPrepend commands with the prefix `-` or `@Luca#1375`. \r\n**Please refrain from using these commands in non testing channels.**\r\n- `botinfo @bot` Shows bot info, title redirects to site listing.\r\n- `bots @user`* Shows all bots of that user, includes bots in the queue.\r\n- `owner / -owners @bot`* Shows all owners of that bot.\r\n- `prefix @bot`* Shows the prefix of that bot.\r\n* Mobile friendly version exists. Just add `noembed` to the end of the command.\r\n", + "shortdesc": "Luca is a bot for managing and informing members of the server", + "prefix": "- or @Luca#1375", + "lib": "discord.js", + "clientid": "264811613708746752", + "avatar": "7edcc4c6fbb0b23762455ca139f0e1c9", + "id": "264811613708746752", + "discriminator": "1375", + "username": "Luca", + "date": "2017-04-26T18:08:17.125Z", + "server_count": 2, + "guilds": ["417723229721853963", "264445053596991498"], + "shards": [], + "monthlyPoints": 19, + "points": 397, + "certifiedBot": false, + "owners": ["129908908096487424"], + "tags": ["Moderation", "Role Management", "Logging"], + "donatebotguildid": "" +} + +// https://docs.top.gg/api/bot/#search-bots +export const BOTS = { + limit: 0, + offset: 0, + count: 1, + total: 1, + results: [BOT], +} + +// https://docs.top.gg/api/bot/#last-1000-votes +export const VOTES = [ + { + "username": "Xetera", + "id": "140862798832861184", + "avatar": "a_1241439d430def25c100dd28add2d42f" + } + ] + +// https://docs.top.gg/api/bot/#bot-stats +export const BOT_STATS = { + server_count: 0, + shards: ['200'], + shard_count: 1 +} + +// https://docs.top.gg/api/bot/#individual-user-vote +export const USER_VOTE = { + "voted": 1 +} + +// https://docs.top.gg/api/user/#structure +export const USER = { + "discriminator": "0001", + "avatar": "a_1241439d430def25c100dd28add2d42f", + "id": "140862798832861184", + "username": "Xetera", + "defAvatar": "322c936a8c8be1b803cd94861bdfa868", + "admin": true, + "webMod": true, + "mod": true, + "certifiedDev": false, + "supporter": false, + "social": {} +} + +// Undocumented 😢 +export const WEEKEND = { + is_weekend: true +} + + \ No newline at end of file diff --git a/tests/mocks/endpoints.ts b/tests/mocks/endpoints.ts new file mode 100644 index 0000000..f12df68 --- /dev/null +++ b/tests/mocks/endpoints.ts @@ -0,0 +1,69 @@ +import { MockInterceptor } from 'undici/types/mock-interceptor'; +import { BOT, BOTS, BOT_STATS, USER, USER_VOTE, VOTES, WEEKEND } from './data'; +import { getIdInPath } from '../jest.setup'; + +export const endpoints = [ + { + pattern: '/api/bots', + method: 'GET', + data: BOTS, + requireAuth: true + }, + { + pattern: '/api/bots/:bot_id', + method: 'GET', + data: BOT, + requireAuth: true, + validate: (request: MockInterceptor.MockResponseCallbackOptions) => { + const bot_id = getIdInPath('/api/bots/:bot_id', request.path); + if (Number(bot_id) === 0) return { statusCode: 404 }; + return null + }, + }, + { + pattern: '/api/bots/:bot_id/votes', + method: 'GET', + data: VOTES, + requireAuth: true + }, + { + pattern: '/api/bots/:bot_id/stats', + method: 'GET', + data: BOT_STATS, + requireAuth: true, + validate: (request: MockInterceptor.MockResponseCallbackOptions) => { + const bot_id = getIdInPath('/api/bots/:bot_id/stats', request.path); + if (Number(bot_id) === 0) return { statusCode: 404 }; + return null + }, + }, + { + pattern: '/api/bots/:bot_id/check', + method: 'GET', + data: USER_VOTE, + requireAuth: true + }, + { + pattern: '/api/bots/:bot_id/stats', + method: 'POST', + requireAuth: true + }, + { + pattern: '/api/bots/stats', + method: 'POST', + data: {}, + requireAuth: true + }, // Undocumented + { + pattern: '/api/users/:user_id', + method: 'GET', + data: USER, + requireAuth: true, + validate: (request: MockInterceptor.MockResponseCallbackOptions) => { + const bot_id = getIdInPath('/api/users/:user_id', request.path); + if (Number(bot_id) === 0) return { statusCode: 404 }; + return null + }, + }, + { pattern: '/api/weekend', method: 'GET', data: WEEKEND, requireAuth: true }, +]; \ No newline at end of file From 28ed2eac80450374d95d1a67a896c5685faf1c0e Mon Sep 17 00:00:00 2001 From: XkijuX Date: Sat, 6 May 2023 21:14:17 +0200 Subject: [PATCH 03/12] Created tests for API.ts --- jest.config.js | 6 ++ tests/Api.test.ts | 135 ++++++++++++++++++++++++++++++++++++++++++++ tests/jest.setup.ts | 67 ++++++++++++++++++++++ tests/test.test.ts | 12 ++++ 4 files changed, 220 insertions(+) create mode 100644 jest.config.js create mode 100644 tests/Api.test.ts create mode 100644 tests/jest.setup.ts create mode 100644 tests/test.test.ts diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..fa04662 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,6 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + setupFilesAfterEnv: ['./tests/jest.setup.ts'] +}; \ No newline at end of file diff --git a/tests/Api.test.ts b/tests/Api.test.ts new file mode 100644 index 0000000..dc65bcc --- /dev/null +++ b/tests/Api.test.ts @@ -0,0 +1,135 @@ +import { Api } from '../src/index'; +import ApiError from '../src/utils/ApiError'; + +const is_owner = new Api('owner_token'); +const not_owner = new Api('not_owner_token'); +const no_token = new Api(''); + +describe('API postStats test', () => { + it('postStats should return 401 when no token is provided', async() => { + await expect(no_token.postStats({serverCount: 1, shardCount: 0})).rejects.toThrowError(ApiError); + }) + it('postStats without server count should throw error', async () => { + await expect(is_owner.postStats({shardCount: 0})).rejects.toThrowError(Error); + }) + it('postStats should return 401 when no token is provided', async () => { + await expect(no_token.postStats({serverCount: 1, shardCount: 0})).rejects.toThrowError(ApiError); + }) + + /* + TODO: Check for this is not added in code and api returns 400 + it('postStats with invalid negative server count should throw error', () => { + expect(is_owner.postStats({serverCount: -1, shardCount: 0})).rejects.toThrowError(Error); + }) + + TODO: Check for negative shardId is not added + it('postStats with invalid negative shardId should throw error', () => { + expect(is_owner.postStats({serverCount: 1, shardCount: 0, shardId: -1})).rejects.toThrowError(Error); + }) + + TODO: ShardId cannot be greater or equal to shardCount + it('postStats with shardId greater than shardCount should throw error', () => { + expect(is_owner.postStats({serverCount: 1, shardCount: 0, shardId: 1})).rejects.toThrowError(Error); + }) + + TODO: Check for negative shardCount is not added + it('postStats with invalid negative shardCount should throw error', () => { + expect(is_owner.postStats({serverCount: 1, shardCount: -1})).rejects.toThrowError(Error); + }) + + TODO: Check if shardCount is greater than 10000 + it('postStats with invalid shardCount should throw error', () => { + expect(is_owner.postStats({serverCount: 1, shardCount: 10001})).rejects.toThrowError(Error); + }) + */ + + it('postStats should return 403 when token is not owner of bot', async () => { + await expect(not_owner.postStats({serverCount: 1, shardCount: 0})).rejects.toThrowError(ApiError); + }) + + it('postStats should return 200 when token is owner of bot', async () => { + await expect(is_owner.postStats({serverCount: 1, shardCount: 1})).resolves.toBeInstanceOf(Object); + }) +}) + +describe('API getStats test', () => { + it('getStats should return 401 when no token is provided', () => { + expect(no_token.getStats('1')).rejects.toThrowError(ApiError); + }) + + it('getStats should return 404 when bot is not found', async() => { + await expect(is_owner.getStats('0')).rejects.toThrowError(ApiError); + }) + + it('getStats should return 200 when bot is found', async () => { + expect(is_owner.getStats('1')).toBeInstanceOf(Object); + }) + + it('getStats should throw when no id is provided', () => { + expect(is_owner.getStats('')).rejects.toThrowError(Error); + }) +}) + + +describe('API getBot test', () => { + it('getBot should return 401 when no token is provided', () => { + expect(no_token.getBot('1')).rejects.toThrowError(ApiError); + }) + it('getBot should return 404 when bot is not found', () => { + expect(is_owner.getBot('0')).rejects.toThrowError(ApiError); + }) + + it('getBot should return 200 when bot is found', async () => { + expect(is_owner.getBot('1')).toBeInstanceOf(Object); + }) + + it('getBot should throw when no id is provided', () => { + expect(is_owner.getBot('')).rejects.toThrowError(Error); + }) + +}) +describe('API getUser test', () => { + it('getUser should return 401 when no token is provided', () => { + expect(no_token.getUser('1')).rejects.toThrowError(ApiError); + }) + + it('getUser should return 404 when user is not found', () => { + expect(is_owner.getUser('0')).rejects.toThrowError(ApiError); + }) + + it('getUser should return 200 when user is found', async () => { + expect(is_owner.getUser('1')).toBeInstanceOf(Object); + }) + + it('getUser should throw when no id is provided', () => { + expect(is_owner.getUser('')).rejects.toThrowError(Error); + }) +}) + + +describe('API getVotes test', () => { + it('getVotes should return throw error when no token is provided', () => { + expect(no_token.getVotes()).rejects.toThrowError(Error); + }) + + it('getVotes should return 200 when token is provided', async () => { + expect(is_owner.getVotes()).toBeInstanceOf(Object); + }) +}); + +describe('API hasVoted test', () => { + it('hasVoted should throw error when no token is provided', () => { + expect(no_token.hasVoted('1')).rejects.toThrowError(Error); + }) + + it('hasVoted should return 200 when token is provided', async () => { + expect(is_owner.hasVoted('1')).toBeInstanceOf(Object); + }) + +}) + +describe('API isWeekend tests', () => { + it('isWeekend should return true', async () => { + expect(is_owner.isWeekend()).resolves.toBe(true) + }) +}); \ No newline at end of file diff --git a/tests/jest.setup.ts b/tests/jest.setup.ts new file mode 100644 index 0000000..68f4a69 --- /dev/null +++ b/tests/jest.setup.ts @@ -0,0 +1,67 @@ +import { Agent, MockAgent, setGlobalDispatcher } from 'undici'; +import { MockInterceptor } from 'undici/types/mock-interceptor'; +import { endpoints } from './mocks/endpoints'; + +interface IOptions { + pattern: string; + requireAuth?: boolean; + validate?: (request: MockInterceptor.MockResponseCallbackOptions) => void; +} + +export const getIdInPath = (pattern: string, url: string) => { + const regex = new RegExp(`^${pattern.replace(/:[^/]+/g, '([^/]+)')}$`); + const match = url.match(regex); + + return match ? match[1] : null; +} + +export const isMatchingPath = (pattern: string, url: string) => { + if (pattern === url) { + return true; + } + return getIdInPath(pattern, url) !== null; +} + +beforeEach(() => { + const mockAgent = new MockAgent() + mockAgent.disableNetConnect(); + const client = mockAgent.get('https://top.gg'); + + + const generateResponse = (request: MockInterceptor.MockResponseCallbackOptions, statusCode: number, data: any, headers = {}, options: IOptions) => { + const reuqestHeaders = request.headers as any; + + // Check if token is avaliable + if (options.requireAuth && (!reuqestHeaders['authorization'] || reuqestHeaders['authorization'] == '')) return { statusCode: 401 }; + + // Check that user is owner of bot + if (options.requireAuth && reuqestHeaders['authorization'] !== 'owner_token') return { statusCode: 403 } + + const error = options.validate?.(request); + if (error) return error; + + return { + statusCode, + data: JSON.stringify(data), + responseOptions: { + headers: { 'content-type': 'application/json', ...headers }, + } + } + } + + endpoints.forEach(({ pattern, method, data, requireAuth, validate }) => { + client.intercept({ + path: (path) => isMatchingPath(pattern, path), + method, + }).reply((request) => {return generateResponse(request, 200, data, {}, { pattern, requireAuth, validate: validate })}); + }) + + client.intercept({ + path: (path) => !endpoints.some(({ pattern }) => isMatchingPath(pattern, path)), + method: (_) => true, + }).reply((request) => { + throw Error(`No endpoint found for ${request.method} ${request.path}`) + }) + + setGlobalDispatcher(mockAgent); +}) \ No newline at end of file diff --git a/tests/test.test.ts b/tests/test.test.ts new file mode 100644 index 0000000..d10dcca --- /dev/null +++ b/tests/test.test.ts @@ -0,0 +1,12 @@ +import { Api } from '../src/index'; +import ApiError from '../src/utils/ApiError'; + +describe('API isWeekend tests', () => { + it('isWeekend should return true', async () => { + const api = new Api('owner_token') + + const isWeekend = await api.isWeekend(); + + expect(isWeekend).toBe(true) + }) +}) \ No newline at end of file From 563d63f52c811b33fa910448d083f5d4b6c4f1d3 Mon Sep 17 00:00:00 2001 From: XkijuX Date: Sat, 6 May 2023 21:47:04 +0200 Subject: [PATCH 04/12] Added test coverage and fixed tests --- package.json | 1 + tests/Api.test.ts | 20 ++++++---- tests/jest.setup.ts | 18 +++++++-- tests/mocks/data.ts | 85 +++++++++++++++++++++------------------- tests/mocks/endpoints.ts | 15 ++++++- 5 files changed, 84 insertions(+), 55 deletions(-) diff --git a/package.json b/package.json index b44dbc2..a080716 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "./dist/index.js", "scripts": { "test": "jest --verbose", + "test:coverage": "jest --coverage", "build": "tsc", "build:ci": "npm i --include=dev && tsc", "docs": "typedoc", diff --git a/tests/Api.test.ts b/tests/Api.test.ts index dc65bcc..66df02d 100644 --- a/tests/Api.test.ts +++ b/tests/Api.test.ts @@ -1,3 +1,4 @@ +import { resolve } from 'path'; import { Api } from '../src/index'; import ApiError from '../src/utils/ApiError'; @@ -62,7 +63,7 @@ describe('API getStats test', () => { }) it('getStats should return 200 when bot is found', async () => { - expect(is_owner.getStats('1')).toBeInstanceOf(Object); + expect(is_owner.getStats('1')).resolves.toBeInstanceOf(Object); }) it('getStats should throw when no id is provided', () => { @@ -80,7 +81,7 @@ describe('API getBot test', () => { }) it('getBot should return 200 when bot is found', async () => { - expect(is_owner.getBot('1')).toBeInstanceOf(Object); + expect(is_owner.getBot('1')).resolves.toBeInstanceOf(Object); }) it('getBot should throw when no id is provided', () => { @@ -98,7 +99,7 @@ describe('API getUser test', () => { }) it('getUser should return 200 when user is found', async () => { - expect(is_owner.getUser('1')).toBeInstanceOf(Object); + expect(is_owner.getUser('1')).resolves.toBeInstanceOf(Object); }) it('getUser should throw when no id is provided', () => { @@ -112,8 +113,8 @@ describe('API getVotes test', () => { expect(no_token.getVotes()).rejects.toThrowError(Error); }) - it('getVotes should return 200 when token is provided', async () => { - expect(is_owner.getVotes()).toBeInstanceOf(Object); + it('getVotes should return 200 when token is provided', () => { + expect(is_owner.getVotes()).resolves.toBeInstanceOf(Object); }) }); @@ -122,10 +123,13 @@ describe('API hasVoted test', () => { expect(no_token.hasVoted('1')).rejects.toThrowError(Error); }) - it('hasVoted should return 200 when token is provided', async () => { - expect(is_owner.hasVoted('1')).toBeInstanceOf(Object); + it('hasVoted should return 200 when token is provided', () => { + expect(is_owner.hasVoted('1')).resolves.toBe(true); + }) + + it('hasVoted should throw error when no id is provided', () => { + expect(is_owner.hasVoted('')).rejects.toThrowError(Error); }) - }) describe('API isWeekend tests', () => { diff --git a/tests/jest.setup.ts b/tests/jest.setup.ts index 68f4a69..4744d58 100644 --- a/tests/jest.setup.ts +++ b/tests/jest.setup.ts @@ -16,9 +16,18 @@ export const getIdInPath = (pattern: string, url: string) => { } export const isMatchingPath = (pattern: string, url: string) => { + // Remove query params + url = url.split("?")[0] + if (pattern === url) { return true; } + + // Check if there is an exact match + if(endpoints.some(({ pattern }) => pattern === url)) { + return false + }; + return getIdInPath(pattern, url) !== null; } @@ -29,17 +38,18 @@ beforeEach(() => { const generateResponse = (request: MockInterceptor.MockResponseCallbackOptions, statusCode: number, data: any, headers = {}, options: IOptions) => { - const reuqestHeaders = request.headers as any; + const requestHeaders = request.headers as any; // Check if token is avaliable - if (options.requireAuth && (!reuqestHeaders['authorization'] || reuqestHeaders['authorization'] == '')) return { statusCode: 401 }; + if (options.requireAuth && (!requestHeaders['authorization'] || requestHeaders['authorization'] == '')) return { statusCode: 401 }; // Check that user is owner of bot - if (options.requireAuth && reuqestHeaders['authorization'] !== 'owner_token') return { statusCode: 403 } + if (options.requireAuth && requestHeaders['authorization'] !== 'owner_token') return { statusCode: 403 } const error = options.validate?.(request); if (error) return error; - + + console.log(request.path, data) return { statusCode, data: JSON.stringify(data), diff --git a/tests/mocks/data.ts b/tests/mocks/data.ts index 7f9e5bb..fc3bd6b 100644 --- a/tests/mocks/data.ts +++ b/tests/mocks/data.ts @@ -1,59 +1,59 @@ // https://docs.top.gg/api/bot/#find-one-bot export const BOT = { - "defAvatar": "6debd47ed13483642cf09e832ed0bc1b", - "invite": "", - "website": "https://discordbots.org", - "support": "KYZsaFb", - "github": "https://github.com/DiscordBotList/Luca", - "longdesc": "Luca only works in the **Discord Bot List** server. \r\nPrepend commands with the prefix `-` or `@Luca#1375`. \r\n**Please refrain from using these commands in non testing channels.**\r\n- `botinfo @bot` Shows bot info, title redirects to site listing.\r\n- `bots @user`* Shows all bots of that user, includes bots in the queue.\r\n- `owner / -owners @bot`* Shows all owners of that bot.\r\n- `prefix @bot`* Shows the prefix of that bot.\r\n* Mobile friendly version exists. Just add `noembed` to the end of the command.\r\n", - "shortdesc": "Luca is a bot for managing and informing members of the server", - "prefix": "- or @Luca#1375", - "lib": "discord.js", - "clientid": "264811613708746752", - "avatar": "7edcc4c6fbb0b23762455ca139f0e1c9", - "id": "264811613708746752", - "discriminator": "1375", - "username": "Luca", - "date": "2017-04-26T18:08:17.125Z", - "server_count": 2, - "guilds": ["417723229721853963", "264445053596991498"], - "shards": [], - "monthlyPoints": 19, - "points": 397, - "certifiedBot": false, - "owners": ["129908908096487424"], - "tags": ["Moderation", "Role Management", "Logging"], - "donatebotguildid": "" + "defAvatar": "6debd47ed13483642cf09e832ed0bc1b", + "invite": "", + "website": "https://discordbots.org", + "support": "KYZsaFb", + "github": "https://github.com/DiscordBotList/Luca", + "longdesc": "Luca only works in the **Discord Bot List** server. \r\nPrepend commands with the prefix `-` or `@Luca#1375`. \r\n**Please refrain from using these commands in non testing channels.**\r\n- `botinfo @bot` Shows bot info, title redirects to site listing.\r\n- `bots @user`* Shows all bots of that user, includes bots in the queue.\r\n- `owner / -owners @bot`* Shows all owners of that bot.\r\n- `prefix @bot`* Shows the prefix of that bot.\r\n* Mobile friendly version exists. Just add `noembed` to the end of the command.\r\n", + "shortdesc": "Luca is a bot for managing and informing members of the server", + "prefix": "- or @Luca#1375", + "lib": "discord.js", + "clientid": "264811613708746752", + "avatar": "7edcc4c6fbb0b23762455ca139f0e1c9", + "id": "264811613708746752", + "discriminator": "1375", + "username": "Luca", + "date": "2017-04-26T18:08:17.125Z", + "server_count": 2, + "guilds": ["417723229721853963", "264445053596991498"], + "shards": [], + "monthlyPoints": 19, + "points": 397, + "certifiedBot": false, + "owners": ["129908908096487424"], + "tags": ["Moderation", "Role Management", "Logging"], + "donatebotguildid": "" } // https://docs.top.gg/api/bot/#search-bots export const BOTS = { - limit: 0, - offset: 0, - count: 1, - total: 1, - results: [BOT], + limit: 0, + offset: 0, + count: 1, + total: 1, + results: [BOT], } // https://docs.top.gg/api/bot/#last-1000-votes export const VOTES = [ - { - "username": "Xetera", - "id": "140862798832861184", - "avatar": "a_1241439d430def25c100dd28add2d42f" - } - ] + { + "username": "Xetera", + "id": "140862798832861184", + "avatar": "a_1241439d430def25c100dd28add2d42f" + } +] // https://docs.top.gg/api/bot/#bot-stats export const BOT_STATS = { - server_count: 0, - shards: ['200'], - shard_count: 1 + server_count: 0, + shards: ['200'], + shard_count: 1 } // https://docs.top.gg/api/bot/#individual-user-vote export const USER_VOTE = { - "voted": 1 + "voted": 1 } // https://docs.top.gg/api/user/#structure @@ -71,9 +71,12 @@ export const USER = { "social": {} } +export const USER_VOTE_CHECK = { + voted: 1 +} + // Undocumented 😢 export const WEEKEND = { is_weekend: true } - - \ No newline at end of file + diff --git a/tests/mocks/endpoints.ts b/tests/mocks/endpoints.ts index f12df68..637d7bf 100644 --- a/tests/mocks/endpoints.ts +++ b/tests/mocks/endpoints.ts @@ -1,5 +1,5 @@ import { MockInterceptor } from 'undici/types/mock-interceptor'; -import { BOT, BOTS, BOT_STATS, USER, USER_VOTE, VOTES, WEEKEND } from './data'; +import { BOT, BOTS, BOT_STATS, USER, USER_VOTE, USER_VOTE_CHECK, VOTES, WEEKEND } from './data'; import { getIdInPath } from '../jest.setup'; export const endpoints = [ @@ -65,5 +65,16 @@ export const endpoints = [ return null }, }, - { pattern: '/api/weekend', method: 'GET', data: WEEKEND, requireAuth: true }, + { + pattern: '/api/bots/check', + method: 'GET', + data: USER_VOTE_CHECK, + requireAuth: true + }, + { + pattern: '/api/weekend', + method: 'GET', + data: WEEKEND, + requireAuth: true + }, ]; \ No newline at end of file From a53e8aef5bb267353b567a9d17c42980f3819012 Mon Sep 17 00:00:00 2001 From: XkijuX Date: Sat, 6 May 2023 22:04:46 +0200 Subject: [PATCH 05/12] Fixed endpoints --- tests/Api.test.ts | 13 +++++++++---- tests/mocks/endpoints.ts | 6 ++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/Api.test.ts b/tests/Api.test.ts index 66df02d..8680df0 100644 --- a/tests/Api.test.ts +++ b/tests/Api.test.ts @@ -1,6 +1,7 @@ import { resolve } from 'path'; import { Api } from '../src/index'; import ApiError from '../src/utils/ApiError'; +import { BOT, BOT_STATS, USER, VOTES } from './mocks/data'; const is_owner = new Api('owner_token'); const not_owner = new Api('not_owner_token'); @@ -63,7 +64,11 @@ describe('API getStats test', () => { }) it('getStats should return 200 when bot is found', async () => { - expect(is_owner.getStats('1')).resolves.toBeInstanceOf(Object); + expect(is_owner.getStats('1')).resolves.toStrictEqual({ + serverCount: BOT_STATS.server_count, + shardCount: BOT_STATS.shard_count, + shards: BOT_STATS.shards + }); }) it('getStats should throw when no id is provided', () => { @@ -81,7 +86,7 @@ describe('API getBot test', () => { }) it('getBot should return 200 when bot is found', async () => { - expect(is_owner.getBot('1')).resolves.toBeInstanceOf(Object); + expect(is_owner.getBot('1')).resolves.toStrictEqual(BOT); }) it('getBot should throw when no id is provided', () => { @@ -99,7 +104,7 @@ describe('API getUser test', () => { }) it('getUser should return 200 when user is found', async () => { - expect(is_owner.getUser('1')).resolves.toBeInstanceOf(Object); + expect(is_owner.getUser('1')).resolves.toStrictEqual(USER); }) it('getUser should throw when no id is provided', () => { @@ -114,7 +119,7 @@ describe('API getVotes test', () => { }) it('getVotes should return 200 when token is provided', () => { - expect(is_owner.getVotes()).resolves.toBeInstanceOf(Object); + expect(is_owner.getVotes()).resolves.toEqual(VOTES); }) }); diff --git a/tests/mocks/endpoints.ts b/tests/mocks/endpoints.ts index 637d7bf..1919c0a 100644 --- a/tests/mocks/endpoints.ts +++ b/tests/mocks/endpoints.ts @@ -26,6 +26,12 @@ export const endpoints = [ data: VOTES, requireAuth: true }, + { + pattern: '/api/bots/votes', + method: 'GET', + data: VOTES, + requireAuth: true + }, // Undocumented { pattern: '/api/bots/:bot_id/stats', method: 'GET', From 835972f5e921bc351679524877a9ef47d3230c49 Mon Sep 17 00:00:00 2001 From: XkijuX Date: Sat, 6 May 2023 22:05:26 +0200 Subject: [PATCH 06/12] removed console.log --- tests/jest.setup.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/jest.setup.ts b/tests/jest.setup.ts index 4744d58..29ecdf2 100644 --- a/tests/jest.setup.ts +++ b/tests/jest.setup.ts @@ -49,7 +49,6 @@ beforeEach(() => { const error = options.validate?.(request); if (error) return error; - console.log(request.path, data) return { statusCode, data: JSON.stringify(data), From 426457ef413248563482d0dee37dd6c4ad09276d Mon Sep 17 00:00:00 2001 From: XkijuX Date: Sun, 7 May 2023 16:54:24 +0200 Subject: [PATCH 07/12] Added a test workflow --- .github/workflows/test.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..2ee828a --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,20 @@ +name: Jest Tests + +on: + push: + branches: + - main + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v2 + with: + node-version: '14.x' + - name: Install Dependencies + run: npm install + - name: Run Jest tests + run: npm run test \ No newline at end of file From 02074af8ad81d4cd074cd811296859a5dcf3e0bb Mon Sep 17 00:00:00 2001 From: XkijuX Date: Sun, 7 May 2023 16:56:10 +0200 Subject: [PATCH 08/12] Changed main branch to master and added workflow for pull requests --- .github/workflows/test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2ee828a..6b82806 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,7 +3,8 @@ name: Jest Tests on: push: branches: - - main + - master + pull_request: jobs: test: From ccf05a722bb8d9e91db4d94ba9d903a6ea606725 Mon Sep 17 00:00:00 2001 From: XkijuX Date: Sun, 7 May 2023 16:57:12 +0200 Subject: [PATCH 09/12] Changed node version to 18.x --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6b82806..4d11e3f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v2 with: - node-version: '14.x' + node-version: '18.x' - name: Install Dependencies run: npm install - name: Run Jest tests From 3f8ba5fc4848d7b710ac8a8415f7dd4bd705511c Mon Sep 17 00:00:00 2001 From: XkijuX Date: Sun, 7 May 2023 17:06:54 +0200 Subject: [PATCH 10/12] Cleaned code --- tests/jest.setup.ts | 2 +- tests/test.test.ts | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) delete mode 100644 tests/test.test.ts diff --git a/tests/jest.setup.ts b/tests/jest.setup.ts index 29ecdf2..7145c22 100644 --- a/tests/jest.setup.ts +++ b/tests/jest.setup.ts @@ -1,4 +1,4 @@ -import { Agent, MockAgent, setGlobalDispatcher } from 'undici'; +import { MockAgent, setGlobalDispatcher } from 'undici'; import { MockInterceptor } from 'undici/types/mock-interceptor'; import { endpoints } from './mocks/endpoints'; diff --git a/tests/test.test.ts b/tests/test.test.ts deleted file mode 100644 index d10dcca..0000000 --- a/tests/test.test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Api } from '../src/index'; -import ApiError from '../src/utils/ApiError'; - -describe('API isWeekend tests', () => { - it('isWeekend should return true', async () => { - const api = new Api('owner_token') - - const isWeekend = await api.isWeekend(); - - expect(isWeekend).toBe(true) - }) -}) \ No newline at end of file From e7ab45cd1510c20c8307f2b2b7e0858ccd7a3d3b Mon Sep 17 00:00:00 2001 From: XkijuX Date: Sun, 7 May 2023 17:07:22 +0200 Subject: [PATCH 11/12] Removed unused import --- tests/Api.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Api.test.ts b/tests/Api.test.ts index 8680df0..04000db 100644 --- a/tests/Api.test.ts +++ b/tests/Api.test.ts @@ -1,4 +1,3 @@ -import { resolve } from 'path'; import { Api } from '../src/index'; import ApiError from '../src/utils/ApiError'; import { BOT, BOT_STATS, USER, VOTES } from './mocks/data'; From 84e95eb137454fa4a65a705eed936a1ca40aed22 Mon Sep 17 00:00:00 2001 From: XkijuX Date: Sun, 7 May 2023 17:15:16 +0200 Subject: [PATCH 12/12] Removed msw --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index a080716..a9efca3 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "husky": "^8.0.3", "jest": "^29.5.0", "lint-staged": "^13.2.0", - "msw": "^1.2.1", "prettier": "^2.8.6", "ts-jest": "^29.1.0", "typedoc": "^0.23.28",