From fc80cd0976200b1e7d940be026ba85e3ef9b8b1e Mon Sep 17 00:00:00 2001 From: vn7n24fzkq Date: Sun, 30 Aug 2020 02:37:31 +0800 Subject: [PATCH] Add api tests --- package-lock.json | 18 +++ package.json | 1 + src/app.js | 2 +- src/github-api/profile-details.js | 60 ++++---- .../{langs.js => repos-per-language.js} | 58 ++++---- tests/github-api/profile-details.test.js | 108 ++++++++++++++ tests/github-api/repos-per-language.test.js | 140 ++++++++++++++++++ 7 files changed, 320 insertions(+), 67 deletions(-) rename src/github-api/{langs.js => repos-per-language.js} (54%) create mode 100644 tests/github-api/profile-details.test.js create mode 100644 tests/github-api/repos-per-language.test.js diff --git a/package-lock.json b/package-lock.json index 763c7c040..07002cb12 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1070,6 +1070,24 @@ "follow-redirects": "1.5.10" } }, + "axios-mock-adapter": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-1.18.2.tgz", + "integrity": "sha512-e5aTsPy2Viov22zNpFTlid76W1Scz82pXeEwwCXdtO85LROhHAF8pHF2qDhiyMONLxKyY3lQ+S4UCsKgrlx8Hw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "is-buffer": "^2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true + } + } + }, "babel-jest": { "version": "26.3.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.3.0.tgz", diff --git a/package.json b/package.json index 5c87bff29..5f259a3a7 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "number-abbreviate": "^2.0.0" }, "devDependencies": { + "axios-mock-adapter": "^1.18.2", "jest": "^26.4.2", "pre-commit": "^1.2.2" }, diff --git a/src/app.js b/src/app.js index 25b5f044c..346e65fa2 100644 --- a/src/app.js +++ b/src/app.js @@ -4,7 +4,7 @@ const core = require("@actions/core"); const { spawn } = require("child_process"); const Themes = require("./const/theme"); const Icons = require("./const/icon"); -const getRepoLanguage = require("./github-api/langs"); +const getRepoLanguage = require("./github-api/repos-per-language"); const getProfileDetails = require("./github-api/profile-details"); const {writeSVG,outputPath} = require("./utils/svg-writer"); const createDonutChartCard = require("./templates/donut-chart-card"); diff --git a/src/github-api/profile-details.js b/src/github-api/profile-details.js index 98a8d42a2..6af17c0a0 100644 --- a/src/github-api/profile-details.js +++ b/src/github-api/profile-details.js @@ -32,6 +32,7 @@ const fetcher = (token, variables) => { totalPullRequestContributions totalPullRequestReviewContributions contributionCalendar { + totalContributions weeks { contributionDays { contributionCount @@ -39,9 +40,6 @@ const fetcher = (token, variables) => { } } } - contributionCalendar { - totalContributions - } } } } @@ -52,50 +50,46 @@ const fetcher = (token, variables) => { ); }; -//repos per language async function getProfileDetails(username) { let result = { name: "", email: "", joinedAt: "", + company: null, + websiteUrl: null, + twitterUsername: null, + location: null, totalContributions: 0, totalPublicRepos: 0, contributions: [], }; - try { - let res = await fetcher(githubToken, { - login: username, - }); + let res = await fetcher(githubToken, { + login: username, + }); - if (res.data.errors) { - throw Error(res.data.errors[0].message || "Github api fail"); - } + if (res.data.errors) { + throw Error(res.data.errors[0].message || "Github api failed"); + } - let user = res.data.data.user; + let user = res.data.data.user; - result.name = user.name; - result.email = user.email; - result.joinedAt = user.createdAt; - result.totalContributions = - user.contributionsCollection.contributionCalendar.totalContributions; - result.totalPublicRepos = user.repositories.totalCount; - result.websiteUrl = user.websiteUrl; - result.company = user.company; - result.location = user.location; + result.name = user.name; + result.email = user.email; + result.joinedAt = user.createdAt; + result.totalContributions = + user.contributionsCollection.contributionCalendar.totalContributions; + result.totalPublicRepos = user.repositories.totalCount; + result.websiteUrl = user.websiteUrl; + result.company = user.company; + result.location = user.location; + result.twitterUsername = user.twitterUsername; - //contributions into array - for (let week of user.contributionsCollection.contributionCalendar.weeks) { - for (let day of week.contributionDays) { - day.date = new Date(day.date); - result.contributions.push(day); - } - } - } catch (e) { - if (e.response) { - console.log(e.response.data); - } else { - console.log(e); + //contributions into array + for (let week of user.contributionsCollection.contributionCalendar.weeks) { + for (let day of week.contributionDays) { + day.date = new Date(day.date); + result.contributions.push(day); } } diff --git a/src/github-api/langs.js b/src/github-api/repos-per-language.js similarity index 54% rename from src/github-api/langs.js rename to src/github-api/repos-per-language.js index ece6af49a..d09756fd7 100644 --- a/src/github-api/langs.js +++ b/src/github-api/repos-per-language.js @@ -46,44 +46,36 @@ async function getRepoLanguage(username) { let languageMap = new Map(); let nodes = []; - try { - while (hasNextPage) { - let res = await fetcher(githubToken, { - login: username, - endCursor: cursor, - }); + while (hasNextPage) { + let res = await fetcher(githubToken, { + login: username, + endCursor: cursor, + }); - if (res.data.errors) { - throw Error(res.data.errors[0].message || "Github api fail"); - } - cursor = res.data.data.user.repositories.pageInfo.endCursor; - hasNextPage = res.data.data.user.repositories.pageInfo.hasNextPage; - nodes.push(...res.data.data.user.repositories.nodes); + if (res.data.errors) { + throw Error(res.data.errors[0].message || "Github api fail"); } + cursor = res.data.data.user.repositories.pageInfo.endCursor; + hasNextPage = res.data.data.user.repositories.pageInfo.hasNextPage; + nodes.push(...res.data.data.user.repositories.nodes); + } - nodes.forEach((node) => { - if (node.languages.edges.length > 0) { - let edge = node.languages.edges[0]; - let langName = edge.node.name; - if (languageMap.has(langName)) { - let lang = languageMap.get(langName); - lang.count += 1; - languageMap.set(langName, lang); - } else { - languageMap.set(langName, { - count: 1, - color: edge.node.color == null ? "#586e75" : edge.node.color, - }); - } + nodes.forEach((node) => { + if (node.languages.edges.length > 0) { + let edge = node.languages.edges[0]; + let langName = edge.node.name; + if (languageMap.has(langName)) { + let lang = languageMap.get(langName); + lang.count += 1; + languageMap.set(langName, lang); + } else { + languageMap.set(langName, { + count: 1, + color: edge.node.color == null ? "#586e75" : edge.node.color, + }); } - }); - } catch (e) { - if (e.response) { - console.log(e.response.data); - } else { - console.log(e); } - } + }); return languageMap; } diff --git a/tests/github-api/profile-details.test.js b/tests/github-api/profile-details.test.js new file mode 100644 index 000000000..d60c5897a --- /dev/null +++ b/tests/github-api/profile-details.test.js @@ -0,0 +1,108 @@ +const getProfileDetails = require("../../src/github-api/profile-details"); +const axios = require("axios"); +const MockAdapter = require("axios-mock-adapter"); +const mock = new MockAdapter(axios); + +const data = { + data: { + user: { + name: "vn7", + email: "vn7n24fzkq@gmail.com", + createdAt: "2016-07-01T10:46:25Z", + twitterUsername: null, + company: "vn7", + location: "Taiwan", + websiteUrl: null, + repositories: { + totalCount: 30, + }, + contributionsCollection: { + totalIssueContributions: 10, + totalCommitContributions: 20, + totalRepositoryContributions: 30, + totalPullRequestContributions: 40, + totalPullRequestReviewContributions: 50, + contributionCalendar: { + totalContributions: 1030, + weeks: [ + { + contributionDays: [ + { + date: "2019-09-06T00:00:00.000+00:00", + contributionCount: 20, + }, + { + date: "2019-09-07T00:00:00.000+00:00", + contributionCount: 10, + }, + ], + }, + { + contributionDays: [ + { + date: "2020-01-12T00:00:00.000+00:00", + contributionCount: 5, + }, + ], + }, + ], + }, + }, + }, + }, +}; + +const error = { + errors: [ + { + type: "NOT_FOUND", + path: ["user"], + locations: [], + message: "Github api failed", + }, + ], +}; + +afterEach(() => { + mock.reset(); +}); + +describe("github api for profile details", () => { + it("should get correct profile data", async () => { + mock.onPost("https://api.github.com/graphql").reply(200, data); + let profileDetails = await getProfileDetails("vn7n24fzkq"); + expect(profileDetails).toStrictEqual({ + name: "vn7", + email: "vn7n24fzkq@gmail.com", + joinedAt: "2016-07-01T10:46:25Z", + company: "vn7", + location: "Taiwan", + websiteUrl: null, + twitterUsername: null, + totalContributions: 1030, + totalPublicRepos: 30, + contributions: [ + { + date: new Date("2019-09-06T00:00:00.000+00:00"), + contributionCount: 20, + }, + { + date: new Date("2019-09-07T00:00:00.000+00:00"), + contributionCount: 10, + }, + { + date: new Date("2020-01-12T00:00:00.000+00:00"), + contributionCount: 5, + }, + ], + }); + }); + + it("should throw error when api failed", async () => { + mock.onPost("https://api.github.com/graphql").reply(200, error); + await expect(getProfileDetails("vn7n24fzkq")).rejects.toThrow( + "Github api failed" + ); + }); +}); + diff --git a/tests/github-api/repos-per-language.test.js b/tests/github-api/repos-per-language.test.js new file mode 100644 index 000000000..40eb6fd2d --- /dev/null +++ b/tests/github-api/repos-per-language.test.js @@ -0,0 +1,140 @@ +const getRepoLanguage = require("../../src/github-api/repos-per-language"); +const axios = require("axios"); +const MockAdapter = require("axios-mock-adapter"); +const mock = new MockAdapter(axios); + +const firstData = { + data: { + user: { + repositories: { + nodes: [ + { + languages: { + edges: [ + { + size: 2072951, + node: { + color: "#b07219", + name: "Java", + }, + }, + { + size: 2600, + node: { + color: "#e34c26", + name: "Kotlin", + }, + }, + ], + }, + }, + { + languages: { + edges: [ + { + size: 10485, + node: { + color: "#b07219", + name: "Rust", + }, + }, + ], + }, + }, + ], + pageInfo: { + endCursor: "ABCD29yOnYyOpHOBslODA==", + hasNextPage: true, + }, + }, + }, + }, +}; +const lastData = { + data: { + user: { + repositories: { + nodes: [ + { + languages: { + edges: [ + { + size: 2072951, + node: { + color: "#b07219", + name: "Java", + }, + }, + { + size: 2600, + node: { + color: "#e34c26", + name: "Java", + }, + }, + ], + }, + }, + { + languages: { + edges: [ + { + size: 10485, + node: { + color: "#b07219", + name: "Kotlin", + }, + }, + ], + }, + }, + ], + pageInfo: { + endCursor: null, + hasNextPage: false, + }, + }, + }, + }, +}; + +const error = { + errors: [ + { + type: "NOT_FOUND", + path: ["user"], + locations: [], + message: "Github api failed", + }, + ], +}; + +afterEach(() => { + mock.reset(); +}); + +describe("github api for repos per language", () => { + it("should get correct data", async () => { + mock + .onPost("https://api.github.com/graphql") + .replyOnce(200, firstData) + .onPost("https://api.github.com/graphql") + .replyOnce(200, lastData) + .onAny(); + let repoData = await getRepoLanguage("vn7n24fzkq"); + expect(repoData).toEqual( + new Map([ + ["Java", { color: "#b07219", count: 2 }], + ["Rust", { color: "#b07219", count: 1 }], + ["Kotlin", { color: "#b07219", count: 1 }], + ]) + ); + }); + + it("should throw error when api failed", async () => { + mock.onPost("https://api.github.com/graphql").reply(200, error); + await expect(getRepoLanguage("vn7n24fzkq")).rejects.toThrow( + "Github api failed" + ); + }); +});